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

Bu belgede, PC Üzerinde Google Play Games'i destekleyen oyunlarda Input SDK'nın nasıl ayarlanacağı ve gösterileceği açıklanmaktadır. Bu görevler arasında SDK'yı oyununuza ekleme ve oyun eylemlerinin kullanıcı girişlerine atamalarını içeren bir giriş haritası oluşturma yer alır.

Başlamadan önce

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

Input SDK, oyununuzun kullandığı 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 için isteğe bağlı olarak klavye yeniden eşlemeye de izin verebilir.

Her kontrol bir InputAction (ör. "J" için "Atla") şeklindedir ve InputActions öğelerinizi InputGroups şeklinde düzenlersiniz. InputGroup, oyununuzda "Sürüş", "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 simgesini de kullanabilirsiniz.

Klavye yeniden eşlemenin sizin için otomatik olarak yapılmasını sağlayabilirsiniz. Ancak kendi kontrol yeniden eşleme arayüzünüzü sağlamayı tercih ederseniz Input SDK yeniden eşlemesini devre dışı bırakabilirsiniz.

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

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

Oyununuzda Input 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 üst karakter + sekme tuşlarına basarak kaplamaya istedikleri zaman erişebilir.

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

Kısayol tuşları tasarlamayla ilgili en iyi uygulamalar

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

  • Oyun oynarken gezinmeyi ve kontrollerin bulunabilirliğini iyileştirmek için InputActions öğelerinizi mantıksal olarak ilişkili InputGroups öğeler halinde gruplandırın.
  • Her InputGroup öğesini en fazla bir InputContext öğesine atayın. İnce ayrıntılı bir InputMap, yer paylaşımındaki kontrollerinizde gezinirken daha iyi bir deneyim sunar.
  • Oyununuzun her farklı sahne türü için bir InputContext oluşturun. Genellikle, "menü benzeri" tüm sahneleriniz için tek bir InputContext kullanabilirsiniz. Oyununuzdaki mini oyunlar veya tek bir sahne için alternatif kontroller için farklı InputContexts kullanın.
  • İki işlem aynı InputContext altında aynı anahtarı kullanacak şekilde tasarlanmışsa "Etkileşim / Ateş et" gibi etiket dizesini kullanın.
  • İki anahtar aynı InputAction ile 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 kimliği farklı olmalıdır.
  • Bir değiştirici tuş bir tuş grubuna uygulanıyorsa değiştirici tuşu birleştiren birden fazla InputActions yerine değiştirici tuşla tek bir InputAction kullanmayı tercih edin (ö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 yazdığında giriş yeniden eşleme otomatik olarak devre dışı bırakılır. Android'in oyununuzdaki metin alanlarını algılayabilmesi ve yeniden eşlenen tuşların bu alanlara müdahale etmesini önlemek için Android metin alanlarını uygulamayla ilgili en iyi uygulamaları izleyin. 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 InputContext kullanabilirsiniz.
  • Oyununuz yeniden eşlemeyi destekliyorsa tuş bağlamalarınızı güncellemenin, kullanıcı tarafından kaydedilen sürümlerle çakışabilecek hassas bir işlem olduğunu unutmayın. Mümkün olduğunda mevcut kontrollerin kimliklerini değiştirmeyin.

Yeniden eşleme özelliği

PC Üzerinde Google Play Games, Input SDK'yı kullanarak oyununuzun sağladığı tuş bağlamalarına göre klavye kontrolünü yeniden eşlemeyi destekler. Bu özellik 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 başlıklı makaleyi inceleyin).

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ının yeniden eşlediği her kontrolü oyununuzun almayı beklediği varsayılan kontrollerle eşler. Bu nedenle, oyununuzun oyuncunun yeniden eşlemesinden haberdar olması gerekmez. İsteğe bağlı olarak, yeniden eşleme etkinlikleri için bir geri arama ekleyerek klavye kontrollerini oyununuzda göstermek için kullanılan öğeleri güncelleyebilirsiniz.

Tuşu yeniden eşlemeyi deneyin.

PC Üzerinde Google Play Games, yeniden eşlenen kontrolleri her kullanıcı için yerel olarak depolar. Bu sayede, oyun oturumları arasında kontrol kalıcılığı sağlanır. Bu bilgiler yalnızca PC platformu için diskte saklanır ve mobil deneyimi etkilemez. Kontrol verileri, kullanıcı PC Üzerinde Google Play Games'i kaldırdığında veya yeniden yüklediğinde silinir. Bu veriler, birden fazla bilgisayar 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 yeniden eşleme özellikleri oyununuzda devre dışı bırakılabilir:

  • Değiştirici tuş + değiştirici olmayan tuş kombinasyonuyla oluşturulmayan ç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, tekrar eden benzersiz kimliklerle birlikte InputActions, InputGroups veya InputContexts içeriyor.

Yeniden eşlemenin 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 tuşlarını Ctrl + B tuşlarına veya A tuşunu Üst Karakter + A tuşlarına yeniden eşleyemez.
  • Yeniden eşleme, fare düğmeleriyle InputActions için 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

Yeniden eşleme özelliğini, Google Play Games PC Emülatörü'nde istediğiniz zaman aşağıdaki adb komutunu vererek etkinleştirebilirsiniz:

adb shell dumpsys input_mapping_service --set RemappingFlagValue true

Yer paylaşımı, aşağıdaki resimde gösterildiği gibi değişir:

Tuş yeniden eşleme özelliğinin etkin olduğu yer paylaşımı.

SDK'yı ekleme

Geliştirme platformunuza göre Input SDK'yı yükleyin.

Java ve Kotlin

Java veya Kotlin için Input SDK'yı, modül düzeyindeki build.gradle dosyanıza bağımlılık ekleyerek edinin:

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

Unity

Input SDK, ç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 Input SDK unitypackage dosyasını indirin. .unitypackage öğesini yüklemek için Öğeler > Paketi içe aktar > Özel Paket'i seçip indirdiğiniz dosyayı bulun.

UPM'yi kullanarak yükleme

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

OpenUPM kullanarak yükleme

Paketi OpenUPM'yi kullanarak yükleyebilirsiniz.

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

Örnek oyunlar

Input SDK ile entegrasyon örnekleri için Kotlin veya Java oyunlarında AGDK Tunnel'ı, Unity oyunlarında ise Trivial Kart'ı inceleyin.

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

InputMap oluşturup InputMappingProvider ile döndürerek tuş bağlamalarınızı kaydedin. Aşağıdaki örnekte bir InputMappingProvider açıklanmaktadır:

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 tuşu veya tuş kombinasyonunu oyun işlemine eşlemek için kullanılır. InputActions, tüm InputActions genelinde benzersiz kimliklere sahip olmalıdır.

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

Bu örnekte, boşluk tuşu Sür işlemine 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 tek tuşlu InputAction gösterilir.

İşlemler, fare girişlerini de temsil edebilir. Bu örnekte Sol tıklama, Taşı işlemi olarak ayarlanı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 MouseInputAction.

Tuş kombinasyonları, InputAction öğenize birden fazla tuş kodu iletilerek belirtilir. Bu örnekte boşluk + üst karakter, Turbo işlemine eşlenir. Bu işlem, Boşluk tuşu Drive'a eşlendiğinde 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 tuşlu InputAction.

Input SDK, tek bir işlem için fare ve tuş düğmelerini birlikte kullanmanıza olanak tanır. Bu örnekte, Shift ve sağ tıklama tuşlarına birlikte basıldığında bu örnek oyuna bir ara nokta eklendiği gösterilmektedir:

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 InputAction kombinasyonu.

InputAction'da aşağıdaki alanlar bulunur:

  • 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ştirme işlemlerini önceden yapın.
  • InputControls: Bu işlemin kullandığı giriş kontrollerini tanımlar. Kontroller, yer paylaşımındaki tutarlı gliflerle eşlenir.
  • InputActionId: InputAction'nin numara kimliğini ve sürümünü depolayan InputIdentifier nesnesi (daha fazla bilgi için İzleme Anahtarı Kimlikleri'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: Yeniden eşleme etkinliklerinde kullanıcı tarafından yeniden eşlenen tuş takımını 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, yer paylaşımında gezinmeyi ve kontrollerin bulunabilirliğini iyileştirmek için InputGroups kullanılarak mantıksal olarak ilişkili işlemlerle gruplandırılır. Her InputGroup kimliği, oyununuzdaki tüm InputGroups genelinde benzersiz olmalıdır.

Giriş işlemlerinizi gruplandırarak oyuncuların mevcut bağlamları için doğru tuş bağlamayı bulmasını kolaylaştırırsınız.

Yeniden eşlemeyi destekliyorsanız InputGroups öğesinin neyle yeniden eşlenebileceğini tanımlayabilirsiniz. Oyununuz yeniden eşlemeyi desteklemiyorsa tüm InputGroups için yeniden eşleme seçeneğini devre dışı bırakmanız gerekir. Ancak Input SDK, InputGroups'nızda yeniden eşlemeyi desteklemiyorsanız yeniden eşlemeyi kapatacak kadar akıllıdır.InputMap

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 kontrollerini 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: Bir dizi işlemi mantıksal olarak gruplandırmak için kullanılabilecek, yer paylaşımında gösterilecek 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'nin numara kimliğini ve sürümünü depolayan InputIdentifier nesnesi. Daha fazla bilgi için İzleme anahtarı kimlikleri başlıklı makaleyi inceleyin.
  • 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 nesnelerde yeniden eşleme seçeneği etkin olarak belirtilmiş olsa bile yeniden eşleme devre dışı bırakılır. Etkinleştirilirse bu gruba ait 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ımlama

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

  • Menülerde gezinmek ve oyunda hareket etmek için farklı giriş kümeleri belirtebilirsiniz.
  • Oyununuzdaki hareket şekline (ör. araba kullanma ve yürüme) bağlı olarak farklı giriş kümeleri belirtebilirsiniz.
  • Oyununuzun mevcut durumuna göre farklı giriş kümeleri belirtebilirsiniz. Örneğin, bir üst dünyada gezinmek ile tek bir seviyeyi oynamak farklı giriş kümeleri gerektirebilir.

InputContexts kullanılırken yer paylaşımında önce kullanımda olan bağlam 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: "Araba kullanma" sahnesinde, Yol kontrolleri işlemleri yer paylaşımının üst kısmında gösterilir. "Mağaza" menüsü açıldığında, "Menü kontrolleri" işlemleri yer paylaşımının üst kısmında gösterilir.

InputContexts, yer paylaşımında grupları sıralar.

Bu yer paylaşımı güncellemeleri, oyununuzun farklı noktalarında farklı bir InputContext ayarlanarak gerçekleştirilir. Bunu yapmak için:

  1. InputActions öğenizi InputGroups kullanarak mantıksal olarak ilişkili işlemlerle gruplandırma
  2. Oyununuzun farklı bölümleri için bu InputGroups öğelerini bir InputContext öğesine atayın.

InputGroups aynıInputContext olanlar, aynı anahtarın kullanıldığı yerlerde çakışan InputActions olamaz. Her birini tek bir InputContext öğesine atamak iyi bir uygulamadır.InputGroup

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'nin numara kimliğini ve sürümünü depolayan InputIdentifier nesnesi (daha fazla bilgi için İzleme Anahtarı Kimlikleri'ne bakın).
  • ActiveGroups: Bu bağlam etkin olduğunda yer paylaşımının üst kısmında kullanılacak ve gösterilecek InputGroups listesi.

