Giriş SDK'sını kullanmaya başlama

Bu dokümanda, PC'de Google Play Games'i destekleyen oyunlarda Giriş SDK'sının nasıl ayarlanacağı ve gösterileceği açıklanmaktadır. Bu görevler arasında SDK'yı oyununuza ekleme ve oyundaki işlemlerle kullanıcı girişi arasındaki atamaları içeren bir giriş haritası oluşturma yer alır.

Başlamadan önce

Giriş SDK'sını oyununuza eklemeden önce oyun motorunuzun giriş sistemini kullanarak klavye ve fare girişini desteklemeniz gerekir.

Giriş SDK'sı, oyununuzda kullanılan kontroller hakkında PC Üzerinde Google Play Games'e bilgi sağlar. Böylece bu kontroller kullanıcıya gösterilebilir. Ayrıca, kullanıcıların klavyelerini isteğe bağlı olarak yeniden eşlemelerine de izin verebilir.

Her kontrol bir InputAction'tir (ör. "Atla" için "J") ve InputActions'lerinizi InputGroups olarak düzenlersiniz. InputGroup, oyununuzdaki farklı bir modu (ör. "Araç kullanma", "Yürüyüş" veya "Ana Menü") temsil edebilir. Oyunun farklı noktalarında hangi grupların etkin olduğunu belirtmek için InputContexts simgesini de kullanabilirsiniz.

Klavye yeniden eşlemenin sizin için otomatik olarak yapılmasını etkinleştirebilirsiniz. Ancak kendi kontrol yeniden eşleme arayüzünüzü sunmayı tercih ederseniz Giriş SDK'sı yeniden eşlemeyi devre dışı bırakabilirsiniz.

Aşağıdaki ardışık düzen şemasında, Giriş SDK'sının API'sinin işleyiş şekli açıklanmaktadır:

Input SDK API'yi çağıran bir oyun uygulamasının ve Android cihazla etkileşiminin sıra diyagramı.

Oyununuz Giriş SDK'sını uyguladığında kontrolleriniz PC Üzerinde Google Play Games yer paylaşımında gösterilir.

PC Üzerinde Google Play Games yer paylaşımı

PC Üzerinde Google Play Games yer paylaşımı ("yer paylaşımı"), oyununuz tarafından tanımlanan kontrolleri gösterir. Kullanıcılar Üst Karakter + Sekme tuşlarına basarak istedikleri zaman yer paylaşımına erişebilir.

PC Üzerinde Google Play Games yer paylaşımı.

Tuş bağlamaları tasarlamayla ilgili en iyi uygulamalar

Tuş bağlamalarını tasarlarken aşağıdaki en iyi uygulamaları göz önünde bulundurun:

  • Oyun sırasında kontrollerin gezinme ve bulunabilirliğini iyileştirmek için InputActions öğelerinizi mantıksal olarak ilişkili InputGroups öğelerde gruplandırın.
  • Her InputGroup öğesini en fazla bir InputContext öğesine atayın. İnce taneli InputMap, yer paylaşımındaki kontrollerinizin arasında gezinme deneyimini iyileştirir.
  • Oyununuzdaki her farklı sahne türü için bir InputContext oluşturun. Genellikle, tüm "menü benzeri" sahneleriniz için tek bir InputContext kullanabilirsiniz. Oyununuzdaki mini oyunlar veya tek bir sahnedeki alternatif kontroller için farklı InputContexts kullanın.
  • İki işlem aynı InputContext altında aynı anahtarı kullanacak şekilde tasarlandıysa "Etkileşim kur / Tetikle" gibi bir etiket dizesi kullanın.
  • İki anahtar aynı InputAction'ye bağlanacak şekilde tasarlandıysa oyununuzda aynı işlemi gerçekleştiren 2 farklı InputActions kullanın. Her iki InputActions için de aynı etiket dizesini kullanabilirsiniz ancak kimliği farklı olmalıdır.
  • Bir değiştirici tuşu bir anahtar grubuna uygulanıyorsa değiştirici tuşunu birleştiren birden fazla InputActions yerine değiştirici tuşunu içeren tek bir InputAction kullanabilirsiniz (örnek: Üst Karakter + W, Üst Karakter + A, Üst Karakter + S, Üst Karakter + D yerine Üst Karakter ve W, A, S, D tuşlarını kullanın).
  • Kullanıcı metin alanlarına yazarken giriş yeniden eşleme otomatik olarak devre dışı bırakılır. Android'in oyununuzdaki metin alanlarını algılayabilmesi ve yeniden eşlenen anahtarların bunlara müdahale etmesini önlemek için Android metin alanlarını uygulamayla ilgili en iyi uygulamaları uygulayın. Oyununuzda geleneksel olmayan metin alanları kullanılması gerekiyorsa yeniden eşlemeyi manuel olarak devre dışı bırakmak için setInputContext() ile boş bir InputGroups listesi içeren bir InputContext kullanabilirsiniz.
  • Oyununuz yeniden eşlemeyi destekliyorsa anahtar bağlamalarınızı güncelleyebilirsiniz. Bu hassas işlem, kullanıcı tarafından kaydedilen sürümlerle çakışabilir. Mümkün olduğunda mevcut denetimlerin kimliklerini değiştirmekten kaçının.

Yeniden eşleme özelliği

PC Üzerinde Google Play Games, oyununuzun Giriş SDK'sını kullanarak sağladığı tuş bağlamalarına göre klavye kontrolünün yeniden haritalanmasını destekler. Bu isteğe bağlıdır ve tamamen devre dışı bırakılabilir. Örneğin, kendi klavye yeniden eşleme arayüzünüzü sağlamak isteyebilirsiniz. Oyununuzda yeniden eşlemeyi devre dışı bırakmak için InputMap için yeniden eşleme seçeneğini devre dışı bırakmanız yeterlidir (daha fazla bilgi için InputMap oluşturma bölümüne bakın).

Bu özelliğe erişmek için kullanıcıların yer paylaşımını açmaları ve ardından yeniden eşlemek istedikleri işlemi tıklamaları gerekir. PC Üzerinde Google Play Games, her yeniden eşleme etkinliğinde kullanıcı tarafından yeniden eşlenen her kontrolü, oyununuzun beklediği varsayılan kontrollerle eşler. Böylece oyununuzun, oyuncunun yeniden eşlemesini bilmesi gerekmez. İsteğe bağlı olarak, yeniden eşleme etkinlikleri için geri arama işlevi ekleyerek oyununuzda klavye kontrollerini görüntülemek için kullanılan öğeleri güncelleyebilirsiniz.

Anahtarı yeniden eşlemeye çalışma

PC Üzerinde Google Play Games, yeniden eşlenen kontrolleri her kullanıcı için yerel olarak depolar. Bu sayede, oyun oturumları boyunca kontrolleri aynı şekilde kullanabilirsiniz. Bu bilgiler yalnızca PC platformu için diskte depolanır ve mobil deneyimi etkilemez. Kontrol verileri, kullanıcı PC'de Google Play Games'i kaldırdığında veya yeniden yüklediğinde silinir. Bu veriler birden fazla PC cihazında kalıcı değildir.

Oyununuzda yeniden eşleme özelliğini desteklemek için aşağıdaki kısıtlamalardan kaçının:

