เอกสารนี้อธิบายวิธีตั้งค่าและแสดง Input SDK ใน เกมที่รองรับ Google Play Games บน PC โดยงานต่างๆ ได้แก่ การเพิ่ม SDK ลงในเกมและการสร้างแผนที่อินพุต ซึ่งมี การกำหนดการดำเนินการในเกมกับอินพุตของผู้ใช้
ก่อนเริ่มต้นใช้งาน
ก่อนเพิ่ม Input SDK ลงในเกม คุณต้องรองรับอินพุตคีย์บอร์ดและเมาส์โดยใช้ระบบอินพุตของเอนจินเกม
Input SDK จะให้ข้อมูลแก่ Google Play Games บน PC เกี่ยวกับ ตัวควบคุมที่เกมของคุณใช้ เพื่อให้ระบบแสดงตัวควบคุมเหล่านั้นต่อผู้ใช้ได้ นอกจากนี้ ยัง อนุญาตให้ผู้ใช้เปลี่ยนการแมปแป้นพิมพ์ได้ด้วย (ไม่บังคับ)
แต่ละการควบคุมคือInputAction (เช่น "J" สำหรับ "ข้าม") และคุณจะจัดระเบียบInputActionsเป็นInputGroups InputGroup อาจแสดงถึงโหมดต่างๆ ในเกม เช่น "ขับรถ" "เดิน" หรือ "เมนูหลัก" นอกจากนี้ คุณยังใช้ InputContexts เพื่อระบุว่ากลุ่มใดที่ใช้งานอยู่ในช่วงต่างๆ ของเกมได้ด้วย
คุณสามารถเปิดใช้การเปลี่ยนแป้นพิมพ์เพื่อจัดการให้คุณโดยอัตโนมัติได้ แต่หากต้องการ ระบุอินเทอร์เฟซการเปลี่ยนการควบคุมของคุณเอง คุณก็ปิดใช้ การเปลี่ยน Input SDK ได้
แผนภาพลำดับต่อไปนี้อธิบายวิธีการทำงานของ API ของ Input SDK

เมื่อเกมของคุณใช้ SDK อินพุต ระบบจะแสดงตัวควบคุมใน ภาพซ้อนทับของ Google Play Games บน PC
การซ้อนทับของ Google Play Games บน PC
การวางซ้อนของ Google Play Games บน PC ("การวางซ้อน") จะแสดงการควบคุม ที่เกมของคุณกำหนด ผู้ใช้เข้าถึงการซ้อนทับได้ทุกเมื่อโดย กด Shift + Tab

