Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Unity SDK

com.openplay.sdk, Unity’den Open Play’e bağlanan C# istemcisidir: misafir ve e-posta/parola oturumu, oturumun yeniden başlatmalar arasında geri yüklenmesi, eklenti komutları ve sorguları ve gerçek zamanlı soket. Bu sayfa kurulumu, kullanımı ve neyin doğrulandığını dürüstçe anlatır.

Uyarı

Paket yalnız Unity 6000.6.7f1 ile doğrulanmıştır; başka editör sürümleri ve çoğu platform doğrulanmadı (Doğrulanan platformlar). Bu belge paket sürümü 0.1.0 içindir.

API başvurusu: C# tiplerinin üretilmiş başvurusu https://open-play.b4klabs.dev/docs/sdk/unity/ adresindedir.

Kurulum

Paket, https://npm.pkg.github.com/@ferdiunal adresindeki GitHub Packages npm kayıt defterinden gelir. Paket adı kapsamsızdır (com.openplay.sdk); kapsam kayıt defteri adresindedir.

  1. Kimlik. GitHub herkese açık paketlerde bile belirteç ister. Kullanıcı klasörünüzde ~/.upmconfig.toml oluşturun. Belirteç read:packages yetkili bir klasik belirteçtir (ince ayarlı belirteç denenmedi) ve bir sırdır: depoya koymayın, günlüğe yazmayın.

    [npmAuth."https://npm.pkg.github.com/@ferdiunal"]
    token = "<read:packages yetkili belirteç>"
    alwaysAuth = true
    
  2. Manifest. Oyun projenizin Packages/manifest.json dosyasına kapsamlı kayıt defterini ve bağımlılığı ekleyin:

    {
      "dependencies": { "com.openplay.sdk": "0.1.0" },
      "scopedRegistries": [
        { "name": "Open Play", "url": "https://npm.pkg.github.com/@ferdiunal", "scopes": ["com.openplay"] }
      ]
    }
    
  3. Unity’yi açın. İki bilinen davranış: Package Manager’ın arama ekranında paket görünmez (GitHub’ın arama uç noktası 405 döner; paketi manifest.json’a elle yazarsınız) ve günlükte Package 'com.openplay.sdk' has been installed without a signature uyarısı çıkar (zararsızdır).

com.unity.nuget.newtonsoft-json 3.2.1 ve com.unity.modules.unitywebrequest bağımlılıkları kendiliğinden çözülür. Yedek yol olarak yerel yol ("com.openplay.sdk": "file:<yol>/sdks/unity") kullanılabilir; bu yalnız kaynak deposuna erişimi olanlar içindir.

Paket bir Basic Login örneği içerir (Package Manager › Open Play SDK › Samples).

Temel kullanım

OpenPlayClient.Create(OpenPlayUnity.Options(baseUrl, environmentId)) istemciyi kurar; Options ana iş parçacığı pompasını, PlayerPrefs deposunu ve platforma uygun taşımayı seçer. Hızlı başlangıçtaki bileşen kayıtlı oturumu geri yükler, yoksa misafir açar.

OpenPlayOptions ayarları:

AyarAnlamı
BaseUrlAPI kökü. Mutlak https (geliştirmede loopback http); sorgu, parça ve kullanıcı bilgisi içeremez
EnvironmentIdOrtam kimliği (x-crx-env); boş olamaz
AllowInsecureTransportYalnız geliştirme: loopback adreslerinde (localhost, 127.0.0.1, ::1) düz http/ws. Varsayılan false
NativeOriginYerel derlemede bilet ve WebSocket isteklerinde gönderilen sabit Origin. Boşsa BaseUrl’den türetilir. Ortamın alan adlarında ya da genel izinli listede olmalıdır
PageOriginYalnız WebGL: sayfanın adresi; BaseUrl ile aynı origin olmalıdır (OpenPlayUnity.Options doldurur)
SecretStoreMisafir sırrı ve yenileme belirtecinin kalıcı deposu (aşağıya bakın)
TimeoutMsToplam istek süresi: 1–120 000, varsayılan 15 000
MaxResponseBytesEn büyük yanıt: 1 bayt–16 MiB, varsayılan 2 MiB
UserAgentBoşsa hiç gönderilmez
RealtimeGerçek zamanlı ayarları (AutoReconnect, ReconnectBaseMs, MaxReconnectAttempts, HeartbeatMs, AuthTimeoutMs, MaxPendingInputs, OnIdleClose)