Yeniden eşleme kısıtlamaları

Tuş bağlamaları aşağıdaki durumlardan herhangi birini içeriyorsa oyununuzda yeniden eşleme özellikleri devre dışı bırakılabilir:

  • Değiştirici tuş + değiştirici olmayan tuştan oluşmayan çoklu InputActions. Örneğin, Üst Karakter + A geçerlidir ancak A + B, Ctrl + Alt veya Üst Karakter + A + Sekme geçerli değildir.
  • InputMap, yinelenen benzersiz kimliklere sahip InputActions, InputGroups veya InputContexts içeriyor.

Yeniden eşlemeyle ilgili sınırlamalar

Yeniden eşleme için tuş bağlamalarınızı tasarlarken aşağıdaki sınırlamaları göz önünde bulundurun:

  • Tuş kombinasyonlarına yeniden eşleme desteklenmez. Örneğin, kullanıcılar Üst Karakter + A'yı Ctrl + B veya A'yı Üst Karakter + A olarak yeniden eşleyemez.
  • Fare düğmeleriyle InputActions için yeniden eşleme desteklenmez. Örneğin, Üst karakter + sağ tıklama yeniden eşlenemez.

PC Üzerinde Google Play Games Emülatörü'nde tuş yeniden eşlemeyi test etme

Aşağıdaki adb komutunu uygulayarak PC Üzerinde Google Play Games emülatöründe yeniden eşleme özelliğini istediğiniz zaman etkinleştirebilirsiniz:

adb shell dumpsys input_mapping_service --set RemappingFlagValue true

Yer paylaşımı aşağıdaki resimdeki gibi değiştirildi:

Anahtar yeniden eşleme etkinken yer paylaşımı.

SDK'yı ekleme

Giriş SDK'sını geliştirme platformunuza göre yükleyin.

Java ve Kotlin

Modül düzeyindeki build.gradle dosyanıza bağımlılık ekleyerek Java veya Kotlin için giriş SDK'sını alın:

dependencies {
  implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
  ...
}

Unity

Giriş SDK'sı, çeşitli bağımlılıklara sahip standart bir Unity paketidir.

Paketin tüm bağımlılıklarıyla birlikte yüklenmesi gerekir. Paketleri yüklemenin birkaç yolu vardır.

.unitypackage

Tüm bağımlılıklarıyla birlikte Giriş SDK'sı unitypackage dosyasını indirin. Öğeler > Paketi içe aktar > Özel Paket'i seçip indirdiğiniz dosyayı bularak .unitypackage'ü yükleyebilirsiniz.

UPM'yi kullanarak yükleme

Alternatif olarak, .tgz'yi indirip bağımlılarını yükleyerek paketi Unity Package Manager'ı kullanarak da yükleyebilirsiniz:

OpenUPM'yi kullanarak yükleme

Paketi OpenUPM'i kullanarak yükleyebilirsiniz.

$ openupm add com.google.android.libraries.play.games.inputmapping

Örnek oyunlar

Giriş SDK'sı ile entegrasyon örnekleri için Kotlin veya Java oyunları için AGDK Tunnel'e, Unity oyunları için ise Trivial Kart'a bakın.

Tuş bağlamalarınızı oluşturma

InputMap oluşturarak ve InputMappingProvider ile döndürerek tuş bağlamalarınızı kaydedin. Aşağıdaki örnekte bir InputMappingProvider'nin ana hatları belirtilmiştir:

Kotlin

class InputSDKProvider : InputMappingProvider {
  override fun onProvideInputMap(): InputMap {
    TODO("Not yet implemented")
  }
}

Java

public class InputSDKProvider implements InputMappingProvider {
    private static final String INPUTMAP_VERSION = "1.0.0";

    @Override
    @NonNull
    public InputMap onProvideInputMap() {
        // TODO: return an InputMap
    }
}

C#

#if PLAY_GAMES_PC
using Java.Lang;
using Java.Util;
using Google.Android.Libraries.Play.Games.Inputmapping;
using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel;

public class InputSDKProvider : InputMappingProviderCallbackHelper
{
    public static readonly string INPUT_MAP_VERSION = "1.0.0";

    public override InputMap OnProvideInputMap()
    {
        // TODO: return an InputMap
    }
}
#endif

Giriş işlemlerinizi tanımlama

InputAction sınıfı, bir anahtarı veya tuş kombinasyonunu bir oyun hareketiyle eşlemek için kullanılır. InputActions, tüm InputActions'lerde benzersiz kimliklere sahip olmalıdır.

Yeniden eşlemeyi destekliyorsanız InputActions değerinin ne şekilde yeniden eşlenebileceğini tanımlayabilirsiniz. Oyununuz yeniden eşlemeyi desteklemiyorsa yeniden eşleme seçeneğini tüm InputActions cihazlarınız için devre dışı bırakmanız gerekir. Ancak Giriş SDK'sı, InputMap cihazınızda desteklemiyorsanız yeniden eşlemeyi devre dışı bırakacak kadar akıllıdır.

Bu örnekte, boşluk tuşu Drive işlemiyle eşlenir.

Kotlin

companion object {
  private val driveInputAction = InputAction.create(
    "Drive",
    InputActionsIds.DRIVE.ordinal.toLong(),
    InputControls.create(listOf(KeyEvent.KEYCODE_SPACE), emptyList()),
    InputEnums.REMAP_OPTION_ENABLED)
}

Java

private static final InputAction driveInputAction = InputAction.create(
    "Drive",
    InputEventIds.DRIVE.ordinal(),
    InputControls.create(
            Collections.singletonList(KeyEvent.KEYCODE_SPACE),
            Collections.emptyList()),
    InputEnums.REMAP_OPTION_ENABLED
);

C#

private static readonly InputAction driveInputAction = InputAction.Create(
    "Drive",
    (long)InputEventIds.DRIVE,
    InputControls.Create(
        new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(),
        new ArrayList<Integer>()),
    InputEnums.REMAP_OPTION_ENABLED
);

Yer paylaşımında gösterilen tek tuşlu InputAction.

İşlemler, fare girişlerini de temsil edebilir. Bu örnekte, Sol tıklama için Taşı işlemi ayarlanmıştır:

Kotlin

companion object {
  private val mouseInputAction = InputAction.create(
    "Move",
    InputActionsIds.MOUSE_MOVEMENT.ordinal.toLong(),
    InputControls.create(emptyList(), listOf(InputControls.MOUSE_LEFT_CLICK)),
    InputEnums.REMAP_OPTION_DISABLED)
}

Java

private static final InputAction mouseInputAction = InputAction.create(
    "Move",
    InputActionsIds.MOUSE_MOVEMENT.ordinal(),
    InputControls.create(
            Collections.emptyList(),
            Collections.singletonList(InputControls.MOUSE_LEFT_CLICK)
    ),
    InputEnums.REMAP_OPTION_DISABLED
);

C#

private static readonly InputAction mouseInputAction = InputAction.Create(
    "Move",
    (long)InputEventIds.MOUSE_MOVEMENT,
    InputControls.Create(
        new ArrayList<Integer>(),
        new[] { new Integer((int)PlayMouseAction.MouseLeftClick) }.ToJavaList()
    ),
    InputEnums.REMAP_OPTION_DISABLED
);

