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

Bu dokümanda, PC Üzerinde Google Play Games'i destekleyen oyunlarda Giriş SDK'sının nasıl ayarlanacağı ve görüntüleneceği açıklanmaktadır. Görevler, SDK'yı oyununuza eklemek ve oyundaki işlemlerin, kullanıcı girişine atamalarının yer aldığı bir giriş haritası oluşturmayı içerir.

Başlamadan önce

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

Giriş SDK'sı, PC Üzerinde Google Play Games'e oyununuzun kullandığı kontroller hakkında bilgi sağlayarak kullanıcıya gösterilebilir. Ayrıca, isteğe bağlı olarak kullanıcılar için klavyenin yeniden eşlenmesine de izin verebilir.

Her kontrol bir InputAction (ör. "Atlama için "J") şeklindedir ve InputActions öğenizi InputGroups olarak düzenlersiniz. InputGroup, oyununuzdaki "Araba", "Yürüyüş" veya "Ana Menü" gibi farklı bir modu temsil edebilir. Ayrıca oyunun farklı noktalarında hangi grupların etkin olduğunu belirtmek için InputContexts kullanabilirsiniz.

Klavyenin yeniden eşlenmesini sizin için otomatik olarak işlenecek şekilde etkinleştirebilirsiniz, ancak kendi kontrol yeniden eşleme arayüzünüzü sağlamayı tercih ederseniz Giriş SDK'sı yeniden eşlemesini devre dışı bırakabilirsiniz.

Aşağıdaki sıra şemasında, Giriş SDK'sının API'sinin nasıl çalıştığı açıklanmaktadır:

Giriş SDK API'sini ve Android cihazla etkileşimini çağıran bir oyun uygulamasının dizi diyagramı.

Oyununuzda Giriş SDK'sı uygulandığı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 istedikleri zaman Üst Karakter + Sekme tuşlarına basarak yer paylaşımına erişebilir.

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

Tuş bağlamalarını tasarlamayla ilgili en iyi uygulamalar

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

  • Oyun sırasında kontrollerin gezinmesini ve keşfedilebilirliğini iyileştirmek için InputActions öğenizi mantıksal olarak alakalı InputGroups olarak gruplandırın.
  • Her InputGroup öğesini en fazla bir InputContext öğesine atayın. Hassas bir şekilde ayrıntılandırılan InputMap, yer paylaşımındaki kontrollerinizde daha iyi bir gezinme deneyimi sunar.
  • Oyununuzun her farklı sahne türü için bir InputContext oluşturun. Genellikle tüm "menü benzeri" sahneleriniz için tek bir InputContext kullanabilirsiniz. Oyununuzdaki tüm mini oyunlar veya tek bir sahnenin alternatif kontrolleri için farklı InputContexts kullanın.
  • İki işlem aynı InputContext altında aynı anahtarı kullanacak şekilde tasarlandıysa "Etkileşim / Tetikle" gibi etiket dizesini kullanın.
  • İki anahtar aynı InputAction öğesine bağlanacak şekilde tasarlanmışsa oyununuzda aynı işlemi gerçekleştiren 2 farklı InputActions kullanın. Her iki InputActions için de aynı etiket dizesini kullanabilirsiniz ancak dizenin kimliği farklı olmalıdır.
  • Bir tuş grubuna değiştirici tuş uygulanırsa değiştirici tuşu birleştiren birden fazla InputActions yerine değiştirici tuşa sahip tek bir InputAction kullanma seçeneğini değerlendirin (örneğin: Üst Karakter ve W, A, S, D yerine Üst Karakter + W, Üst Karakter + A, Üst Karakter + S, Üst Karakter + D kullanın).
  • Kullanıcı metin alanlarına metin yazdığında giriş yeniden eşleme otomatik olarak devre dışı bırakılır. Android'in oyununuzdaki metin alanlarını algılayabilmesini ve yeniden eşlenen tuşların bunlara müdahale etmesini önlemesini sağlamak için Android metin alanlarını uygulamayla ilgili en iyi uygulamaları takip edin. Oyununuzun geleneksel olmayan metin alanları kullanması gerekiyorsa manuel olarak yeniden eşlemeyi devre dışı bırakmak için setInputContext() ile birlikte boş bir InputGroups listesi içeren InputContext kullanabilirsiniz.
  • Oyununuz yeniden eşlemeyi destekliyorsa anahtar bağlamalarınızı, kullanıcının kaydettiği sürümlerle çakışabilecek hassas bir işlem olarak güncelleyin. Mümkün olduğunda mevcut kontrollerin kimliklerini değiştirmekten kaçının.

Yeniden eşleme özelliği

PC Üzerinde Google Play Games, oyununuzun Giriş SDK'sı kullanarak sağladığı tuş bağlamalarına göre klavye kontrolü yeniden eşlemesini destekler. İsteğ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 üzere InputMap için yeniden eşleme seçeneğini devre dışı bırakmanız yeterlidir (daha fazla bilgi için Giriş Haritası oluşturma bölümüne bakın).

Bu özelliğe erişmek için kullanıcıların yer paylaşımını açıp yeniden eşlemek istedikleri işlemi tıklamaları gerekir. PC Üzerinde Google Play Games her yeniden eşleme etkinliğinden sonra kullanıcı tarafından yeniden eşlenen her kontrolü, oyununuzun almayı beklediği varsayılan kontrollerle eşler. Bu nedenle oyununuzun, oyuncunun yeniden eşlediğini bilmesi gerekmez. İsteğe bağlı olarak, etkinlikleri yeniden eşlemek için bir geri çağırma ekleyerek oyununuzda klavye kontrollerini görüntülemek için kullanılan öğeleri güncelleyebilirsiniz.

Anahtarı yeniden eşlemeye çalış

PC Üzerinde Google Play Games, yeniden eşlenen kontrolleri her kullanıcı için yerel olarak depolayarak oyun oturumları genelinde kontrol kalıcılığını sağlar. Bu bilgiler yalnızca PC platformu için diskte depolanır ve mobil deneyimi etkilemez. Kullanıcı, PC Üzerinde Google Play Games'i kaldırdıktan veya yeniden yükledikten sonra kontrol verileri 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şlemeyle ilgili kısıtlamalar

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

  • Değiştirici tuş + değiştirici olmayan bir tuştan oluşmayan çok tuşlu 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

Tuş bağlamalarınızı yeniden eşlemek için tasarlarken aşağıdaki kısıtlamaları göz önünde bulundurun:

  • Tuş kombinasyonlarıyla yeniden eşleme desteklenmiyor. Örneğin, kullanıcılar Üst Karakter + A'yı Ctrl + B veya A'yı Üst Karakter + A olarak yeniden eşleyemez.
  • InputActions için fare düğmeleri kullanılarak yeniden eşleme desteklenmiyor. Örneğin, ÜstKrktr + Sağ tıklama yeniden eşlenemez.

PC Üzerinde Google Play Games Emülatörü'nde anahtarların yeniden eşlenmesini test edin

Aşağıdaki adb komutunu göndererek PC Üzerinde Google Play Games Emülatörü'ndeki 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 resimde olduğu gibi değişir:

Tuş yeniden eşlemenin etkin olduğu yer paylaşımı.

SDK'yı ekleyin

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

Java ve Kotlin

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

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

Birlik

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

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

.unitypackage uygulamasını yükleyin

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 öğesini yükleyebilirsiniz.

UPM kullanarak yükle

Alternatif olarak Unity'nin Paket Yöneticisi'ni kullanarak .tgz dosyasını indirip bağımlılıklarını yükleyerek paketi yükleyebilirsiniz:

OpenUPM kullanarak yükleme

Paketi OpenUPM kullanarak yükleyebilirsiniz.

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

Örnek oyunlar

Giriş SDK'sı ile nasıl entegrasyon yapılacağıyla ilgili örnekler için Kotlin veya Java oyunları için AGDK Tunnel'a, Unity oyunları içinse Trivial Kart'a göz atın.

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

Bir InputMap oluşturup InputMappingProvider ile iade ederek anahtar bağlamalarınızı kaydedin. Aşağıdaki örnekte bir InputMappingProvider özetlenmektedir:

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ımlayın

InputAction sınıfı, anahtar veya tuş kombinasyonunu bir oyun işlemiyle eşlemek için kullanılır. InputActions, InputActions genelinde benzersiz kimliklere sahip olmalıdır.

Yeniden eşlemeyi destekliyorsanız hangi InputActions öğesinin yeniden eşlenebileceğini tanımlayabilirsiniz. Oyununuz yeniden eşlemeyi desteklemiyorsa tüm InputActions öğeleriniz için yeniden eşleme seçeneğini devre dışı olarak ayarlamanız gerekir. Ancak Giriş SDK'sı, InputMap cihazınızda desteklemiyorsanız yeniden eşlemeyi kapatacak kadar akıllıdır.

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

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 de fare girişlerini temsil edebilir. Aşağıdaki örnekte Sol tıklama, Taşı işlemine ayarlanmaktadı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ş İşlemi.

Anahtar kombinasyonları, InputAction öğenize birden fazla anahtar kodu iletilerek belirtilir. Bu örnekte boşluk + üst karakter, Boşluk Drive ile eşlendiğinde bile çalışan Turbo işlemiyle eşlenmiştir.

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 tuşlu InputAction.

Giriş SDK'sı, tek bir işlem için fare ve tuş düğmelerini birlikte kullanabilmenizi sağlar. Bu örnek, bu örnek oyunda birlikte basıldığında Üst Karakter ve Sağ tıklama'nın bir referans noktası eklediğini göstermektedir:

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örüntülenen tuş + fare InputAction kombinasyonu.

InputAction aşağıdaki alanlara sahiptir:

  • ActionLabel: Kullanıcı arayüzünde bu işlemi temsil edecek şekilde görüntülenen dize. Yerelleştirme otomatik olarak yapılmadığından yerelleştirmeyi önceden yapın.
  • InputControls: Bu işlemde kullanılan giriş denetimlerini tanımlar. Kontroller, yer paylaşımındaki tutarlı gliflerle eşlenir.
  • InputActionId: InputAction sayı 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ştirilmediğini tanımlar. Oyununuz yeniden eşlemeyi desteklemiyorsa bu alanı atlayabilir veya devre dışı olarak ayarlayabilirsiniz.
  • RemappedInputControls: Kullanıcının etkinlikleri yeniden eşlemede ayarladığı yeniden eşlenen anahtarı okumak için kullanılan salt okunur InputControls nesnesi (etkinlikleri yeniden eşlemeyle ilgili 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 listesidir. Bunlar Unity için KeyEvent veya 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ımlayın

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

Giriş işlemlerinizi gruplar halinde düzenleyerek bir oyuncunun mevcut bağlamı için doğru tuş bağlantısını bulmasını kolaylaştırırsınız.

Yeniden eşlemeyi destekliyorsanız hangi InputGroups öğesinin yeniden eşlenebileceğini tanımlayabilirsiniz. Oyununuz yeniden eşlemeyi desteklemiyorsa tüm InputGroups öğeleriniz için yeniden eşleme seçeneğini devre dışı olarak ayarlamanız gerekir. Ancak Giriş SDK'sı, InputMap cihazınızda desteklemiyorsanız yeniden eşlemeyi kapatacak 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 denetimlerini ve Menü denetimleri giriş gruplarını içeren bir Giriş Haritasını gösteren yer paylaşımı.

InputGroup şu alanlara sahiptir:

  • GroupLabel: Yer paylaşımında gösterilecek ve bir dizi işlemi mantıksal olarak gruplandırmak için kullanılabilecek bir dizedir. Bu dize otomatik olarak yerelleştirilmez.
  • InputActions: Önceki adımda tanımladığınız InputAction nesnelerin listesi. Tüm bu işlemler, grup başlığı altında görsel olarak görüntülenir.
  • InputGroupId: InputGroup öğesinin sayı 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 nesnelerinin yeniden eşleme seçeneği etkin olsa bile yeniden eşleme devre dışı olur. Etkinleştirilirse bu gruba ait olan tüm işlemler, tek tek işlemler tarafından devre dışı bırakılmadığı sürece yeniden eşlenebilir.

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

InputContexts, oyununuzun farklı sahneler için farklı klavye kontrolleri kullanmasına olanak tanır. Örneğin:

  • Menülerde gezinmek ve oyunda hareket etmek için farklı giriş grupları belirtebilirsiniz.
  • Araba kullanma veya yürüme gibi, oyununuzdaki hareket moduna bağlı olarak farklı giriş grupları belirtebilirsiniz.
  • Oyununuzun mevcut durumuna göre farklı giriş grupları belirtebilirsiniz. Örneğin, dünya üzerinde gezinme veya bireysel seviyeyi oynama gibi.

InputContexts kullanılırken yer paylaşımı ilk olarak kullanımdaki bağlam gruplarını gösterir. Bu davranışı etkinleştirmek için setInputContext() çağrısı yaparak oyununuz farklı bir sahneye girdiğinde bağlamı ayarlayın. Aşağıdaki resimde bu davranış gösterilmektedir: "Arabayla" sahnesinde, Yol kontrolleri işlemleri yer paylaşımının üst kısmında gösterilir. "Mağaza" menüsünü açtığınızda, yer paylaşımının üst kısmında "Menü kontrolleri" işlemleri görüntülenir.

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

Bu yer paylaşımı güncellemeleri, oyununuzun farklı noktalarında farklı bir InputContext ayarlayarak elde edilir. Bunun için:

  1. InputGroups kullanarak InputActions öğenizi mantıksal olarak alakalı işlemlerle gruplandırın
  2. Bu InputGroups için oyununuzun farklı bölümleri için bir InputContext atayın

Aynı anahtara ait InputGroups öğelerdeInputContextaynı anahtarın kullanıldığı durumlarda çakışmalar InputActions olamaz. Her InputGroup öğesini tek bir InputContext öğesine atamak iyi bir uygulamadır.

Aşağıdaki örnek kod, InputContext mantığını gösterir:

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 şu alanlara sahiptir:

  • LocalizedContextLabel: Bağlama ait grupları açıklayan bir dize.
  • InputContextId: InputContext sayı 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 yer paylaşımının üst kısmında kullanılacak ve görüntülenecek InputGroups listesi.

Giriş haritası oluşturma

InputMap, bir oyundaki mevcut tüm InputGroup nesnelerinin ve dolayısıyla, bir oyuncunun gerçekleştirmeyi bekleyebileceği tüm InputAction nesnelerinin koleksiyonudur.

Anahtar bağlamalarınızı bildirirken 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, InputGroups koleksiyonunu bildirmek için kullanılan bir InputMap derlenmektedir.

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 şu alanlara sahiptir:

  • InputGroups: oyununuz tarafından bildirilen Giriş Grupları. Şu anda setInputContext() çağrısı yapan mevcut gruplar belirtilmedikçe gruplar, yer paylaşımında sıralı olarak görüntülenir.
  • MouseSettings: MouseSettings nesnesi, fare hassasiyetinin ayarlanabileceğini ve farenin y ekseninde ters çevrilmiş olduğunu gösterir.
  • InputMapId: InputMap sayı 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şlemesine izin verilmeyecek InputControls listesi.

Anahtar kimliklerini izle

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 öğelerinizin sürümlerini izlemeniz önerilir. Dize sürümü sağlanmazsa dize boş olur. InputMap nesneleri için dize sürümü gereklidir.

Aşağıdaki örnek, InputActions veya InputGroups öğesine bir dize sürümü atar:

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 nesne sayı kimlikleri, InputMap içindeki tüm InputActions genelinde benzersiz olmalıdır. Benzer şekilde, InputGroup nesne kimlikleri bir InputMap içindeki tüm InputGroups genelinde benzersiz olmalıdır. Aşağıdaki örnekte, nesnenizin benzersiz kimliklerini izlemek için enum öğesinin 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 şu alanlara sahiptir:

  • UniqueId: belirli bir giriş verileri kümesini benzersiz şekilde tanımlamak için ayarlanmış benzersiz bir sayı kimliğidir.
  • VersionString: Giriş verisi değişikliklerinin 2 sürümü arasındaki giriş verilerinin bir sürümünü tanımlamak için ayarlanmış, okunabilir bir sürüm dizesidir.

Etkinliklerin yeniden eşlenmesiyle ilgili bildirim alın (İsteğe bağlı)

Oyununuzda kullanılan anahtarlar hakkında bilgi edinmek için yeniden eşleme etkinlikleriyle ilgili bildirimler alın. Bu şekilde 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ı sırasıyla J, X ve T olarak yeniden eşlendikten sonra, oyunun kullanıcı arayüzü öğelerinin kullanıcı tarafından ayarlanan anahtarları görüntüleyecek şekilde güncellendiği bir örnek gösterilmektedir.

Kullanıcı arayüzü, InputRemappingListener geri çağırmasını kullanarak etkinliklerin yeniden eşlenmesine tepki veriyor.

Bu işlev, bir InputRemappingListener geri çağırmanın kaydedilmesiyle gerçekleştirilir. 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 kontrolleri yükledikten sonra ve kullanıcıların anahtarlarını yeniden eşlediği her seferde başlatma sırasında bilgilendirilir.

Başlatma

InputContexts kullanıyorsanız ilk sahnenizde kullanılan ilk bağlam da dahil olmak üzere yeni bir sahneye geçişin bağlamını ayarlayın. InputMap kaydettirildikten sonra InputContext ayarlamanız gerekir.

Etkinliklerin yeniden eşlenmesiyle ilgili bildirim almak için InputRemappingListeners kullanıyorsanız InputMappingProvider cihazınızı kaydetmeden önce InputRemappingListener cihazınızı 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

Giriş SDK'sı aşağıdaki işlemleri yapmazsanız kaynak sızıntısını önleyecek kadar akıllı olmasına rağmen oyununuz kapatıldığında InputMappingProvider örneğinizin ve tüm InputRemappingListener örneğinizin kaydını iptal edin:

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'sı uygulamanızı test edebilirsiniz.

PC Üzerinde Google Play Games Emülatörü, giriş haritanızın doğruluğunu yaygın hatalara göre kontrol eder. Benzersiz kimliklerin yinelenmesi, farklı giriş haritaları kullanma veya yeniden eşleme kurallarında başarısız olma (yeniden eşleme etkinse) gibi senaryolarda yer paylaşımı aşağıdaki gibi bir hata mesajı gösterir: Giriş SDK&#39;sı yer paylaşımı.

Komut satırında adb komutunu 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ı yazın):

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

InputMap cihazınızı başarıyla kaydettiyseniz aşağıdakine 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 kullanmıyor. Bu nedenle, InputMap gönderirken yerelleştirilmiş dizeler sağlamanız gerekir. Oyun motorunuzun yerelleştirme sistemini de kullanabilirsiniz.

Uzman

Oyununuzu küçültmek için ProGuard'ı kullanırken SDK'nın nihai paketinizden çıkarılmasını önlemek için 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 gereksinimlerinin tamamına devam edebilirsiniz. Daha fazla bilgi için PC Üzerinde Google Play Games'i kullanmaya başlama başlıklı makaleyi inceleyin.