Yanlış ayar OpenPlayException ile ErrorKind.Configuration ve kodlu bir neden verir (örneğin base_url_scheme_invalid, insecure_transport_not_loopback, environment_id_required).

Oturum

client.Session:

YöntemNe yapar?
RestoreAsync()Kayıtlı oturumu geri yükler; yoksa misafir yaratmaz
SignInGuestAsync()Misafir girişi (Misafir)
SignUpEmailAsync, SignInEmailAsync, UpgradeGuestAsyncE-posta kayıt/giriş/terfi (E-posta)
ChangePasswordAsync, RequestPasswordResetAsync, ResetPasswordAsyncParola işlemleri
RenameAsync(displayName)Görünen ad değiştirme (2–24 karakter, saatte 10)
RefreshAsync() · LogoutAsync()Yenileme ve çıkış
StateChanged olayı · StateSessionState: Status, PlayerId, SessionId, IsGuest, DisplayName, Email

SessionStatus: SignedOut, Authenticating, Authenticated, Refreshing, ReauthRequired, SigningOut, LogoutUncertain, Banned (terminal; yalnız LogoutAsync ile çıkılır), Disposed. Parola ve belirteçler SecretText ile taşınır; ToString() ve günlüklere girmez.

E-posta ve parola örnekleri için E-posta ve parola sayfasına bakın.

Sır depolama

Misafir sırrı ve yenileme belirteci ISecretStore ile saklanır. Varsayılan PlayerPrefs deposu düz metindir ve güvenli depo değildir (iOS Keychain, Android Keystore yok). Üretimde platformun güvenli deposuna yazan kendi ISecretStore uygulamanızı verin:

using System.Threading;
using System.Threading.Tasks;
using OpenPlay.Support;

/// <summary>Platformunuzun güvenli deposunu (iOS Keychain, Android Keystore, masaüstü kimlik deposu) temsil eden kendi arayüzünüz.</summary>
public interface IPlatformKeystore
{
    string Read(string key);
    void Write(string key, string value);
    void Delete(string key);
}

/// <summary>
/// ISecretStore sözleşmesi: misafir bootstrap sırrı ve yenileme belirteci burada saklanır.
/// Varsayılan PlayerPrefs deposu düz metindir ve güvenli depo DEĞİLDİR; üretimde bunun gibi kendi deponuzu verin:
///   options.SecretStore = new KeystoreSecretStore(myKeystore);
/// </summary>
public sealed class KeystoreSecretStore : ISecretStore
{
    private readonly IPlatformKeystore _keystore;

    public KeystoreSecretStore(IPlatformKeystore keystore) { _keystore = keystore; }

    public Task<string> GetAsync(string key, CancellationToken cancellationToken) => Task.FromResult(_keystore.Read(key));

    public Task SetAsync(string key, string value, CancellationToken cancellationToken)
    {
        _keystore.Write(key, value);
        return Task.CompletedTask;
    }

    public Task ClearAsync(string key, CancellationToken cancellationToken)
    {
        _keystore.Delete(key);
        return Task.CompletedTask;
    }
}

Sözleşme: değer günlüğe, istisna iletisine ve ToString()’e girmez; olmayan anahtar için GetAsync null döner; her işlem başarısız olabilir ya da geç dönebilir (SDK 3 sn sonra vazgeçer).

Eklenti komutları ve sorguları