Yer paylaşımında gösterilen fare girişi işlemi.

Tuş kombinasyonları, InputAction öğenize birden fazla tuş kodu iletilerek belirtilir. Bu örnekte boşluk + üst karakter, Turbo işlemiyle eşleştirilmiştir. Bu işlem, Boşluk Sür ile eşleştirilmiş olsa bile çalışır.

Kotlin

companion object {
  private val turboInputAction = InputAction.create(
    "Turbo",
    InputActionsIds.TURBO.ordinal.toLong(),
    InputControls.create(
      listOf(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE),
      emptyList()),
    InputEnums.REMAP_OPTION_ENABLED)
}

Java

private static final InputAction turboInputAction = InputAction.create(
    "Turbo",
    InputActionsIds.TURBO.ordinal(),
    InputControls.create(
            Arrays.asList(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE),
            Collections.emptyList()
    ),
    InputEnums.REMAP_OPTION_ENABLED
);

C#

private static readonly InputAction turboInputAction = InputAction.Create(
    "Turbo",
    (long)InputEventIds.TURBO,
    InputControls.Create(
        new[]
        {
            new Integer(AndroidKeyCode.KEYCODE_SHIFT_LEFT),
            new Integer(AndroidKeyCode.KEYCODE_SPACE)
        }.ToJavaList(),
        new ArrayList<Integer>()),
    InputEnums.REMAP_OPTION_ENABLED
);

Yer paylaşımında gösterilen çok anahtarlı InputAction.

Giriş SDK'sı, tek bir işlem için fare ve tuş düğmelerini birlikte kullanmanıza olanak tanır. Bu örnekte, Üst Karakter ve Sağ tıklama tuşlarının birlikte basılması sonucunda bu örnek oyunda bir yol noktası eklendiğini görebilirsiniz:

Kotlin

companion object {
  private val addWaypointInputAction = InputAction.create(
    "Add waypoint",
    InputActionsIds.ADD_WAYPOINT.ordinal.toLong(),
    InputControls.create(
      listOf(KeyEvent.KeyEvent.KEYCODE_TAB),
      listOf(InputControls.MOUSE_RIGHT_CLICK)),
    InputEnums.REMAP_OPTION_DISABLED)
}

Java

private static final InputAction addWaypointInputAction = InputAction.create(
    "Add waypoint",
    InputActionsIds.ADD_WAYPOINT.ordinal(),
    InputControls.create(
            Collections.singletonList(KeyEvent.KEYCODE_TAB),
            Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
    ),
    InputEnums.REMAP_OPTION_DISABLED
);

C#

private static readonly InputAction addWaypointInputAction = InputAction.Create(
    "Add waypoint",
    (long)InputEventIds.ADD_WAYPOINT,
    InputControls.Create(
        new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(),
        new[] { new Integer((int)PlayMouseAction.MouseRightClick) }.ToJavaList()
    ),
    InputEnums.REMAP_OPTION_DISABLED
);

Yer paylaşımında gösterilen tuş + fare giriş işlemi kombinasyonu.

InputAction aşağıdaki alanlara sahiptir:

  • ActionLabel: Bu işlemi temsil etmek için kullanıcı arayüzünde gösterilen dize. Yerelleştirme otomatik olarak yapılmaz. Bu nedenle, yerelleştirmeyi önceden yapın.
  • InputControls: Bu işlemin kullandığı giriş denetimlerini tanımlar. Kontroller, yer paylaşımındaki tutarlı karakterlerle eşlenir.
  • InputActionId: InputAction kimliğini ve sürümünü depolayan InputIdentifier nesnesi (daha fazla bilgi için İzleme Anahtar Kimlikleri bölümüne bakın).
  • InputRemappingOption: InputEnums.REMAP_OPTION_ENABLED veya InputEnums.REMAP_OPTION_DISABLED değerlerinden biri. İşlemin yeniden eşleme için etkinleştirilip etkinleştirilmeyeceğini tanımlar. Oyununuz yeniden eşlemeyi desteklemiyorsa bu alanı atlayabilir veya devre dışı bırakabilirsiniz.
  • RemappedInputControls: Yeniden eşleme etkinliklerinde kullanıcı tarafından ayarlanan yeniden eşlenen anahtarı okumak için kullanılan salt okunur InputControls nesnesi (yeniden eşleme etkinlikleri hakkında bildirim almak için kullanılır).

InputControls, bir işlemle ilişkili girişleri temsil eder ve aşağıdaki alanları içerir:

  • AndroidKeycodes: Bir işlemle ilişkili klavye girişlerini temsil eden tam sayıların listesidir. Bunlar KeyEvent sınıfında veya Unity için AndroidKeycode sınıfında tanımlanır.
  • MouseActions: Bu işlemle ilişkili fare girişlerini temsil eden MouseAction değerlerinin listesidir.

Giriş gruplarınızı tanımlama

InputActions, gezinmeyi iyileştirmek ve yer paylaşımındaki bulunabilirliği kontrol etmek için InputGroups kullanılarak mantıksal olarak ilişkili işlemlerle gruplandırılır. Her InputGroup kimliğinin, oyununuzdaki tüm InputGroups'ler için benzersiz olması gerekir.

Giriş işlemlerinizi gruplara ayırarak oyuncuların mevcut bağlamları için doğru tuş bağlamalarını bulmalarını kolaylaştırırsınız.

Yeniden eşlemeyi destekliyorsanız InputGroups değerinin ne şekilde yeniden eşlenebileceğini tanımlayabilirsiniz. Oyununuz yeniden eşlemeyi desteklemiyorsa yeniden eşleme seçeneğini tüm InputGroups cihazlarınız için devre dışı bırakmanız gerekir. Ancak Giriş SDK'sı, InputMap cihazınızda yeniden eşlemeyi desteklemiyorsanız yeniden eşlemeyi devre dışı bırakacak kadar akıllıdır.

Kotlin

companion object {
  private val menuInputGroup = InputGroup.create(
    "Menu keys",
    listOf(
      navigateUpInputAction,
      navigateLeftInputAction,
      navigateDownInputAction,
      navigateRightInputAction,
      openMenuInputAction,
      returnMenuInputAction),
    InputGroupsIds.MENU_ACTION_KEYS.ordinal.toLong(),
    InputEnums.REMAP_OPTION_ENABLED
  )
}

Java

private static final InputGroup menuInputGroup = InputGroup.create(
    "Menu keys",
    Arrays.asList(
           navigateUpInputAction,
           navigateLeftInputAction,
           navigateDownInputAction,
           navigateRightInputAction,
           openMenuInputAction,
           returnMenuInputAction),
    InputGroupsIds.MENU_ACTION_KEYS.ordinal(),
    REMAP_OPTION_ENABLED
);

C#

private static readonly InputGroup menuInputGroup = InputGroup.Create(
    "Menu keys",
    new[]
    {
        navigateUpInputAction,
        navigateLeftInputAction,
        navigateDownInputAction,
        navigateRightInputAction,
        openMenuInputAction,
        returnMenuInputAction,
    }.ToJavaList(),
    (long)InputGroupsIds.MENU_ACTION_KEYS,
    InputEnums.REMAP_OPTION_ENABLED
);