แนวทางปฏิบัติแนะนำในการออกแบบการเชื่อมโยงคีย์
เมื่อออกแบบการเชื่อมโยงคีย์ ให้พิจารณาแนวทางปฏิบัติแนะนำต่อไปนี้
- จัดกลุ่ม
InputActionsเป็นInputGroupsที่เกี่ยวข้องอย่างมีตรรกะเพื่อปรับปรุง การไปยังส่วนต่างๆ และการค้นพบตัวควบคุมในระหว่างการเล่นเกม - กำหนด
InputGroupแต่ละรายการให้กับInputContextอย่างน้อย 1 รายการ การปรับอย่างละเอียดInputMapจะช่วยให้คุณได้รับประสบการณ์การใช้งานที่ดียิ่งขึ้นในการไปยังส่วนควบคุมใน การซ้อนทับ - สร้าง
InputContextสำหรับฉากประเภทต่างๆ ของเกม โดยปกติแล้ว คุณจะใช้InputContextเดียวสำหรับฉาก "เหมือนเมนู" ทั้งหมดได้ ใช้InputContextsที่แตกต่างกันสำหรับมินิเกมในเกมหรือสำหรับ การควบคุมทางเลือกสำหรับฉากเดียว - หากการดำเนินการ 2 อย่างออกแบบมาให้ใช้คีย์เดียวกันภายใต้
InputContextเดียวกัน ให้ใช้สตริงป้ายกำกับ เช่น "โต้ตอบ / ยิง" - หากออกแบบคีย์ 2 คีย์ให้ผูกกับ
InputActionเดียวกัน ให้ใช้InputActions2 อันที่แตกต่างกันซึ่งทําการกระทําเดียวกันในเกม คุณอาจใช้สตริงป้ายกำกับเดียวกันสำหรับทั้งInputActionsแต่รหัสต้องแตกต่างกัน - หากใช้แป้นกดร่วมกับชุดแป้น ให้ใช้
InputActionเดียวที่มีแป้นกดร่วมแทนInputActionsหลายรายการที่รวมแป้นกดร่วม (เช่น ใช้ Shift และ W, A, S, D แทน Shift + W, Shift + A, Shift + S, Shift + D) - การแมปอินพุตใหม่จะปิดใช้โดยอัตโนมัติเมื่อผู้ใช้เขียนลงในช่องข้อความ ทําตามแนวทางปฏิบัติแนะนําในการใช้ช่องข้อความ Android เพื่อให้แน่ใจว่า
Android สามารถตรวจหาช่องข้อความในเกมและป้องกันไม่ให้คีย์ที่แมปใหม่
รบกวนช่องข้อความเหล่านั้น หากเกมต้องใช้ช่องข้อความที่ไม่เป็นไปตามรูปแบบปกติ
คุณสามารถใช้
setInputContext()กับInputContextที่มี รายการว่างของInputGroupsเพื่อปิดใช้การแมปใหม่ด้วยตนเอง - หากเกมรองรับการแมปใหม่ ให้พิจารณาอัปเดตการเชื่อมโยงคีย์ ซึ่งเป็น การดำเนินการที่ละเอียดอ่อนซึ่งอาจขัดแย้งกับเวอร์ชันที่ผู้ใช้บันทึกไว้ หลีกเลี่ยง การเปลี่ยนรหัสของตัวควบคุมที่มีอยู่ หากเป็นไปได้
ฟีเจอร์การแมปใหม่
Google Play Games บน PC รองรับการเปลี่ยนการแมปการควบคุมด้วยแป้นพิมพ์ตามการเชื่อมโยงคีย์
ที่เกมของคุณระบุโดยใช้ Input SDK คุณจะทำขั้นตอนนี้หรือไม่ก็ได้และ
ปิดใช้ได้ทั้งหมด เช่น คุณอาจต้องการจัดเตรียมอินเทอร์เฟซการเปลี่ยนเส้นทางแป้นพิมพ์ของคุณเอง หากต้องการปิดใช้การแมปใหม่สำหรับเกม คุณเพียงแค่ต้องระบุ
ตัวเลือกการแมปใหม่ที่ปิดใช้สำหรับ InputMap (ดูข้อมูลเพิ่มเติมได้ที่
สร้าง InputMap)
หากต้องการเข้าถึงฟีเจอร์นี้ ผู้ใช้ต้องเปิดการซ้อนทับแล้วคลิกการดำเนินการ ที่ต้องการแมปใหม่ หลังจากเหตุการณ์การแมปใหม่ทุกครั้ง Google Play Games บน PC จะแมป การควบคุมที่ผู้ใช้แมปใหม่แต่ละรายการกับการควบคุมเริ่มต้นที่เกมคาดหวัง ที่จะได้รับ ดังนั้นเกมจึงไม่จำเป็นต้องทราบการแมปใหม่ของผู้เล่น คุณ สามารถเลือกอัปเดตชิ้นงานที่ใช้แสดงการควบคุมด้วยแป้นพิมพ์ใน เกมได้โดยเพิ่ม Callback สำหรับเหตุการณ์การแมปใหม่