Giriş eşlemesi oluşturma

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

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

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

Aşağıdaki örnekte, InputMap koleksiyonunu bildirmek için kullanılan bir InputGroups 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 bildirilen InputGroups. Gruplar, setInputContext() çağrılarak kullanılan mevcut gruplar belirtilmediği sürece yer paylaşımı üzerinde sırayla gösterilir.
  • MouseSettings: MouseSettings nesnesi, fare hassasiyetinin ayarlanabileceğini ve farenin y ekseninde ters çevrildiğini gösterir.
  • InputMapId: InputIdentifier kimlik numarasını ve InputMap sürümünü depolayan nesne (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 InputControls ile yeniden eşlemesine izin verilmeyenlerin listesi.

Önemli kimlikleri izleme

InputAction, InputGroup, InputContext ve InputMap nesneleri, benzersiz bir sayı kimliğini ve dize sürümü kimliğini depolayan bir InputIdentifier nesnesi içerir. Nesnelerinizin dize sürümünü izlemek isteğe bağlıdır ancak InputMap sürümlerini 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 örnek, InputActions veya InputGroups için 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 numarası 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 nasıl enum kullanacağınız 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ş verileri kümesini benzersiz şekilde tanımlamak için ayarlanan benzersiz bir sayı kimliği.
  • VersionString: Giriş verilerinin iki sürümü arasındaki değişiklikleri tanımlamak için ayarlanan, insan tarafından okunabilir bir sürüm dizesi.

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

Yeniden eşleme etkinlikleriyle ilgili bildirimler alarak oyununuzda kullanılan tuşlar hakkında bilgi edinin. Bu, oyununuzun işlem kontrollerini göstermek için kullanılan oyun ekranında gösterilen öğeleri güncellemesine olanak tanır.

Aşağıdaki resimde, bu davranışın bir örneği gösterilmektedir. Bu örnekte, G, P ve S tuşları sırasıyla J, X ve T olarak yeniden eşlendikten sonra oyunun kullanıcı arayüzü öğeleri, kullanıcı tarafından ayarlanan tuşları gösterecek şekilde güncellenir.

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

Bu işlev, InputRemappingListener geri çağırma işlevi kaydedilerek gerçekleştirilir. Bu özelliği uygulamak için öncelikle 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şlenmiş 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 yeni sahneye geçişte bağlamı ayarlayın. InputContext ayarını InputMap kaydettikten sonra yapmanız gerekir.

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

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 kapatıldığında InputMappingProvider örneğinizin ve tüm InputRemappingListener örneklerinin kaydını kaldırın. Input SDK, kaynak sızıntısını önleyecek kadar akıllı olsa da bunu yapmanız önerilir:

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

Oyuncu deneyimini görüntülemek için yer paylaşımını manuel olarak açarak veya otomatik test ve doğrulama için adb shell aracılığıyla Input SDK uygulamanızı test edebilirsiniz.

PC Üzerinde Google Play Games Emülatörü, giriş haritanızın doğruluğunu yaygın hatalara karşı kontrol eder. Yinelenen benzersiz kimlikler, 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: Input SDK yerleşimi.

Komut satırında adb kullanarak Input SDK uygulamanızı doğrulayın. Mevcut 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 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

Input SDK, Android'in yerelleştirme sistemini kullanmaz. Bu nedenle, InputMap gönderirken yerelleştirilmiş dizeler sağlamanız gerekir. Oyun motorunuzun yerelleştirme sistemini de kullanabilirsiniz.

Proguard

Oyununuzu küçültmek için Proguard'ı kullanırken SDK'nın son paketinizden kaldırılmaması 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?

Input SDK'yı oyununuza entegre ettikten sonra PC Üzerinde Google Play Games ile ilgili kalan tüm şartları karşılamaya devam edebilirsiniz. Daha fazla bilgi için PC Üzerinde Google Play Games'i kullanmaya başlama başlıklı makaleyi inceleyin.