Aşağıdaki örnekte, yer paylaşımındaki Yol kontrolleri ve Menü kontrolleri giriş grupları gösterilmektedir:

Yol kontrolleri ve menü kontrolleri giriş gruplarını içeren bir InputMap&#39;i gösteren yer paylaşımı.

InputGroup aşağıdaki alanları içerir:

  • GroupLabel: Yer paylaşımında gösterilecek ve bir dizi işlemi mantıksal olarak gruplandırmak için kullanılabilecek bir dize. Bu dize otomatik olarak yerelleştirilmez.
  • InputActions: Önceki adımda tanımladığınız InputAction nesnelerinin listesi. Bu işlemlerin tümü grup başlığı altında görsel olarak gösterilir.
  • InputGroupId: InputGroup öğesinin numara kimliğini ve sürümünü depolayan InputIdentifier nesnesi. Daha fazla bilgi için İzleme Anahtar Kimlikleri bölümüne bakın.
  • InputRemappingOption: InputEnums.REMAP_OPTION_ENABLED veya InputEnums.REMAP_OPTION_DISABLED değerlerinden biri. Devre dışı bırakılırsa bu gruba ait tüm InputActionöğelerin yeniden eşleme seçeneği etkin olsa bile yeniden eşleme devre dışı bırakılır. Bu seçenek etkinleştirilirse, ayrı ayrı işlemler tarafından devre dışı bırakılmadığı sürece bu gruba ait tüm işlemler yeniden atanabilir.

Giriş bağlamlarınızı tanımlama

InputContexts, oyununuzun farklı sahneleri için farklı bir klavye kontrol grubu kullanmasına olanak tanır. Örnek:

  • Menülerde gezinmek ve oyunda hareket etmek için farklı giriş grupları belirtebilirsiniz.
  • Oyununuzdaki hareket şekline (ör. araba sürme veya yürüme) bağlı olarak farklı giriş kümeleri belirtebilirsiniz.
  • Oyununuzun mevcut durumuna göre farklı giriş grupları belirtebilirsiniz (ör. bir üst dünyada gezinme ve tek bir seviyeyi oynama).

InputContexts kullanılırken yer paylaşımında önce kullanılan bağlamın grupları gösterilir. Bu davranışı etkinleştirmek için oyununuz farklı bir sahneye her girdiğinde bağlamı ayarlamak üzere setInputContext() işlevini çağırın. Aşağıdaki resimde bu davranış gösterilmektedir: "Araç kullanma" sahnesinde, Yol kontrolleri işlemleri yer paylaşımının üst kısmında gösterilmektedir. "Mağaza" menüsü açıldığında "Menü kontrolleri" işlemleri yer paylaşımının üst kısmında gösterilir.

Yer paylaşımındaki grupları sıralayan InputContexts.

Bu yer paylaşımı güncellemeleri, oyununuzun farklı noktalarında farklı bir InputContext ayarlayarak yapılır. Bunu yapmak için:

  1. InputActions öğelerinizi InputGroups kullanarak mantıksal olarak ilişkili işlemlerle gruplandırın
  2. Bu InputGroups'leri oyununuzun farklı bölümleri için bir InputContext'e atayın

InputGroups aynı anahtarın kullanıldığıInputContext birbirine çelişen InputActions sahip olamaz. Her InputGroup öğesini tek bir InputContext öğesine atamak iyi bir uygulamadır.

Aşağıdaki örnek kodda InputContext mantığı gösterilmektedir:

Kotlin

companion object {
  val menuSceneInputContext = InputContext.create(
    "Menu",
    InputIdentifier.create(
      INPUTMAP_VERSION,
      InputContextIds.MENU_SCENE.ordinal.toLong()),
    listOf(basicMenuNavigationInputGroup, menuActionsInputGroup))

  val gameSceneInputContext = InputContext.create(
    "Game",
    InputIdentifier.create(
      INPUTMAP_VERSION,
      InputContextIds.GAME_SCENE.ordinal.toLong()),
    listOf(
      movementInputGroup,
      mouseActionsInputGroup,
      emojisInputGroup,
      gameActionsInputGroup))
}

Java

public static final InputContext menuSceneInputContext = InputContext.create(
        "Menu",
        InputIdentifier.create(
                INPUTMAP_VERSION,
                InputContextIds.MENU_SCENE.ordinal()),
        Arrays.asList(
                basicMenuNavigationInputGroup,
                menuActionsInputGroup
        )
);

public static final InputContext gameSceneInputContext = InputContext.create(
        "Game",
        InputIdentifier.create(
                INPUTMAP_VERSION,
                InputContextIds.GAME_SCENE.ordinal()),
        Arrays.asList(
                movementInputGroup,
                mouseActionsInputGroup,
                emojisInputGroup,
                gameActionsInputGroup
        )
);

C#

public static readonly InputContext menuSceneInputContext = InputContext.Create(
    "Menu",
    InputIdentifier.Create(
        INPUT_MAP_VERSION,
        (long)InputContextsIds.MENU_SCENE),
    new[]
    {
        basicMenuNavigationInputGroup,
        menuActionsInputGroup
    }.ToJavaList()
);

public static readonly InputContext gameSceneInputContext = InputContext.Create(
    "Game",
    InputIdentifier.Create(
        INPUT_MAP_VERSION,
        (long)InputContextsIds.GAME_SCENE),
    new[]
    {
        movementInputGroup,
        mouseActionsInputGroup,
        emojisInputGroup,
        gameActionsInputGroup
    }.ToJavaList()
);

InputContext aşağıdaki alanları içerir:

  • LocalizedContextLabel: Bağlama ait grupları açıklayan bir dize.
  • InputContextId: InputContext kimliğini ve sürümünü depolayan InputIdentifier nesnesi (daha fazla bilgi için İzleme Anahtar Kimlikleri bölümüne bakın).
  • ActiveGroups: Bu bağlam etkin olduğunda kullanılacak ve yer paylaşımının üst kısmında gösterilecek InputGroups öğelerinin listesi.

Giriş haritası oluşturma

InputMap, bir oyunda bulunan tüm InputGroup nesnelerinin ve dolayısıyla bir oyuncunun gerçekleştirebileceği tüm InputAction nesnelerinin bir koleksiyonudur.

Tuş bağlamalarınızı raporlarken oyununuzda kullanılan tüm InputGroups ile bir InputMap oluşturursunuz.

Oyununuz yeniden eşlemeyi desteklemiyorsa yeniden eşleme seçeneğini devre dışı bırakın ve ayrılmış anahtarları boş bırakın.

Aşağıdaki örnekte, bir InputGroups koleksiyonunu bildirmek için kullanılan bir InputMap oluşturulmaktadır.

Kotlin

companion object {
  val gameInputMap = InputMap.create(
    listOf(
      basicMenuNavigationInputGroup,
      menuActionKeysInputGroup,
      movementInputGroup,
      mouseMovementInputGroup,
      pauseMenuInputGroup),
    MouseSettings.create(true, false),
    InputIdentifier.create(INPUTMAP_VERSION, INPUT_MAP_ID.toLong()),
    InputEnums.REMAP_OPTION_ENABLED,
    // Use ESCAPE as reserved remapping key
    listof(InputControls.create(listOf(KeyEvent.KEYCODE_ESCAPE), emptyList()))
  )
}