Google Play Games บน PC จะจัดเก็บการควบคุมที่แมปใหม่ไว้ในเครื่องสำหรับผู้ใช้แต่ละราย เพื่อให้การควบคุมยังคงอยู่ตลอดเซสชันการเล่นเกม ระบบจะจัดเก็บข้อมูลนี้ ไว้ในดิสก์สำหรับแพลตฟอร์ม PC เท่านั้น และไม่มีผลต่อประสบการณ์การใช้งานบนอุปกรณ์เคลื่อนที่ ระบบจะลบข้อมูลการควบคุมเมื่อผู้ใช้ถอนการติดตั้งหรือติดตั้ง Google Play Games บน PC อีกครั้ง ข้อมูลนี้จะไม่คงอยู่บนอุปกรณ์ PC หลายเครื่อง
หากต้องการรองรับฟีเจอร์การแมปใหม่ในเกม ให้หลีกเลี่ยงข้อจำกัดต่อไปนี้
ข้อจำกัดของการแมปใหม่
คุณปิดใช้ฟีเจอร์การแมปใหม่ในเกมได้หากการเชื่อมโยงคีย์มีกรณีใดกรณีหนึ่งต่อไปนี้
InputActionsหลายแป้นที่ไม่ได้ประกอบด้วยแป้นกดร่วม + แป้นที่ไม่ใช่แป้นกดร่วม เช่น Shift + A ใช้ได้ แต่ A + B, Ctrl + Alt หรือ Shift + A + Tab ใช้ไม่ได้InputMapมีInputActions,InputGroupsหรือInputContextsที่มีรหัสที่ไม่ซ้ำซ้ำกัน
ข้อจำกัดของการแมปใหม่
เมื่อออกแบบการเชื่อมโยงคีย์สำหรับการแมปใหม่ ให้พิจารณาข้อจำกัดต่อไปนี้
- ระบบไม่รองรับการแมปใหม่กับชุดแป้นที่กดร่วมกัน เช่น ผู้ใช้จะ เปลี่ยนเส้นทาง Shift + A เป็น Ctrl + B หรือ A เป็น Shift + A ไม่ได้
InputActionsที่มีปุ่มเมาส์ไม่รองรับการแมปใหม่ ตัวอย่างเช่น Shift + คลิกขวาจะแมปใหม่ไม่ได้
ทดสอบการแมปปุ่มใหม่ในโปรแกรมจำลอง Google Play Games บน PC
คุณเปิดใช้ฟีเจอร์การแมปใหม่ในโปรแกรมจำลอง Google Play Games บน PC ได้ทุกเมื่อ โดยใช้คำสั่ง adb ต่อไปนี้
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
การเปลี่ยนแปลงการวางซ้อนดังรูปภาพต่อไปนี้

เพิ่ม SDK
ติดตั้ง Input SDK ตามแพลตฟอร์มการพัฒนาของคุณ
Java และ Kotlin
รับ Input SDK สำหรับ Java หรือ Kotlin โดยเพิ่มทรัพยากร Dependency ลงใน
ไฟล์ระดับโมดูล build.gradle
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
...
}
Unity
Input SDK เป็นแพ็กเกจ Unity มาตรฐานที่มีทรัพยากร Dependency หลายรายการ
คุณต้องติดตั้งแพ็กเกจที่มีการอ้างอิงทั้งหมด การติดตั้งแพ็กเกจทำได้หลายวิธี
ติดตั้ง .unitypackage
ดาวน์โหลดไฟล์ unitypackage ของ Input SDK
พร้อมกับทรัพยากร Dependency ทั้งหมด คุณติดตั้ง .unitypackage ได้โดยเลือกชิ้นงาน > นำเข้าแพ็กเกจ > แพ็กเกจที่กำหนดเอง แล้วค้นหาไฟล์ที่คุณดาวน์โหลด
ติดตั้งโดยใช้ UPM
หรือคุณจะติดตั้งแพ็กเกจโดยใช้ Unity Package Manager ก็ได้โดย
ดาวน์โหลด .tgz และติดตั้งทรัพยากร Dependency ดังนี้
- 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.1-beta (หรือเลือก tgz จากที่เก็บถาวรนี้)
ติดตั้งโดยใช้ OpenUPM
คุณติดตั้งแพ็กเกจได้โดยใช้ OpenUPM
$ openupm add com.google.android.libraries.play.games.inputmapping
เกมตัวอย่าง
ดูตัวอย่างวิธีผสานรวมกับ Input SDK ได้ที่ AGDK Tunnel สำหรับเกม 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ทั้งหมด แต่ Input 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 );

