يصف هذا المستند كيفية إعداد وعرض SDK للإدخال في الألعاب المتوافقة مع برنامج "ألعاب Google Play على الكمبيوتر". تتضمن المهام إضافة حزمة SDK للعبتك وإنشاء خريطة إدخال تحتوي على مهام ألعاب-إجراءات-إدخال-المستخدمين.
قبل البدء
قبل إضافة "حزمة تطوير البرامج (SDK) للإدخال" إلى لعبتك، عليك التوافق مع هذه الأجهزة إدخال لوحة المفاتيح والماوس باستخدام مفتاح محرّك لعبتك إدخال نظام إدخال.
توفّر "حزمة تطوير البرامج (SDK) للإدخال" معلومات إلى برنامج "ألعاب Google Play على الكمبيوتر" حول وعناصر التحكم التي تستخدمها لعبتك، ليتم عرضها للمستخدم. يمكنه أيضًا للسماح بإعادة تخصيص لوحة المفاتيح للمستخدمين اختياريًا.
يُعد كل عنصر تحكم InputAction
(على سبيل المثال، "J" لعبارة "Jump") كما تنظم
InputActions
إلى InputGroups
. قد يمثل InputGroup
قيمة مختلفة
الوضع في لعبتك، مثل "القيادة" أو "المشي" أو "القائمة الرئيسية". يمكنك أيضًا
استخدِم InputContexts
للإشارة إلى المجموعات النشطة في نقاط مختلفة من
باللعبة.
يمكنك تفعيل إعادة تخصيص لوحة المفاتيح ليتم التعامل معها تلقائيًا، ولكن إذا وكنت تفضل توفير واجهة لإعادة تخصيص التحكم الخاصة بك، فيمكنك بعد ذلك تعطيل إعادة تخصيص حزمة تطوير البرامج (SDK) للإدخال.
يوضّح الرسم البياني للتسلسل التالي طريقة عمل واجهة برمجة التطبيقات لحزمة تطوير البرامج (SDK) للإدخال:
عندما تنفّذ لعبتك "حزمة تطوير البرامج (SDK) للإدخال"، تظهر عناصر التحكّم. في طبقة "ألعاب Google Play على الكمبيوتر"
إعلان يظهر على سطح الفيديو في برنامج "ألعاب Google Play على الكمبيوتر"
يعرض تراكب "ألعاب Google Play على الكمبيوتر" ("التراكب") عناصر التحكّم. محددة من خلال لعبتك. يمكن للمستخدمين الوصول إلى التراكب في أي وقت من خلال الضغط على Shift + Tab.
أفضل الممارسات لتصميم روابط المفاتيح
عند تصميم روابط المفاتيح، ضع في اعتبارك أفضل الممارسات التالية:
- تجميع
InputActions
فيInputGroups
مرتبط منطقيًا لتحسينه التنقل وقابلية اكتشاف عناصر التحكم أثناء اللعب. - عليك تخصيص كل
InputGroup
إلىInputContext
واحد على الأكثر. حبيبات دقيقة تقدّم ميزةInputMap
تجربة أفضل للتنقل بين عناصر التحكّم من خلال التراكب. - أنشِئ
InputContext
لكل نوع مشهد مختلف في لعبتك. يمكنك عادةً استخدامInputContext
واحدة لكل "ما يشبه قائمة الطعام". المشاهد. استخدِمInputContexts
مختلفة لأي ألعاب مصغّرة في لعبتك أو في عناصر تحكم بديلة لمشهد واحد. - إذا تم تصميم إجراءين لاستخدام نفس المفتاح تحت
InputContext
، استخدِم سلسلة التصنيف مثل "تفاعل أو إطلاق النار". - إذا كان هناك مفتاحان مصمّمان لربطهما بجهاز
InputAction
نفسه، استخدِم المفتاح 2InputActions
مختلفة تؤدي الإجراء نفسه في لعبتك. يمكنك استخدام سلسلة التصنيف نفسها لكلتاInputActions
، ولكن يجب أن يكون رقم التعريف الخاص بها مختلفة. - في حال تطبيق مفتاح تعديل على مجموعة من المفاتيح، ننصحك باستخدام مفتاح واحد
InputAction
باستخدام مفتاح التعديل بدلاً من عناصرInputActions
المتعددة التي الجمع بين مفتاح التعديل (مثال: استخدِم Shift وW وA وS وD بدلاً من ذلك Shift + W وShift + A وShift + S وShift + D). - يتم تلقائيًا إيقاف إعادة تخصيص الإدخالات عندما يكتب المستخدم نصًا.
الحقول. اتّباع أفضل الممارسات لتنفيذ حقول Android النصية لضمان
بإمكان Android رصد الحقول النصية في لعبتك ومنع المفاتيح المُعاد تخصيصها
من التدخل معها. يجب أن تستخدم اللعبة نصوصًا غير تقليدية
يمكنك استخدام
setInputContext()
معInputContext
تحتوي على قائمة فارغة تتضمّنInputGroups
لإيقاف إعادة التخصيص يدويًا. - إذا كانت لعبتك تتيح إعادة التخصيص، يمكنك تعديل عمليات ربط المفاتيح عملية حساسة قد تتعارض مع النُسخ المحفوظة للمستخدم. تجنب تغيير معرفات عناصر التحكم الحالية متى أمكن.
ميزة إعادة التخصيص
يتيح برنامج "ألعاب Google Play على الكمبيوتر" إعادة تخصيص عناصر التحكّم بلوحة المفاتيح استنادًا إلى المفتاح
التي توفّرها لعبتك باستخدام حِزمة تطوير البرامج (SDK) للإدخال. يعد هذا اختياريًا
يمكن أن يتم إيقافه تمامًا. على سبيل المثال، يمكنك توفير لوحة المفاتيح الخاصة بك
لإعادة تخصيص واجهة المستخدم. لإيقاف إعادة تخصيص لعبتك، عليك فقط تحديد
تم إيقاف خيار إعادة التخصيص لجهاز InputMap
(راجع
إنشاء خريطة الإدخال للحصول على مزيد من المعلومات).
للوصول إلى هذه الميزة، يحتاج المستخدمون إلى فتح التراكب ثم النقر على الإجراء ما يريدون إعادة تخصيصه. بعد كل حدث لإعادة تخصيص خرائط برنامج "ألعاب Google Play على الكمبيوتر" كل عنصر تحكّم مُعاد تخصيصه للمستخدم لعناصر التحكّم التلقائية التي تتوقعها لعبتك التي تتلقاها، حتى لا تكون اللعبة على دراية بعملية إعادة تخصيص اللاعبين. إِنْتَ يمكنك تعديل الأصول المستخدمة لعرض عناصر تحكم لوحة المفاتيح في لعبتك من خلال إضافة استدعاء لإعادة تخصيص الأحداث.
يخزِّن برنامج "ألعاب Google Play على الكمبيوتر" عناصر التحكّم المُعاد تخصيصها محليًا لكل مستخدم. مما يتيح القدرة على التحكم في جلسات الألعاب. هذه المعلومات محفوظة على القرص لنظام التشغيل PC فقط ولا تؤثر على تجربة الهاتف المحمول. يتم حذف بيانات عنصر التحكّم عندما يلغي المستخدم تثبيت برنامج "ألعاب Google Play على الكمبيوتر" أو يعيد تثبيته. ولا تكون هذه البيانات مستمرة على عدة أجهزة كمبيوتر.
لإتاحة ميزة إعادة التخصيص في لعبتك، تجنَّب القيود التالية:
قيود إعادة التخصيص
يمكن إيقاف ميزات إعادة تخصيص المفاتيح في لعبتك إذا كانت عمليات ربط المفاتيح تحتوي على أي مما يلي: في الحالات التالية:
InputActions
مفاتيح متعددة لا تتألف من مفتاح تعديل + a مفتاح غير معدل. على سبيل المثال، يكون Shift + A صالحًا ولكن A + B، Ctrl + Alt أو Shift + A + Tab غير متاح.- يتضمّن
InputMap
InputActions
أوInputGroups
أوInputContexts
. بمعرّفات فريدة متكررة.
حدود إعادة التخصيص
عند تصميم روابط المفاتيح لإعادة التعيين، ضع في اعتبارك ما يلي: القيود:
- لا يمكن إعادة التخصيص إلى مجموعات المفاتيح. على سبيل المثال، لا يستطيع المستخدمون أعِد ضبط Shift + A على Ctrl + B أو A إلى Shift + A.
- لا يمكن إعادة تخصيص "
InputActions
" باستخدام أزرار الماوس. بالنسبة على سبيل المثال، لا يمكن إعادة تخصيص Shift + النقر بزر الماوس الأيمن.
اختبار إعادة تخصيص المفاتيح في محاكي برنامج "ألعاب Google Play على الكمبيوتر"
يمكنك في أي وقت تفعيل ميزة إعادة التخصيص في محاكي "ألعاب Google Play على الكمبيوتر" من خلال إصدار أمر adb التالي:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
يتغير التراكب كما في الصورة التالية:
إضافة حزمة SDK
ثبِّت "حزمة تطوير البرامج (SDK) للإدخال" وفقًا لمنصّة التطوير التي تستخدمها.
Java وKotlin
احصل على حزمة SDK للإدخال لـ Java أو Kotlin عن طريق إضافة تبعية إلى
ملف build.gradle
على مستوى الوحدة:
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.0-beta'
...
}
الانسجام
حزمة تطوير البرامج (SDK) للإدخال هي حزمة Unity عادية تتضمّن العديد من التبعيات.
مطلوب تثبيت الحزمة التي تحتوي على جميع التبعيات. تتوفر عدة طرق لتثبيت الحزم.
تثبيت ".unitypackage
"
تنزيل ملف unitypackage لحزمة تطوير البرامج (SDK)
مع كل تبعياته. يمكنك تثبيت ".unitypackage
" من خلال النقر على
مواد العرض > استيراد الحزمة > الحزمة المخصّصة وتحديد موقع الملف الذي نزّلته
التثبيت باستخدام UPM
وبدلاً من ذلك، يمكنك تثبيت الحزمة باستخدام
مدير حزم Unity من خلال
جارٍ تنزيل .tgz
وتثبيت ملحقاته:
- com.google.external-dependency-manager-1.2.172
- com.google.librarywrapper.java-0.2.0
- com.google.librarywrapper.openjdk8-0.2.0
- com.google.android.libraries.play.games.inputmapping-1.1.0-beta
التثبيت باستخدام OpenUPM
يمكنك تثبيت الحزمة باستخدام OpenUPM.
$ openupm add com.google.android.libraries.play.games.inputmapping
نماذج ألعاب
للحصول على أمثلة حول كيفية الدمج مع حزمة أدوات تطوير البرامج (SDK) للإدخال، يُرجى الاطّلاع على نفق AGDK لألعاب Kotlin أو Java Trivial Kart من ألعاب Unity.
إنشاء روابط المفاتيح
يمكنك تسجيل عمليات ربط المفاتيح من خلال إنشاء InputMap
وعرضها باستخدام
InputMappingProvider
يوضح المثال التالي
InputMappingProvider
:
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
تحديد إجراءات الإدخال
تُستخدَم الفئة InputAction
لربط مفتاح أو مجموعة مفاتيح بلعبة معيّنة.
اتخاذ القرار. يجب أن يكون لدى InputActions
معرّفات فريدة في جميع InputActions
.
إذا كنت تدعم إعادة التخصيص، يمكنك تحديد InputActions
.
وإعادة تخصيصه. إذا كانت لعبتك لا تتيح إعادة التخصيص، عليك ضبط إعدادات إعادة التخصيص.
تم إيقاف الخيار لجميع InputActions
، ولكن حزمة تطوير البرامج (SDK) للإدخال
وذكاء بما يكفي لإيقاف إعادة التخصيص إذا لم تكن تدعمها في
InputMap
يربط هذا المثال مفتاح
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 );
ويمكن أن تمثل الإجراءات إدخالات الماوس أيضًا. يضبط هذا المثال خيار النقر بزر الماوس الأيسر على إجراء نقل:
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 );
يتم تحديد مجموعات المفاتيح من خلال تمرير رموز مفاتيح متعددة إلى
InputAction
في هذا المثال، تمّ تعيين
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 );
تتيح لك حزمة تطوير البرامج (SDK) للإدخال مزج أزرار الماوس والمفاتيح معًا
إجراء واحد. يشير هذا المثال إلى أنّ المفتاحَين
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 );
يحتوي الإدخالAction على الحقول التالية:
ActionLabel
: السلسلة المعروضة في واجهة المستخدم لتمثيل هذا الإجراء. لا تتم عملية الأقلمة تلقائيًا، لذا يجب تنفيذ أي أقلمة المقدمة.InputControls
: تحدّد عناصر تحكّم الإدخال التي يستخدمها هذا الإجراء. تشير رسالة الأشكال البيانية تعيين عناصر التحكم إلى رموز رسومية متسقة في التراكب.InputActionId
: عنصرInputIdentifier
يخزِّن رقم تعريف الرقم والإصدار منInputAction
(اطّلع على أرقام تعريف مفاتيح التتبُّع لمزيد من المعلومات المعلومات).InputRemappingOption
: أحدInputEnums.REMAP_OPTION_ENABLED
أوInputEnums.REMAP_OPTION_DISABLED
تُحدِّد ما إذا كان الإجراء مفعَّلاً لإعادة التخصيص. إذا كانت لعبتك لا تتيح إعادة التخصيص، يمكنك تخطي هذا الحقل أو قم ببساطة بتعيينه معطلاً.RemappedInputControls
: كائنInputControls
للقراءة فقط يُستخدَم لقراءة المفتاح الذي تمت إعادة تخصيصه من قِبل المستخدم في إعادة تخصيص الأحداث (يُستخدَم في تلقّي إشعارات بشأن إعادة تخصيص الأحداث).
يمثل InputControls
المدخلات المرتبطة بإجراء ويحتوي على
الحقول التالية::
AndroidKeycodes
: هي قائمة من الأعداد الصحيحة التي تمثّل إدخالات لوحة المفاتيح المرتبطة بإجراء ما. يتم تحديدها في KeyEvent أو فئة AndroidKeycode من أجل Unity.MouseActions
: قائمة بقيمMouseAction
التي تمثّل إدخالات الماوس المرتبطة بهذا الإجراء.
تحديد مجموعات الإدخال
يتم تجميع InputActions
مع إجراءات ذات صلة منطقيًا باستخدام InputGroups
تحسين التنقل وعناصر التحكم في قابلية اكتشاف التراكب. على كل
يجب أن يكون رقم تعريف "InputGroup
" فريدًا على مستوى كل InputGroups
في لعبتك.
ومن خلال تنظيم إجراءات الإدخال في مجموعات، يمكنك تسهيل للعثور على ربط المفتاح الصحيح للسياق الحالي.
إذا كنت تدعم إعادة التخصيص، يمكنك تحديد InputGroups
.
وإعادة تخصيصه. إذا كانت لعبتك لا تتيح إعادة التخصيص، عليك ضبط إعدادات إعادة التخصيص.
تم إيقاف الخيار لجميع InputGroups
، ولكن حزمة تطوير البرامج (SDK) للإدخال
وذكاء بما يكفي لإيقاف إعادة التخصيص إذا لم تكن تدعمها في
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 );
يعرض المثال التالي عناصر التحكم في الطريق وعناصر التحكم في القائمة مجموعات الإدخال في التراكب:
يحتوي InputGroup
على الحقول التالية:
GroupLabel
: سلسلة يتم عرضها في التراكب ويمكن استخدامها وتجميع مجموعة من الإجراءات بشكل منطقي. هذه السلسلة ليست تلقائية مترجَمة.InputActions
: قائمة تضمInputAction
من العناصر التي تم تحديدها في السابق . ويتم عرض كل هذه الإجراءات بصريًا أسفل عنوان المجموعة.InputGroupId
: عنصرInputIdentifier
يخزِّن رقم تعريف الرقم منInputGroup
. اطّلع على أرقام تعريف مفاتيح التتبّع لمعرفة مزيد من المعلومات.InputRemappingOption
: أحدInputEnums.REMAP_OPTION_ENABLED
أوInputEnums.REMAP_OPTION_DISABLED
في حال الإيقاف، سيتم إرسال جميعInputAction
ستتوقف إعادة تخصيص العناصر التي تنتمي إلى هذه المجموعة حتى إذا وتحديد خيار إعادة التعيين. وفي حال تفعيل هذا الإعداد، سيتم تنفيذ إلى هذه المجموعة يمكن إعادة تحديده ما لم يحدد هذا الفرد مناسبة.
تحديد سياقات الإدخال
تسمح InputContexts
للعبتك باستخدام مجموعة مختلفة من عناصر التحكم بلوحة المفاتيح
مشاهد مختلفة للعبتك. مثلاً:
- يمكنك تحديد مجموعات مختلفة من الإدخالات للتنقل بين القوائم بدلاً من نقلها في اللعبة.
- يمكنك تحديد مجموعات مختلفة من الإدخالات بناءً على وضع التنقل في لعبتك، مثل القيادة والمشي
- ويمكنك تحديد مجموعات مختلفة من الإدخالات بناءً على الحالة الحالية مثل التنقل في عالم علوي مقابل لعب مستوى فردي.
عند استخدام InputContexts
، يعرض المركّب أولاً مجموعات السياق
قيد الاستخدام. لتفعيل هذا السلوك، يمكنك طلب setInputContext()
لضبط
سياقًا كلما انتقلت لعبتك إلى مشهد مختلف الصورة التالية
هذا السلوك: في نموذج "القيادة" المشهد، وعناصر التحكم في الطريق
يتم عرض الإجراءات أعلى التراكب. عند فتح "المتجر" القائمة،
"عناصر التحكّم في القائمة" يتم عرض الإجراءات أعلى التراكب.
يتم تطبيق هذه التعديلات على التراكب من خلال ضبط InputContext
مختلف على
النقاط المختلفة في لعبتك. ولإجراء ذلك:
- تجميع
InputActions
من خلال إجراءات ذات صلة منطقيًا باستخدامInputGroups
- يمكنك تعيين قيمة
InputGroups
هذه إلىInputContext
للأجزاء المختلفة من لعبتك
InputGroups
التي تنتمي إلى النطاق نفسهInputContext
لا يمكن أن يحدث التعارض
InputActions
حيث يُستخدم المفتاح نفسه. من الممارسات الجيدة تعيين كل
InputGroup
إلى InputContext
واحد.
يوضح الرمز النموذجي التالي منطق InputContext
:
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
على الحقول التالية:
LocalizedContextLabel
: سلسلة تصف المجموعات التي تنتمي إلى السياق.InputContextId
: عنصرInputIdentifier
يخزِّن رقم تعريف الرقم والإصدار منInputContext
(اطّلع على أرقام تعريف مفاتيح التتبُّع لمزيد من المعلومات المعلومات).ActiveGroups
: قائمة تضمInputGroups
ليتم استخدامها وعرضها في الأعلى للتراكب عندما يكون هذا السياق نشطًا.
إنشاء خريطة إدخال
InputMap
هي مجموعة من جميع عناصر InputGroup
المتوفّرة في
وبالتالي جميع الكائنات InputAction
التي يمكن للاعب توقعها
تنفيذها.
عند الإبلاغ عن عمليات ربط المفاتيح، عليك إنشاء InputMap
باستخدام جميع
تم استخدام InputGroups
في لعبتك.
إذا كانت لعبتك لا تتيح إعادة التخصيص، يمكنك إيقاف خيار إعادة التخصيص و المفاتيح المحجوزة فارغة.
ينشئ المثال التالي InputMap
يتم استخدامه للإبلاغ عن مجموعة من
InputGroups
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
على الحقول التالية:
InputGroups
: مجموعات الإدخال التي أبلغت عنها لعبتك تُعد المجموعات بالترتيب في التراكب، ما لم يتم تحديد المجموعات الحالية في استخدام الاتصال بالرقمsetInputContext()
.MouseSettings
: يشير الكائنMouseSettings
إلى حساسية الماوس. وأن يتم قلب الماوس على المحور ص.InputMapId
: عنصرInputIdentifier
يخزِّن رقم تعريف الرقم وإصدارهInputMap
(اطّلع على أرقام تعريف مفاتيح التتبُّع لمزيد من المعلومات المعلومات).InputRemappingOption
: أحدInputEnums.REMAP_OPTION_ENABLED
أوInputEnums.REMAP_OPTION_DISABLED
تحدد ما إذا كانت ميزة إعادة التخصيص مفعّلة.ReservedControls
: قائمة تتضمّنInputControls
لن يُسمح للمستخدمين بتنفيذها إعادة التخصيص إليه.
أرقام تعريف مفاتيح التتبُّع
تحتوي العناصر InputAction
وInputGroup
وInputContext
وInputMap
على
عنصر InputIdentifier
يخزِّن رقم تعريف رقم فريد ورقم تعريف إصدار للسلسلة.
تجدر الإشارة إلى أنّ تتبُّع إصدار السلسلة من العناصر هو إجراء اختياري، ولكننا ننصح بتتبّعه.
إصدارات InputMap
. إذا لم يتم توفير إصدار السلسلة،
السلسلة فارغة. مطلوب إصدار سلسلة للعناصر InputMap
.
يعيّن المثال التالي إصدارًا سلسلة إلى InputActions
أو
InputGroups
:
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
فريدة على جميع InputActions
في
InputMap
. وبالمثل، يجب أن تكون أرقام تعريف كائنات InputGroup
فريدة على مستوى جميع
InputGroups
في InputMap
. يوضح المثال التالي كيفية استخدام
enum
لتتبُّع المعرّفات الفريدة للعنصر:
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
على الحقول التالية:
UniqueId
: معرّف رقم فريد تم ضبطه لتحديد مجموعة معيّنة من الإدخالات بوضوح بشكل فريد.VersionString
: سلسلة نسخة يمكن لشخص عادي قراءتها لتحديد إصدار معيّن من بيانات الإدخال بين نسختين من تغييرات بيانات الإدخال.
تلقّي إشعارات بشأن إعادة تخصيص الأحداث (اختياري)
تلقّي إشعارات حول أحداث إعادة تخصيص الأحداث للإعلام بالمفاتيح التي يتم استخدامها في لعبتك. يتيح هذا الإجراء للعبتك تحديث مواد العرض التي تظهر على شاشة اللعبة. المستخدم لعرض عناصر التحكم في الإجراءات.
توضح الصورة التالية مثالاً على هذا السلوك حيث بعد إعادة تخصيص
المفاتيح
ويتم تحقيق هذه الوظيفة من خلال تسجيل InputRemappingListener
.
معاودة الاتصال. لتنفيذ هذه الميزة، ابدأ بتسجيل
مثال واحد (InputRemappingListener
):
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
" في وقت الإطلاق بعد تحميل
عناصر التحكم المُعاد تعيينها التي حفظها المستخدم، وبعد كل مرة يعيد المستخدم تعيين مفاتيحه.
الإعداد
في حال استخدام InputContexts
، حدِّد السياق لكل
الانتقال إلى مشهد جديد، بما في ذلك السياق الأول المستخدم
مشهد. عليك ضبط InputContext
بعد تسجيل
InputMap
في حال استخدام "InputRemappingListeners
" لتلقّي إشعارات حول إعادة تخصيص الأحداث
تسجيل InputRemappingListener
قبل تسجيل
InputMappingProvider
، وإلا قد تفوتك أحداث مهمة خلال
وقت الإطلاق.
يوضح النموذج التالي كيفية إعداد واجهة برمجة التطبيقات:
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 } }
تَنظيم
إلغاء تسجيل مثيل InputMappingProvider
وأي InputRemappingListener
عندما يتم إغلاق اللعبة، على الرغم من أن حزمة تطوير البرامج (SDK) للإدخال ذكية
بما يكفي لتجنُّب تسريب الموارد في حال عدم إجراء ما يلي:
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 } }
الاختبار
يمكنك اختبار تنفيذ حزمة تطوير البرامج (SDK) للإدخال عن طريق فتح الإعلان الذي يظهر على سطح الفيديو لعرض تجربة اللاعب أو من خلال واجهة Adb للاختبار التلقائي والتحقق.
يتحقّق محاكي "ألعاب Google Play على الكمبيوتر" من صحة الخريطة التي تم إدخالها.
مقابل الأخطاء الشائعة. بالنسبة إلى سيناريوهات مثل المعرّفات الفريدة المكررة، يمكن أن يكون استخدام
خرائط الإدخال أو الإخفاق في قواعد إعادة التعيين (إذا تم تمكين إعادة التعيين)،
يظهر على سطح الصفحة رسالة خطأ كما يلي:
يمكنك التحقُّق من تنفيذ حزمة تطوير البرامج (SDK) للإدخال باستخدام adb
في سطر الأوامر.
للحصول على خريطة الإدخال الحالية، استخدِم الأمر adb shell
التالي (استبدِله)
MY.PACKAGE.NAME
مع اسم لعبتك):
adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME
ستظهر لك نتيجة مشابهة لما يلي إذا سجّلت
InputMap
:
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
}
الأقلمة
لا تستخدم حزمة تطوير البرامج (SDK) للإدخال نظام أقلمة Android. نتيجة لذلك، أُنشئت مكتبة مات بلوت ليب في
يجب توفير سلاسل مترجَمة عند إرسال InputMap
. إِنْتَ
قد يستخدم أيضًا نظام أقلمة محرك لعبتك.
مؤسسة Proguard
عند استخدام Proguard لتصغير حجم لعبتك، أضِف القواعد التالية إلى ملف إعداد Proguard لضمان عدم إزالة حزمة SDK من الحزمة النهائية:
-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }
الخطوات التالية
بعد دمج حِزمة تطوير البرامج (SDK) للإدخال في لعبتك، يمكنك المتابعة مع أي متطلبات متبقية لبرنامج "ألعاب Google Play على الكمبيوتر". لمزيد من المعلومات يُرجى الاطّلاع على بدء استخدام برنامج "ألعاب Google Play على الكمبيوتر".