Java

public static final InputMap gameInputMap = InputMap.create(
        Arrays.asList(
                basicMenuNavigationInputGroup,
                menuActionKeysInputGroup,
                movementInputGroup,
                mouseMovementInputGroup,
                pauseMenuInputGroup),
        MouseSettings.create(true, false),
        InputIdentifier.create(INPUTMAP_VERSION, INPUT_MAP_ID),
        REMAP_OPTION_ENABLED,
        // Use ESCAPE as reserved remapping key
        Arrays.asList(
                InputControls.create(
                        Collections.singletonList(KeyEvent.KEYCODE_ESCAPE),
                        Collections.emptyList()
                )
        )
);

C#

public static readonly InputMap gameInputMap = InputMap.Create(
    new[]
    {
        basicMenuNavigationInputGroup,
        menuActionKeysInputGroup,
        movementInputGroup,
        mouseMovementInputGroup,
        pauseMenuInputGroup,
    }.ToJavaList(),
    MouseSettings.Create(true, false),
    InputIdentifier.Create(INPUT_MAP_VERSION, INPUT_MAP_ID),
    InputEnums.REMAP_OPTION_ENABLED,
    // Use ESCAPE as reserved remapping key
    new[]
    {
        InputControls.Create(
            New[] {
            new Integer(AndroidKeyCode.KEYCODE_ESCAPE)
        }.ToJavaList(),
        new ArrayList<Integer>())
    }.ToJavaList()
);

InputMap aşağıdaki alanları içerir:

  • InputGroups: Oyununuz tarafından raporlanan InputGroups. setInputContext() çağrısı yapılarak kullanılan mevcut gruplar belirtilmediği sürece gruplar yer paylaşımında sırayla gösterilir.
  • MouseSettings: MouseSettings nesnesi, fare hassasiyetinin ayarlanabileceğini ve farenin y ekseninde ters çevrildiğini gösterir.
  • InputMapId: InputMap kimliğini ve sürümünü depolayan InputIdentifier nesnesi (daha fazla bilgi için İzleme Anahtarı Kimlikleri bölümüne bakın).
  • InputRemappingOption: InputEnums.REMAP_OPTION_ENABLED veya InputEnums.REMAP_OPTION_DISABLED değerlerinden biri. Yeniden eşleme özelliğinin etkin olup olmadığını tanımlar.
  • ReservedControls: Kullanıcıların yeniden eşlemeye izin verilmeyen InputControls değerlerinin listesi.

Anahtar kimliklerini izleme

InputAction, InputGroup, InputContext ve InputMap nesneleri, benzersiz bir sayı kimliği ve dize sürüm kimliği depolayan bir InputIdentifier nesnesi içerir. Nesnelerinizin dize sürümünü izlemek isteğe bağlıdır ancak InputMap sürümlerinizi izlemek için önerilir. Dize sürümü sağlanmazsa dize boş olur. InputMap nesneleri için dize sürümü gereklidir.

Aşağıdaki örnekte, InputActions veya InputGroups için bir dize sürümü atanmaktadır:

Kotlin

class InputSDKProviderKotlin : InputMappingProvider {
  companion object {
    const val INPUTMAP_VERSION = "1.0.0"
    private val enterMenuInputAction = InputAction.create(
      "Enter menu",
      InputControls.create(listOf(KeyEvent.KEYCODE_ENTER), emptyList()),
      InputIdentifier.create(
        INPUTMAP_VERSION, InputActionsIds.ENTER_MENU.ordinal.toLong()),
      InputEnums.REMAP_OPTION_ENABLED
    )

    private val movementInputGroup  = InputGroup.create(
      "Basic movement",
      listOf(
        moveUpInputAction,
        moveLeftInputAction,
        moveDownInputAction,
        mouseGameInputAction),
      InputIdentifier.create(
        INPUTMAP_VERSION, InputGroupsIds.BASIC_MOVEMENT.ordinal.toLong()),
      InputEnums.REMAP_OPTION_ENABLED)
  }
}

Java

public class InputSDKProvider implements InputMappingProvider {
    public static final String INPUTMAP_VERSION = "1.0.0";

    private static final InputAction enterMenuInputAction = InputAction.create(
            "Enter menu",
            InputControls.create(
                    Collections.singletonList(KeyEvent.KEYCODE_ENTER),
                    Collections.emptyList()),
            InputIdentifier.create(
                    INPUTMAP_VERSION, InputActionsIds.ENTER_MENU.ordinal()),
            InputEnums.REMAP_OPTION_ENABLED
    );

    private static final InputGroup movementInputGroup = InputGroup.create(
            "Basic movement",
            Arrays.asList(
                    moveUpInputAction,
                    moveLeftInputAction,
                    moveDownInputAction,
                    moveRightInputAction,
                    mouseGameInputAction
            ),
            InputIdentifier.create(
                    INPUTMAP_VERSION, InputGroupsIds.BASIC_MOVEMENT.ordinal()),
            InputEnums.REMAP_OPTION_ENABLED
    );
}

C#

#if PLAY_GAMES_PC

using Java.Lang;
using Java.Util;
using Google.Android.Libraries.Play.Games.Inputmapping;
using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel;

public class InputSDKMappingProvider : InputMappingProviderCallbackHelper
{
    public static readonly string INPUT_MAP_VERSION = "1.0.0";

    private static readonly InputAction enterMenuInputAction =
        InputAction.Create(
            "Enter menu",
            InputControls.Create(
                new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE)}.ToJavaList(),
                new ArrayList<Integer>()),
            InputIdentifier.Create(
                INPUT_MAP_VERSION,
                (long)InputEventIds.ENTER_MENU),
            InputEnums.REMAP_OPTION_ENABLED
        );

    private static readonly InputGroup movementInputGroup = InputGroup.Create(
        "Basic movement",
        new[]
        {
            moveUpInputAction,
            moveLeftInputAction,
            moveDownInputAction,
            moveRightInputAction,
            mouseGameInputAction
        }.ToJavaList(),
        InputIdentifier.Create(
            INPUT_MAP_VERSION,
            (long)InputGroupsIds.BASIC_MOVEMENT),
        InputEnums.REMAP_OPTION_ENABLED
    );
}
#endif

InputAction nesnelerinin numara kimlikleri, InputMap'nizdeki tüm InputActions'ler arasında benzersiz olmalıdır. Benzer şekilde, InputGroup nesne kimlikleri bir InputMap içindeki tüm InputGroups'ler için benzersiz olmalıdır. Aşağıdaki örnekte, nesnenizin benzersiz kimliklerini izlemek için enum değerinin nasıl kullanılacağı gösterilmektedir:

Kotlin

enum class InputActionsIds {
    NAVIGATE_UP,
    NAVIGATE_DOWN,
    ENTER_MENU,
    EXIT_MENU,
    // ...
    JUMP,
    RUN,
    EMOJI_1,
    EMOJI_2,
    // ...
}