client.Plugin(binding, pin) eklenti istemcisi verir (PrepareCommand, QueryAsync, PublicQueryAsync, VerifyServerSchemaAsync). Komut hazırlanırken tek bir Idempotency-Key üretilir ve gövde dondurulur; belirsiz sonuçta (ErrorKind.UnknownOutcome) aynı anahtarla LookupAsync ile sorgulanır, kaybolduysa ResumeAsync ile tam aynı komut yeniden gönderilir. Kör yeni komut üretilmez.

Not

Yayımlanan pakette yalnız package-ride eklentisinin üretilmiş tipli bağlaması vardır (OpenPlay.PackageRide). Başka bir eklenti için bugün üretilmiş Unity bağlaması yoktur; ham PluginBinding ile çalışırsınız. Bağlama, sunucudaki şema özetine (schemaSha256) sabitlenir: uyuşmazlıkta UpgradeRequired alırsınız.

using System.Threading.Tasks;
using OpenPlay;
using OpenPlay.PackageRide;
using OpenPlay.Plugins;

/// <summary>
/// Eklenti komutu: yayımlı pakette yalnız package-ride için üretilmiş tipli bağlama vardır.
/// Komut hazırlanırken tek Idempotency-Key üretilir; belirsiz sonuçta AYNI anahtarla sorgulanır.
/// </summary>
public static class PluginCall
{
    public static async Task ClaimLoginBonus(OpenPlayClient client, long expectedVersion)
    {
        var rides = PackageRideClient.Create(client); // bağlama sürümü ve şema özeti sunucuyla eşleşmezse UpgradeRequired
        var command = rides.Commands.ClaimLoginBonus.Prepare(new LoginBonusInput { ExpectedVersion = expectedVersion });
        try
        {
            var receipt = await command.SendAsync();
            LoginBonusOutput output = rides.Commands.ClaimLoginBonus.ParseOutput(receipt); // tipli çıktı
            UnityEngine.Debug.Log("giriş bonusu işlendi, HTTP durumu: " + receipt.Status + ", çıktı: " + output.GetType().Name);
        }
        catch (OpenPlayException ex) when (ex.Kind == ErrorKind.UnknownOutcome)
        {
            // Yanıt kayboldu; komut uygulanmış olabilir. Yeni komut üretmeyin, aynı anahtarla sorgulayın.
            var lookup = await command.LookupAsync();
            if (lookup.Status == CommandLookupStatus.NotFound) await command.ResumeAsync(); // tam aynı anahtar ve gövde
        }
    }
}

Gerçek zamanlı

client.Realtime.ConnectAsync() bileti alır, soketi açar ve kimlik doğrular; kopmada artan gecikmeyle yeniden bağlanır. Yerel derlemede bilet Authorization: Bearer + x-crx-env + sabit Origin ile alınır; çerez kullanılmaz. Abonelik açmak için RealtimeConnection.JoinAsync(modül, JoinTarget.PlayerSelf() / Room / Scene / InterestSet) kullanılır. Protokol ayrıntıları: Gerçek zamanlı.

using System;
using System.Threading.Tasks;
using OpenPlay;
using OpenPlay.Realtime;
using OpenPlay.Unity;

/// <summary>
/// Realtime soketi: bilet alma, bağlanma ve yeniden bağlanma SDK'dadır.
/// Sunucu etkinlik göstermeyen soketi 4100 koduyla kapatır; OnIdleClose verirseniz otomatik yeniden bağlanma olmaz.
/// </summary>
public static class RealtimeConnect
{
    public static OpenPlayClient Create(Uri baseUrl, Guid environmentId, Action showContinue)
    {
        var options = OpenPlayUnity.Options(baseUrl, environmentId);
        options.Realtime = new RealtimeOptions { OnIdleClose = _ => showContinue() }; // "Devam et" düğmesini gösterin
        return OpenPlayClient.Create(options);
    }