Input 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 );

InputAction มีฟิลด์ต่อไปนี้
ActionLabel: สตริงที่แสดงใน UI เพื่อแสดงการดำเนินการนี้ ระบบจะไม่ทำการแปลโดยอัตโนมัติ ดังนั้นคุณจึงต้องทำการแปลล่วงหน้าInputControls: กำหนดตัวควบคุมอินพุตที่การดำเนินการนี้ใช้ โดย การควบคุมจะแมปกับอักขระที่สอดคล้องกันในภาพซ้อนทับInputActionId: ออบเจ็กต์InputIdentifierที่จัดเก็บรหัสหมายเลขและเวอร์ชันของInputAction(ดูข้อมูลเพิ่มเติมได้ที่รหัสคีย์การติดตาม)InputRemappingOption: หนึ่งในInputEnums.REMAP_OPTION_ENABLEDหรือInputEnums.REMAP_OPTION_DISABLEDกำหนดว่าเปิดใช้การดำเนินการเพื่อ เปลี่ยนเส้นทางหรือไม่ หากเกมไม่รองรับการแมปใหม่ คุณอาจข้ามช่องนี้หรือ ตั้งค่าเป็นปิดใช้RemappedInputControls: ออบเจ็กต์InputControlsแบบอ่านอย่างเดียวที่ใช้ในการอ่านชุดคีย์ที่ผู้ใช้แมปใหม่ในเหตุการณ์การแมปใหม่ (ใช้สำหรับรับการแจ้งเตือนเกี่ยวกับเหตุการณ์การแมปใหม่)
InputControls แสดงอินพุตที่เชื่อมโยงกับการดำเนินการและมีฟิลด์ต่อไปนี้
AndroidKeycodes: คือรายการจำนวนเต็มที่แสดงถึงอินพุตของแป้นพิมพ์ ที่เชื่อมโยงกับการดำเนินการ ซึ่งกำหนดไว้ในคลาส KeyEvent หรือคลาส AndroidKeycode สำหรับ UnityMouseActions: คือรายการค่าMouseActionที่แสดงถึงอินพุตของเมาส์ ที่เชื่อมโยงกับการดำเนินการนี้
กำหนดกลุ่มอินพุต
InputActions จะจัดกลุ่มกับการดำเนินการที่เกี่ยวข้องอย่างมีตรรกะโดยใช้ InputGroups เพื่อ
ปรับปรุงการนำทางและความสามารถในการค้นพบการควบคุมในภาพซ้อนทับ แต่ละInputGroupรหัสต้องไม่ซ้ำกันในInputGroupsทั้งหมดในเกม
การจัดระเบียบการกระทำที่ป้อนเป็นกลุ่มจะช่วยให้ผู้เล่นค้นหาการเชื่อมโยงคีย์ที่ถูกต้องสำหรับบริบทปัจจุบันได้ง่ายขึ้น
หากรองรับการแมปใหม่ คุณจะกำหนดได้ว่าInputGroupsสามารถ
แมปใหม่ได้ หากเกมไม่รองรับการแมปใหม่ คุณควรตั้งค่าตัวเลือกการแมปใหม่
เป็นปิดสำหรับInputGroupsทั้งหมด แต่ Input 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: InputGroups ที่เกมรายงาน กลุ่มจะแสดงตามลำดับในภาพซ้อน เว้นแต่จะระบุกลุ่มปัจจุบันที่ใช้ในการโทรsetInputContext()MouseSettings: ออบเจ็กต์MouseSettingsระบุว่าสามารถปรับความไวของเมาส์ และเมาส์จะกลับด้านบนแกน yInputMapId: ออบเจ็กต์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รหัสออบเจ็กต์ต้องไม่ซ้ำกันในInputMapทั้งหมด
InputGroups ตัวอย่างต่อไปนี้แสดงวิธีใช้
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: สตริงเวอร์ชันที่มนุษย์อ่านได้ซึ่งตั้งค่าเพื่อระบุเวอร์ชัน ของข้อมูลนำเข้าระหว่างการเปลี่ยนแปลงข้อมูลนำเข้า 2 เวอร์ชัน
รับการแจ้งเตือนเมื่อมีการแมปเหตุการณ์ใหม่ (ไม่บังคับ)
รับการแจ้งเตือนเกี่ยวกับเหตุการณ์การแมปใหม่เพื่อรับทราบคีย์ที่ใช้ในเกม ของคุณ ซึ่งจะช่วยให้เกมอัปเดตชิ้นงานที่แสดงบนหน้าจอเกม ที่ใช้แสดงตัวควบคุมการดำเนินการได้
รูปภาพต่อไปนี้แสดงตัวอย่างลักษณะการทำงานนี้ ซึ่งหลังจากรีแมป
ปุ่ม