enum class InputGroupsIds {
    // Main menu scene
    BASIC_NAVIGATION, // WASD, Enter, Backspace
    MENU_ACTIONS, // C: chat, Space: quick game, S: store
    // Gameplay scene
    BASIC_MOVEMENT, // WASD, space: jump, Shift: run
    MOUSE_ACTIONS, // Left click: shoot, Right click: aim
    EMOJIS, // Emojis with keys 1,2,3,4 and 5
    GAME_ACTIONS, // M: map, P: pause, R: reload
}

enum class InputContextIds {
    MENU_SCENE, // Basic menu navigation, menu actions
    GAME_SCENE, // Basic movement, mouse actions, emojis, game actions
}

const val INPUT_MAP_ID = 0

Java

public enum InputActionsIds {
    NAVIGATE_UP,
    NAVIGATE_DOWN,
    ENTER_MENU,
    EXIT_MENU,
    // ...
    JUMP,
    RUN,
    EMOJI_1,
    EMOJI_2,
    // ...
}

public enum InputGroupsIds {
    // Main menu scene
    BASIC_NAVIGATION, // WASD, Enter, Backspace
    MENU_ACTIONS, // C: chat, Space: quick game, S: store
    // Gameplay scene
    BASIC_MOVEMENT, // WASD, space: jump, Shift: run
    MOUSE_ACTIONS, // Left click: shoot, Right click: aim
    EMOJIS, // Emojis with keys 1,2,3,4 and 5
    GAME_ACTIONS, // M: map, P: pause, R: reload
}

public enum InputContextIds {
    MENU_SCENE, // Basic navigation, menu actions
    GAME_SCENE, // Basic movement, mouse actions, emojis, game actions
}

public static final long INPUT_MAP_ID = 0;

C#

public enum InputActionsIds
{
    NAVIGATE_UP,
    NAVIGATE_DOWN,
    ENTER_MENU,
    EXIT_MENU,
    // ...
    JUMP,
    RUN,
    EMOJI_1,
    EMOJI_2,
    // ...
}

public enum InputGroupsIds
{
    // Main menu scene
    BASIC_NAVIGATION, // WASD, Enter, Backspace
    MENU_ACTIONS, // C: chat, Space: quick game, S: store
    // Gameplay scene
    BASIC_MOVEMENT, // WASD, space: jump, Shift: run
    MOUSE_ACTIONS, // Left click: shoot, Right click: aim
    EMOJIS, // Emojis with keys 1,2,3,4 and 5
    GAME_ACTIONS, // M: map, P: pause, R: reload
}

public enum InputContextIds
{
    MENU_SCENE, // Basic navigation, menu actions
    GAME_SCENE, // Basic movement, mouse actions, emojis, game actions
}

public static readonly long INPUT_MAP_ID = 0;

InputIdentifier aşağıdaki alanları içerir:

  • UniqueId: Belirli bir giriş verisi grubunu benzersiz şekilde tanımlamak için ayarlanan benzersiz bir sayı kimliği.
  • VersionString: Giriş verileri değişikliklerinin 2 sürümü arasındaki giriş verisi sürümünü tanımlamak için ayarlanmış, kullanıcı tarafından okunabilen bir sürüm dizesi.

Yeniden eşleme etkinlikleri hakkında bildirim alma (İsteğe bağlı)

Oyununuzda kullanılan tuşlar hakkında bilgi edinmek için yeniden eşleme etkinlikleriyle ilgili bildirim alın. Bu sayede oyununuz, işlem kontrollerini görüntülemek için kullanılan oyun ekranında gösterilen öğeleri güncelleyebilir.

Aşağıdaki resimde, G, P ve S tuşlarının sırasıyla J, X ve T olarak yeniden eşlenmesinden sonra oyunun kullanıcı arayüzü öğelerinin, kullanıcı tarafından ayarlanan tuşları göstermek üzere güncellendiği bu davranışa örnek gösterilmektedir.

InputRemappingListener geri çağırma işlevini kullanarak yeniden eşleme etkinliklerine tepki veren kullanıcı arayüzü.

Bu işlev, bir InputRemappingListener geri çağırma işlevi kaydedilerek elde edilir. Bu özelliği uygulamak için bir InputRemappingListener örneği kaydederek başlayın:

Kotlin

class InputSDKRemappingListener : InputRemappingListener {
  override fun onInputMapChanged(inputMap: InputMap) {
    Log.i(TAG, "Received update on input map changed.")
    if (inputMap.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) {
      return
    }
    for (inputGroup in inputMap.inputGroups()) {
      if (inputGroup.inputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED) {
        continue
      }
      for (inputAction in inputGroup.inputActions()) {
        if (inputAction.inputRemappingOption() != InputEnums.REMAP_OPTION_DISABLED) {
          // Found InputAction remapped by user
          processRemappedAction(inputAction)
        }
      }
    }
  }

  private fun processRemappedAction(remappedInputAction: InputAction) {
    // Get remapped action info
    val remappedControls = remappedInputAction.remappedInputControls()
    val remappedKeyCodes = remappedControls.keycodes()
    val mouseActions = remappedControls.mouseActions()
    val version = remappedInputAction.inputActionId().versionString()
    val remappedActionId = remappedInputAction.inputActionId().uniqueId()
    val currentInputAction: Optional<InputAction>
    currentInputAction = if (version == null || version.isEmpty()
      || version == InputSDKProvider.INPUTMAP_VERSION
    ) {
      getCurrentVersionInputAction(remappedActionId)
    } else {
      Log.i(TAG,
            "Detected version of user-saved input action defers from current version")
      getCurrentVersionInputActionFromPreviousVersion(
        remappedActionId, version)
    }
    if (!currentInputAction.isPresent) {
      Log.e(TAG, String.format(
        "can't find remapped input action with id %d and version %s",
        remappedActionId, if (version == null || version.isEmpty()) "UNKNOWN" else version))
      return
    }
    val originalControls = currentInputAction.get().inputControls()
    val originalKeyCodes = originalControls.keycodes()
    Log.i(TAG, String.format(
      "Found input action with id %d remapped from key %s to key %s",
      remappedActionId,
      keyCodesToString(originalKeyCodes),
      keyCodesToString(remappedKeyCodes)))

    // TODO: make display changes to match controls used by the user
  }

  private fun getCurrentVersionInputAction(inputActionId: Long): Optional<InputAction> {
    for (inputGroup in InputSDKProvider.gameInputMap.inputGroups()) {
      for (inputAction in inputGroup.inputActions()) {
        if (inputAction.inputActionId().uniqueId() == inputActionId) {
          return Optional.of(inputAction)
        }
      }
    }
    return Optional.empty()
  }

  private fun getCurrentVersionInputActionFromPreviousVersion(
    inputActionId: Long, previousVersion: String
  ): Optional<InputAction7gt; {
    // TODO: add logic to this method considering the diff between the current and previous
    //  InputMap.
    return Optional.empty()
  }

  private fun keyCodesToString(keyCodes: List<Int>): String {
    val builder = StringBuilder()
    for (keyCode in keyCodes) {
      if (!builder.toString().isEmpty()) {
        builder.append(" + ")
      }
      builder.append(keyCode)
    }
    return String.format("(%s)", builder)
  }

  companion object {
    private const val TAG = "InputSDKRemappingListener"
  }
}

Java

public class InputSDKRemappingListener implements InputRemappingListener {

    private static final String TAG = "InputSDKRemappingListener";