    /// <summary>Oturum açıldıktan sonra çağrılır; "Devam et" onayında da aynı çağrı yeni bilet alıp sürdürür.</summary>
    public static Task<RealtimeConnection> Connect(OpenPlayClient client) => client.Realtime.ConnectAsync();
}

WebGL

WebGL oynatıcısında SDK tarayıcı kipine geçer (OpenPlayUnity.Options bunu kendisi seçer): HTTP UnityWebRequest ile, gerçek zamanlı tarayıcının WebSocket’iyle (küçük bir jslib köprüsü) gider ve oturum çerezlerini tarayıcı yönetir. SDK Cookie, Origin, Authorization ya da User-Agent başlığı koymaz; her mutasyon x-csrf-token taşır.

  • Yalnız aynı origin (SDK kısıtı). Unity WebGL SDK’sı bugün oyun sayfası ile Open Play API’sinin aynı kökten sunulmasını şart koşar; sunucu artık ortam alan adı listesindeki origin’lere CORS verir ama Unity SDK’sı bunu henüz kullanmaz (Mimari ve barındırma). Farklı origin OpenPlayException ile Configuration ve webgl_cross_origin_unsupported kodunu verir; sessizce başarısız olmaz.
  • Gizli sekme. Kalp atışı tarayıcı zamanlayıcısıyla sürer, sekme arka plana alınınca bağlantı açık kalır. Gizliyken gelen mesajlar ve HTTP tamamlanmaları Unity karesini bekler ve sekme görünür olunca işlenir. Application.runInBackground kapalıyken oyun döngüsü gizli sekmede durur; oyununuz gizliyken de ilerlemeliyse Application.runInBackground = true yapın.
  • Çok sekme. Aynı origin’deki sekmeler tek çerez kavanozunu paylaşır; ikinci sekmedeki giriş birincinin oturum çerezini değiştirir.

Doğrulanan platformlar

Düzey: R = Unity’de ölçüldü, B = yalnız belge ya da dotnet göstergesi, — = yok.

HedefDüzeyNot
Unity 6000.6.7f1 Editör (Linux)RMono ve IL2CPP ölçüldü
WindowsBdoğrulanmadı
macOSBdoğrulanmadı
AndroidBdoğrulanmadı (telefon ölçümü yapılmadı)
iOS—doğrulanmadı
WebGL (aynı origin)RBasicLogin WebGL oynatıcısı gerçek API’ye karşı: misafir ve e-posta girişi, eklenti sorgusu, gerçek zamanlı Ready, katılım ve girdi onayı; 35 sn gizli sekmede kalp atışı sürdü. Yalnız Chrome; Firefox ve Safari doğrulanmadı

package.json içindeki unity: 2022.3 alanı yalnız alt sınırdır; Unity 2022.3 doğrulanmadı.

Hatalar

Tüm hatalar OpenPlayException olarak gelir: Kind (ErrorKind), Status, Attempts, Code, Operation, DeliveryState, Reference, Reason. ErrorKind değerleri: Http, Network, Timeout, Cancelled, Contract, Configuration, Pagination, Codegen, Auth, UnknownOutcome, Storage, Realtime, Backpressure, UpgradeRequired, CapabilityUnavailable, Disposed, ScopeChanged. Anlamları TypeScript SDK’sındakilerle aynıdır (TypeScript SDK › Hatalar).

Kapsam dışı ve bilinen sınırlar

  • Unity SDK’sında yoktur: OAuth (Google), katalog, mağaza, skor tablosu, bildirimler ve sunucu anahtarıyla yönetim işlemleri. Bunlar için ham REST kullanın; sunucu anahtarını oyun istemcisine koymayın.
  • Yanıt sıkıştırması (permessage-deflate) yoktur.
  • Erişim JWT’si uygulamaya açılmaz (Sunucuda doğrulama).
  • Android, iOS ve macOS oynatıcı koşuları yapılmadı; WebGL yalnız aynı origin’de çalışır.
  • PlayerPrefs deposu güvenli değildir; üretimde kendi deponuzu verin.