ฟังก์ชันนี้จะทำงานโดยการลงทะเบียน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
มิฉะนั้นเกมของคุณอาจพลาดเหตุการณ์สำคัญในช่วง
เวลาเปิดตัว
ตัวอย่างต่อไปนี้แสดงวิธีเริ่มต้น API
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
เมื่อปิดเกม แม้ว่า Input 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 } }
ทดสอบ
คุณสามารถทดสอบการติดตั้งใช้งาน Input SDK ได้โดยเปิดการวางซ้อนด้วยตนเองเพื่อดูประสบการณ์การใช้งานของผู้เล่น หรือผ่าน adb shell สำหรับการทดสอบและการยืนยันอัตโนมัติ
โปรแกรมจำลอง Google Play Games บน PC จะตรวจสอบความถูกต้องของแผนที่อินพุต
เทียบกับข้อผิดพลาดที่พบบ่อย สำหรับสถานการณ์ต่างๆ เช่น รหัสที่ไม่ซ้ำกันที่ซ้ำกัน การใช้
อินพุตแมปที่แตกต่างกัน หรือการไม่เป็นไปตามกฎการแมปใหม่ (หากเปิดใช้การแมปใหม่)
การวางซ้อนจะแสดงข้อความแสดงข้อผิดพลาดดังนี้

ยืนยันการติดตั้งใช้งาน Input 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
}
การแปล
Input SDK ไม่ได้ใช้ระบบการแปลของ Android ด้วยเหตุนี้ คุณจึงต้องระบุสตริงที่แปลแล้วเมื่อส่ง InputMap
คุณยังใช้ระบบการแปลของเกมเอนจินได้ด้วย
Proguard
เมื่อใช้ Proguard เพื่อลดขนาดเกม ให้เพิ่มกฎต่อไปนี้ลงในไฟล์การกำหนดค่า Proguard เพื่อให้แน่ใจว่า SDK จะไม่ถูกนำออกจากแพ็กเกจสุดท้าย
-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }
ขั้นตอนถัดไป
หลังจากผสานรวม Input SDK เข้ากับเกมแล้ว คุณสามารถดำเนินการต่อ ตามข้อกำหนดที่เหลือของ Google Play Games บน PC ดูข้อมูลเพิ่มเติมได้ที่เริ่มต้นใช้งาน Google Play Games บน PC