    @Override
    public void onInputMapChanged(InputMap inputMap) {
        Log.i(TAG, "Received update on input map changed.");
        if (inputMap.inputRemappingOption() ==
                InputEnums.REMAP_OPTION_DISABLED) {
            return;
        }
        for (InputGroup inputGroup : inputMap.inputGroups()) {
            if (inputGroup.inputRemappingOption() ==
                    InputEnums.REMAP_OPTION_DISABLED) {
                continue;
            }
            for (InputAction inputAction : inputGroup.inputActions()) {
                if (inputAction.inputRemappingOption() !=
                        InputEnums.REMAP_OPTION_DISABLED) {
                    // Found InputAction remapped by user
                    processRemappedAction(inputAction);
                }
            }
        }
    }

    private void processRemappedAction(InputAction remappedInputAction) {
        // Get remapped action info
        InputControls remappedControls =
            remappedInputAction.remappedInputControls();
        List<Integer> remappedKeyCodes = remappedControls.keycodes();
        List<Integer> mouseActions = remappedControls.mouseActions();
        String version = remappedInputAction.inputActionId().versionString();
        long remappedActionId = remappedInputAction.inputActionId().uniqueId();
        Optional<InputAction> currentInputAction;
        if (version == null || version.isEmpty()
                    || version.equals(InputSDKProvider.INPUTMAP_VERSION)) {
            currentInputAction = getCurrentVersionInputAction(remappedActionId);
        } else {
            Log.i(TAG, "Detected version of user-saved input action defers " +
                    "from current version");
            currentInputAction =
                    getCurrentVersionInputActionFromPreviousVersion(
                            remappedActionId, version);
        }
        if (!currentInputAction.isPresent()) {
            Log.e(TAG, String.format(
                    "input action with id %d and version %s not found",
                    remappedActionId, version == null || version.isEmpty() ?
                            "UNKNOWN" : version));
            return;
        }
        InputControls originalControls =
                currentInputAction.get().inputControls();
        List<Integer> originalKeyCodes = originalControls.keycodes();

        Log.i(TAG, String.format(
                "Found input action with id %d remapped from key %s to key %s",
                remappedActionId,
                keyCodesToString(originalKeyCodes),
                keyCodesToString(remappedKeyCodes)));

        // TODO: make display changes to match controls used by the user
    }

    private Optional<InputAction> getCurrentVersionInputAction(
            long inputActionId) {
        for (InputGroup inputGroup :
                    InputSDKProvider.gameInputMap.inputGroups()) {
            for (InputAction inputAction : inputGroup.inputActions()) {
                if (inputAction.inputActionId().uniqueId() == inputActionId) {
                    return Optional.of(inputAction);
                }
            }
        }
        return Optional.empty();
    }

    private Optional<InputAction>
            getCurrentVersionInputActionFromPreviousVersion(
                    long inputActionId, String previousVersion) {
        // TODO: add logic to this method considering the diff between your
        // current and previous InputMap.
        return Optional.empty();
    }

    private String keyCodesToString(List<Integer> keyCodes) {
        StringBuilder builder = new StringBuilder();
        for (Integer keyCode : keyCodes) {
            if (!builder.toString().isEmpty()) {
                builder.append(" + ");
            }
            builder.append(keyCode);
        }
        return String.format("(%s)", builder);
    }
}

C#

#if PLAY_GAMES_PC

using System.Text;
using Java.Lang;
using Java.Util;
using Google.Android.Libraries.Play.Games.Inputmapping;
using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel;
using UnityEngine;

public class InputSDKRemappingListener : InputRemappingListenerCallbackHelper
{
    public override void OnInputMapChanged(InputMap inputMap)
    {
        Debug.Log("Received update on remapped controls.");
        if (inputMap.InputRemappingOption() == InputEnums.REMAP_OPTION_DISABLED)
        {
            return;
        }
        List<InputGroup> inputGroups = inputMap.InputGroups();
        for (int i = 0; i < inputGroups.Size(); i ++)
        {
            InputGroup inputGroup = inputGroups.Get(i);
            if (inputGroup.InputRemappingOption()
                    == InputEnums.REMAP_OPTION_DISABLED)
            {
                continue;
            }
            List<InputAction> inputActions = inputGroup.InputActions();
            for (int j = 0; j < inputActions.Size(); j ++)
            {
                InputAction inputAction = inputActions.Get(j);
                if (inputAction.InputRemappingOption()
                        != InputEnums.REMAP_OPTION_DISABLED)
                {
                    // Found action remapped by user
                    ProcessRemappedAction(inputAction);
                }
            }
        }
    }

    private void ProcessRemappedAction(InputAction remappedInputAction)
    {
        InputControls remappedInputControls =
                remappedInputAction.RemappedInputControls();
        List<Integer> remappedKeycodes = remappedInputControls.Keycodes();
        List<Integer> mouseActions = remappedInputControls.MouseActions();
        string version = remappedInputAction.InputActionId().VersionString();
        long remappedActionId = remappedInputAction.InputActionId().UniqueId();
        InputAction currentInputAction;
        if (string.IsNullOrEmpty(version)
                || string.Equals(
                version, InputSDKMappingProvider.INPUT_MAP_VERSION))
        {
            currentInputAction = GetCurrentVersionInputAction(remappedActionId);
        }
        else
        {
            Debug.Log("Detected version of used-saved input action defers" +
                " from current version");
            currentInputAction =
                GetCurrentVersionInputActionFromPreviousVersion(
                    remappedActionId, version);
        }
        if (currentInputAction == null)
        {
            Debug.LogError(string.Format(
                "Input Action with id {0} and version {1} not found",
                remappedActionId,
                string.IsNullOrEmpty(version) ? "UNKNOWN" : version));
            return;
        }
        InputControls originalControls = currentInputAction.InputControls();
        List<Integer> originalKeycodes = originalControls.Keycodes();

        Debug.Log(string.Format(
            "Found Input Action with id {0} remapped from key {1} to key {2}",
            remappedActionId,
            KeyCodesToString(originalKeycodes),
            KeyCodesToString(remappedKeycodes)));
        // TODO: update HUD according to the controls of the user
    }

    private InputAction GetCurrentVersionInputAction(
            long inputActionId)
    {
        List<InputGroup> inputGroups =
            InputSDKMappingProvider.gameInputMap.InputGroups();
        for (int i = 0; i < inputGroups.Size(); i++)
        {
            InputGroup inputGroup = inputGroups.Get(i);
            List<InputAction> inputActions = inputGroup.InputActions();
            for (int j = 0; j < inputActions.Size(); j++)
            {
                InputAction inputAction = inputActions.Get(j);
                if (inputAction.InputActionId().UniqueId() == inputActionId)
                {
                    return inputAction;
                }
            }
        }
        return null;
    }

    private InputAction GetCurrentVersionInputActionFromPreviousVersion(
            long inputActionId, string version)
    {
        // TODO: add logic to this method considering the diff between your
        // current and previous InputMap.
        return null;
    }

    private string KeyCodesToString(List<Integer> keycodes)
    {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < keycodes.Size(); i ++)
        {
            Integer keycode = keycodes.Get(i);
            if (builder.Length > 0)
            {
                builder.Append(" + ");
            }
            builder.Append(keycode.IntValue());
        }
        return string.Format("({0})", builder.ToString());
    }
}
#endif

InputRemappingListener, kullanıcı tarafından kaydedilen yeniden eşlenen kontroller yüklendikten sonra ve kullanıcı tuşlarını her yeniden eşlediğinde başlatma sırasında bilgilendirilir.

Başlatma

InputContexts kullanıyorsanız ilk sahneniz için kullanılan ilk bağlam da dahil olmak üzere her geçişte yeni bir bağlam ayarlayın. InputMap'unuzu kaydettikten sonra InputContext ayarını yapmanız gerekir.

Yeniden eşleme etkinlikleri hakkında bildirim almak için InputRemappingListeners kullanıyorsanız InputMappingProvider'nizi kaydettirmeden önce InputRemappingListener'nizi kaydedin. Aksi takdirde oyununuz lansman sırasında önemli etkinlikleri kaçırabilir.

Aşağıdaki örnekte API'nin nasıl başlatılacağı gösterilmektedir:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    if (isGooglePlayGamesOnPC()) {
        val inputMappingClient = Input.getInputMappingClient(this)
        // Register listener before registering the provider
        inputMappingClient.registerRemappingListener(InputSDKRemappingListener())
        inputMappingClient.setInputMappingProvider(
                InputSDKProvider())
        // Set the context after you have registered the provider.
        inputMappingClient.setInputContext(InputSDKProvider.menuSceneInputContext)
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (isGooglePlayGamesOnPC()) {
        InputMappingClient inputMappingClient =
                Input.getInputMappingClient(this);
        // Register listener before registering the provider
        inputMappingClient.registerRemappingListener(
                new InputSDKRemappingListener());
        inputMappingClient.setInputMappingProvider(
                new InputSDKProvider());
        // Set the context after you have registered the provider
        inputMappingClient.setInputContext(InputSDKProvider.menuSceneInputContext);
    }
}

C#

#if PLAY_GAMES_PC
using Google.Android.Libraries.Play.Games.Inputmapping;
using Google.Android.Libraries.Play.Games.InputMapping.ExternalType.Android.Content;
using Google.LibraryWrapper.Java;
#endif

public class GameManager : MonoBehaviour
{
#if PLAY_GAMES_PC
    private InputSDKMappingProvider _inputMapProvider =
        new InputSDKMappingProvider();
    private InputMappingClient _inputMappingClient;
#endif

    public void Awake()
    {
#if PLAY_GAMES_PC
        Context context = (Context)Utils.GetUnityActivity().GetRawObject();
        _inputMappingClient = Google.Android.Libraries.Play.Games.Inputmapping
            .Input.GetInputMappingClient(context);
        // Register listener before registering the provider.
        _inputMappingClient.RegisterRemappingListener(
            new InputSDKRemappingListener());
        _inputMappingClient.SetInputMappingProvider(_inputMapProvider);
        // Register context after you have registered the provider.
       _inputMappingClient.SetInputContext(
           InputSDKMappingProvider.menuSceneInputContext);
#endif
    }
}

Düzenle

Oyununuz kapalıyken InputMappingProvider örneğinizin ve tüm InputRemappingListener örneklerinin kaydını silin. Giriş SDK'sı, bunu yapmamanız durumunda kaynakların sızınmasını önlemek için yeterince akıllı olsa da:

Kotlin

override fun onDestroy() {
    if (isGooglePlayGamesOnPC()) {
        val inputMappingClient = Input.getInputMappingClient(this)
        inputMappingClient.clearInputMappingProvider()
        inputMappingClient.clearRemappingListener()
    }

    super.onDestroy()
}

Java

@Override
protected void onDestroy() {
    if (isGooglePlayGamesOnPC()) {
        InputMappingClient inputMappingClient =
                Input.getInputMappingClient(this);
        inputMappingClient.clearInputMappingProvider();
        inputMappingClient.clearRemappingListener();
    }

    super.onDestroy();
}

C#

public class GameManager : MonoBehaviour
{
    private void OnDestroy()
    {
#if PLAY_GAMES_PC
        _inputMappingClient.ClearInputMappingProvider();
        _inputMappingClient.ClearRemappingListener();
#endif
    }
}

Test

Oynatıcı deneyimini görüntülemek için yer paylaşımını manuel olarak açarak veya otomatik test ve doğrulama için adb kabuğunu kullanarak Giriş SDK'nızın uygulamasını test edebilirsiniz.

PC Üzerinde Google Play Games Emülatörü, giriş haritanızın doğruluğunu sık karşılaşılan hatalara karşı kontrol eder. Yinelenen benzersiz kimlikler, farklı giriş haritaları kullanma veya yeniden eşleme kurallarının başarısız olması (yeniden eşleme etkinse) gibi senaryolarda yer paylaşımında aşağıdaki hata mesajı gösterilir: Giriş SDK&#39;sı yer paylaşımı.

Komut satırında adb kullanarak giriş SDK'sı uygulamanızı doğrulayın. Geçerli giriş haritasını almak için aşağıdaki adb shell komutunu kullanın (MY.PACKAGE.NAME yerine oyununuzun adını girin):

adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME

InputMap öğenizi başarıyla kaydettiyseniz buna benzer bir çıkış görürsünüz:

Getting input map for com.example.inputsample...
Successfully received the following inputmap:
# com.google.android.libraries.play.games.InputMap@d73526e1
input_groups {
  group_label: "Basic Movement"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
    }
    unique_id: 0
  }
  input_actions {
    action_label: "Left"
    input_controls {
      keycodes: 29
      keycodes: 21
    }
    unique_id: 1
  }
  input_actions {
    action_label: "Right"
    input_controls {
      keycodes: 32
      keycodes: 22
    }
    unique_id: 2
  }
  input_actions {
    action_label: "Use"
    input_controls {
      keycodes: 33
      keycodes: 66
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 3
  }
}
input_groups {
  group_label: "Special Input"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
      keycodes: 62
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 4
  }
  input_actions {
    action_label: "Duck"
    input_controls {
      keycodes: 47
      keycodes: 20
      keycodes: 113
      mouse_actions: MOUSE_RIGHT_CLICK
      mouse_actions_value: 1
    }
    unique_id: 5
  }
}
mouse_settings {
  allow_mouse_sensitivity_adjustment: true
  invert_mouse_movement: true
}

Yerelleştirme

Giriş SDK'sı, Android'in yerelleştirme sistemini kullanmaz. Sonuç olarak, InputMap gönderirken yerelleştirilmiş dize sağlamanız gerekir. Oyun motorunuzun yerelleştirme sistemini de kullanabilirsiniz.

Proguard

Oyununuzu küçültmek için Proguard'ı kullanırken SDK'nın nihai paketinizden kaldırılmamasını sağlamak üzere Proguard yapılandırma dosyanıza aşağıdaki kuralları ekleyin:

-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }

Sırada ne var?

Giriş SDK'sını oyununuza entegre ettikten sonra PC Üzerinde Google Play Games ile ilgili diğer koşulları yerine getirmeye devam edebilirsiniz. Daha fazla bilgi için PC Üzerinde Google Play Games'i kullanmaya başlama başlıklı makaleyi inceleyin.