این سند نحوه تنظیم و نمایش Input SDK را در بازیهایی که از Google Play Games در رایانه شخصی پشتیبانی میکنند، شرح میدهد. وظایف شامل اضافه کردن SDK به بازی شما و ایجاد یک نقشه ورودی است که شامل تکالیف ورودی کاربر از اقدامات بازی است.
قبل از اینکه شروع کنید
قبل از اینکه Input SDK را به بازی خود اضافه کنید، باید با استفاده از سیستم ورودی موتور بازی خود، از ورودی صفحه کلید و ماوس پشتیبانی کنید.
کیت توسعه نرمافزار ورودی (Input SDK) اطلاعاتی در مورد کنترلهای مورد استفاده بازی شما در اختیار بازیهای گوگل پلی روی کامپیوتر قرار میدهد تا بتوان آنها را به کاربر نمایش داد. همچنین میتواند به صورت اختیاری امکان تغییر نقشه صفحه کلید را برای کاربران فراهم کند.
هر کنترل یک InputAction است (مثلاً "J" برای "پرش") و شما InputActions خود را در InputGroups سازماندهی میکنید. یک InputGroup ممکن است حالت متفاوتی را در بازی شما نشان دهد، مانند "رانندگی" یا "پیادهروی" یا "منوی اصلی". همچنین میتوانید InputContexts برای نشان دادن گروههای فعال در نقاط مختلف بازی استفاده کنید.
میتوانید تنظیم خودکار تغییر نقشه صفحهکلید را فعال کنید، اما اگر ترجیح میدهید رابط تغییر نقشه کنترل خودتان را داشته باشید، میتوانید تغییر نقشه ورودی SDK را غیرفعال کنید.
نمودار توالی زیر نحوه عملکرد API مربوط به Input SDK را شرح میدهد:

وقتی بازی شما Input SDK را پیادهسازی میکند، کنترلهای شما در صفحه بازیهای گوگل پلی روی کامپیوتر نمایش داده میشوند.
پوشش بازیهای گوگل پلی روی کامپیوتر
پوشش Google Play Games on PC ("پوشش") کنترلهای تعریفشده توسط بازی شما را نمایش میدهد. کاربران در هر زمان با فشار دادن Shift + Tab به این پوشش دسترسی پیدا میکنند.

بهترین شیوهها برای طراحی اتصال کلید
هنگام طراحی کلیدهای اتصال خود، بهترین شیوههای زیر را در نظر بگیرید:
-
InputActionsخود را درInputGroupsمنطقی مرتبط گروهبندی کنید تا پیمایش و قابلیت کشف کنترلها در حین بازی بهبود یابد. - هر
InputGroupحداکثر به یکInputContextاختصاص دهید. یکInputMapبا جزئیات دقیق، تجربه بهتری را برای پیمایش کنترلهای شما در لایه پوششی ایجاد میکند. - برای هر نوع صحنهی مختلف از بازی خود، یک
InputContextایجاد کنید. معمولاً میتوانید از یکInputContextبرای تمام صحنههای «منو مانند» خود استفاده کنید. برای هر مینیگیم در بازی خود یا برای کنترلهای جایگزین برای یک صحنه،InputContextsمختلف استفاده کنید. - اگر دو اکشن طوری طراحی شدهاند که از یک کلید تحت یک
InputContextاستفاده کنند، از رشته برچسب مانند "Interact / Fire" استفاده کنید. - اگر دو کلید برای اتصال به یک
InputActionیکسان طراحی شدهاند، از دوInputActionsمختلف استفاده کنید که عمل یکسانی را در بازی شما انجام میدهند. میتوانید از یک رشته برچسب یکسان برای هر دوInputActionsاستفاده کنید، اما شناسه (ID) آن باید متفاوت باشد. - اگر یک کلید اصلاحکننده برای مجموعهای از کلیدها اعمال میشود، به جای چندین
InputActionsکه کلید اصلاحکننده را ترکیب میکنند، داشتن یکInputActionواحد با کلید اصلاحکننده را در نظر بگیرید (مثال: به جای Shift + W، Shift + A، Shift + S، Shift + D از Shift و W ، A، S، D استفاده کنید). - تغییر نگاشت ورودی به طور خودکار زمانی که کاربر در فیلدهای متنی مینویسد، غیرفعال میشود. برای اطمینان از اینکه اندروید میتواند فیلدهای متنی را در بازی شما شناسایی کند و از تداخل کلیدهای تغییر نگاشت شده با آنها جلوگیری کند، از بهترین شیوههای پیادهسازی فیلدهای متنی اندروید پیروی کنید. اگر بازی شما مجبور است از فیلدهای متنی غیرمتعارف استفاده کند، میتوانید
setInputContext()باInputContextحاوی لیست خالی ازInputGroupsبرای غیرفعال کردن تغییر نگاشت دستی استفاده کنید. - اگر بازی شما از تغییر نگاشت پشتیبانی میکند، بهروزرسانی اتصالات کلید خود را در نظر بگیرید، عملیاتی حساس که میتواند با نسخههای ذخیره شده توسط کاربر تداخل داشته باشد. در صورت امکان از تغییر شناسه کنترلهای موجود خودداری کنید.
ویژگی بازنگاشت
بازیهای گوگل پلی روی کامپیوتر از بازنگاشت کنترل صفحهکلید بر اساس کلیدهای اتصالی که بازی شما با استفاده از Input SDK ارائه میدهد، پشتیبانی میکند. این گزینه اختیاری است و میتواند کاملاً غیرفعال شود. به عنوان مثال، ممکن است بخواهید رابط بازنگاشت صفحهکلید خود را ارائه دهید. برای غیرفعال کردن بازنگاشت برای بازی خود، فقط باید گزینه بازنگاشت را برای InputMap خود غیرفعال کنید (برای اطلاعات بیشتر به Build an InputMap مراجعه کنید).
برای دسترسی به این ویژگی، کاربران باید صفحه پوششی را باز کرده و سپس روی عملی که میخواهند تغییر مکان دهند کلیک کنند. پس از هر رویداد تغییر مکان، Google Play Games روی کامپیوتر، هر کنترل تغییر مکان داده شده توسط کاربر را به کنترلهای پیشفرضی که بازی شما انتظار دریافت آنها را دارد، تغییر مکان میدهد، بنابراین بازی شما نیازی به آگاهی از تغییر مکان بازیکن ندارد. میتوانید به صورت اختیاری، با اضافه کردن یک فراخوانی برای رویدادهای تغییر مکان، داراییهای مورد استفاده برای نمایش کنترلهای صفحه کلید در بازی خود را بهروزرسانی کنید.

بازیهای گوگل پلی روی کامپیوتر، کنترلهای تغییر یافته را به صورت محلی برای هر کاربر ذخیره میکند و امکان پایداری کنترل را در طول جلسات بازی فراهم میکند. این اطلاعات فقط برای پلتفرم کامپیوتر روی دیسک ذخیره میشود و بر تجربه موبایل تأثیری ندارد. دادههای کنترل پس از حذف یا نصب مجدد بازیهای گوگل پلی روی کامپیوتر توسط کاربر حذف میشوند. این دادهها در چندین دستگاه کامپیوتر پایدار نیستند.
برای پشتیبانی از قابلیت remapping در بازی خود، از محدودیتهای زیر اجتناب کنید:
محدودیتهای بازنگاشت
اگر کلیدهای ترکیبی شامل هر یک از موارد زیر باشند، میتوان ویژگیهای بازنگاشت را در بازی شما غیرفعال کرد:
-
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 روی شبیهساز کامپیوتر
شما میتوانید قابلیت remapping را در Google Play Games on PC Emulator در هر زمانی با اجرای دستور adb زیر فعال کنید:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
تغییر لایه پوششی مانند تصویر زیر:

اضافه کردن SDK
Input SDK را مطابق با پلتفرم توسعه خود نصب کنید.
جاوا و کاتلین
با اضافه کردن یک وابستگی به فایل build.gradle در سطح ماژول، Input SDK مربوط به جاوا یا کاتلین را دریافت کنید:
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
...
}
وحدت
کیت توسعه نرمافزار ورودی (Input SDK) یک بسته استاندارد یونیتی با چندین وابستگی است.
نصب بسته به همراه تمام وابستگیها الزامی است. روشهای مختلفی برای نصب بستهها وجود دارد.
نصب پکیج .unitypackage
فایل پکیج یونیتی Input SDK را به همراه تمام وابستگیهایش دانلود کنید . میتوانید با انتخاب Assets > Import package > Custom Package و پیدا کردن فایلی که دانلود کردهاید، پکیج .unitypackage را نصب کنید.
نصب با استفاده از UPM
روش دیگر این است که با دانلود فایل .tgz و نصب وابستگیهای آن، بسته را با استفاده از Unity Package Manager نصب کنید:
- 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 را شرح میدهد:
کاتلین
class InputSDKProvider : InputMappingProvider { override fun onProvideInputMap(): InputMap { TODO("Not yet implemented") } }
جاوا
public class InputSDKProvider implements InputMappingProvider { private static final String INPUTMAP_VERSION = "1.0.0"; @Override @NonNull public InputMap onProvideInputMap() { // TODO: return an InputMap } }
سی شارپ
#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 دارای شناسههای منحصر به فرد باشد.
اگر از remapping پشتیبانی میکنید، میتوانید تعریف کنید که کدام InputActions میتوانند remapping شوند. اگر بازی شما از remapping پشتیبانی نمیکند، باید گزینه remapping را برای همه InputActions خود غیرفعال کنید، اما Input SDK به اندازه کافی هوشمند است که اگر remapping را در InputMap خود پشتیبانی نمیکنید، آن را غیرفعال کند.
این مثال، نقشه
کاتلین
companion object { private val driveInputAction = InputAction.create( "Drive", InputActionsIds.DRIVE.ordinal.toLong(), InputControls.create(listOf(KeyEvent.KEYCODE_SPACE), emptyList()), InputEnums.REMAP_OPTION_ENABLED) }
جاوا
private static final InputAction driveInputAction = InputAction.create( "Drive", InputEventIds.DRIVE.ordinal(), InputControls.create( Collections.singletonList(KeyEvent.KEYCODE_SPACE), Collections.emptyList()), InputEnums.REMAP_OPTION_ENABLED );
سی شارپ
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 );

اکشنها میتوانند ورودیهای ماوس را نیز نمایش دهند. این مثال ، کلیک چپ را به اکشن Move تبدیل میکند:
کاتلین
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) }
جاوا
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 );
سی شارپ
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 شما مشخص میشود. در این مثال
کاتلین
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) }
جاوا
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 );
سی شارپ
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) به شما امکان میدهد دکمههای ماوس و کلید را برای یک عمل واحد با هم ترکیب کنید. این مثال نشان میدهد که
کاتلین
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) }
جاوا
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 );
سی شارپ
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: رشتهای که در رابط کاربری برای نمایش این عمل نمایش داده میشود. محلیسازی به صورت خودکار انجام نمیشود، بنابراین هرگونه محلیسازی را از قبل انجام دهید. -
InputControls: کنترلهای ورودی مورد استفاده این اکشن را تعریف میکند. این کنترلها به گلیفهای سازگار در پوشش نگاشت میشوند. -
InputActionId: شیءInputIdentifierکه شناسه شماره و نسخهInputActionرا ذخیره میکند (برای اطلاعات بیشتر به Tracking Key IDs مراجعه کنید). -
InputRemappingOption: یکی ازInputEnums.REMAP_OPTION_ENABLEDیاInputEnums.REMAP_OPTION_DISABLED. مشخص میکند که آیا عمل remap فعال است یا خیر. اگر بازی شما از remapping پشتیبانی نمیکند، میتوانید از این فیلد صرف نظر کنید یا به سادگی آن را غیرفعال کنید. -
RemappedInputControls: شیءInputControlsفقط خواندنی که برای خواندن کلید تغییر یافته تنظیم شده توسط کاربر در رویدادهای تغییر مسیر (برای دریافت اعلان در مورد رویدادهای تغییر مسیر ) استفاده میشود.
InputControls ورودیهای مرتبط با یک اکشن را نشان میدهد و شامل فیلدهای زیر است:
-
AndroidKeycodes: فهرستی از اعداد صحیح است که ورودیهای صفحهکلید مرتبط با یک عمل را نشان میدهد. این اعداد در کلاس KeyEvent یا کلاس AndroidKeycode برای Unity تعریف شدهاند. -
MouseActions: فهرستی از مقادیرMouseActionاست که ورودیهای ماوس مرتبط با این عمل را نشان میدهد.
گروههای ورودی خود را تعریف کنید
InputActions با استفاده از InputGroups با اقدامات منطقی مرتبط گروهبندی میشوند تا قابلیت پیمایش و کنترلها در پوشش بهبود یابد. هر شناسه InputGroup باید در تمام InputGroups بازی شما منحصر به فرد باشد.
با سازماندهی اقدامات ورودی خود در گروهها، پیدا کردن کلید اتصال صحیح برای زمینه فعلی خود را برای بازیکن آسانتر میکنید.
اگر از remapping پشتیبانی میکنید، میتوانید تعریف کنید که کدام InputGroups میتوانند remapping شوند. اگر بازی شما از remapping پشتیبانی نمیکند، باید گزینه remapping را برای همه InputGroups خود غیرفعال کنید، اما Input SDK به اندازه کافی هوشمند است که اگر remapping را در InputMap خود پشتیبانی نمیکنید، آن را غیرفعال کند.
کاتلین
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 ) }
جاوا
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 );
سی شارپ
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را ذخیره میکند. برای اطلاعات بیشتر به Tracking Key IDs مراجعه کنید. -
InputRemappingOption: یکی ازInputEnums.REMAP_OPTION_ENABLEDیاInputEnums.REMAP_OPTION_DISABLED. در صورت غیرفعال بودن، نگاشت مجدد تمام اشیاءInputActionمتعلق به این گروه غیرفعال خواهد شد، حتی اگر گزینه نگاشت مجدد آن را فعال کرده باشند. در صورت فعال بودن، تمام اقدامات متعلق به این گروه قابل نگاشت مجدد هستند، مگر اینکه توسط اقدامات جداگانه غیرفعال شده باشد.
زمینههای ورودی خود را تعریف کنید
InputContexts به بازی شما اجازه میدهد تا از مجموعه متفاوتی از کنترلهای صفحهکلید برای صحنههای مختلف بازی استفاده کند. برای مثال:
- شما میتوانید مجموعههای مختلفی از ورودیها را برای پیمایش منوها در مقابل حرکت در بازی مشخص کنید.
- شما میتوانید بسته به حالت حرکت در بازی خود، مانند رانندگی در مقابل پیادهروی، مجموعههای مختلفی از ورودیها را مشخص کنید.
- شما میتوانید مجموعههای مختلفی از ورودیها را بر اساس وضعیت فعلی بازی خود مشخص کنید، مانند پیمایش در یک دنیای وسیع در مقابل بازی کردن یک مرحله به صورت جداگانه.
هنگام استفاده از InputContexts ، لایه رویی ابتدا گروههای زمینه مورد استفاده را نشان میدهد. برای فعال کردن این رفتار، تابع setInputContext() را فراخوانی کنید تا هر زمان که بازی شما وارد صحنه دیگری میشود، زمینه تنظیم شود. تصویر زیر این رفتار را نشان میدهد: در صحنه "رانندگی"، اکشنهای کنترل جاده در بالای لایه رویی نشان داده میشوند. هنگام باز کردن منوی "فروشگاه"، اکشنهای "کنترلهای منو" در بالای لایه رویی نمایش داده میشوند.

این بهروزرسانیهای پوششی با تنظیم InputContext متفاوت در نقاط مختلف بازی شما انجام میشوند. برای انجام این کار:
- با استفاده از
InputGroupsInputActionsخود را با اقدامات منطقی مرتبط گروهبندی کنید. - این
InputGroupsبرای بخشهای مختلف بازی خود بهInputContextاختصاص دهید.
InputGroups که به InputContext یکسانی تعلق دارند، نمیتوانند InputActions متناقضی داشته باشند که در آنها از کلید یکسانی استفاده شده است. بهتر است هر InputGroup به یک InputContext واحد اختصاص دهید.
کد نمونه زیر منطق InputContext را نشان میدهد:
کاتلین
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)) }
جاوا
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 ) );
سی شارپ
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را ذخیره میکند (برای اطلاعات بیشتر به Tracking Key IDs مراجعه کنید). -
ActiveGroups: فهرستی ازInputGroupsکه هنگام فعال بودن این context در بالای overlay نمایش داده میشوند.
ساخت نقشه ورودی
یک InputMap مجموعهای از تمام اشیاء InputGroup موجود در یک بازی است، و بنابراین تمام اشیاء InputAction که یک بازیکن میتواند انتظار انجام آنها را داشته باشد.
هنگام گزارشدهی اتصالات کلید خود، شما یک InputMap با تمام InputGroups مورد استفاده در بازی خود میسازید.
اگر بازی شما از remapping پشتیبانی نمیکند، گزینه remapping را غیرفعال و کلیدهای رزرو شده را خالی بگذارید.
مثال زیر یک InputMap میسازد که برای گزارش مجموعهای از InputGroups استفاده میشود.
کاتلین
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())) ) }
جاوا
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() ) ) );
سی شارپ
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نشان میدهد که حساسیت ماوس قابل تنظیم است و ماوس روی محور y معکوس میشود. -
InputMapId: شیءInputIdentifierکه شناسه شماره و نسخهInputMapرا ذخیره میکند (برای اطلاعات بیشتر به Tracking Key IDs مراجعه کنید). -
InputRemappingOption: یکی ازInputEnums.REMAP_OPTION_ENABLEDیاInputEnums.REMAP_OPTION_DISABLED. مشخص میکند که آیا ویژگی remapping فعال است یا خیر. -
ReservedControls: فهرستی ازInputControlsکه کاربران مجاز به تغییر به آنها نیستند.
شناسههای کلید ردیابی
اشیاء InputAction ، InputGroup ، InputContext و InputMap حاوی یک شیء InputIdentifier هستند که یک شناسه عددی منحصر به فرد و یک شناسه نسخه رشتهای را ذخیره میکند. ردیابی نسخه رشتهای اشیاء شما اختیاری است، اما برای ردیابی نسخههای InputMap شما توصیه میشود. اگر نسخه رشتهای ارائه نشود، رشته خالی است. یک نسخه رشتهای برای اشیاء InputMap لازم است.
مثال زیر یک نسخه رشتهای را به InputActions یا InputGroups اختصاص میدهد:
کاتلین
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) } }
جاوا
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 ); }
سی شارپ
#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 برای ردیابی شناسههای منحصر به فرد شیء شما را نشان میدهد:
کاتلین
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
جاوا
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;
سی شارپ
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 شروع کنید:
کاتلین
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" } }
جاوا
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); } }
سی شارپ
#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 استفاده میکنید، در هر انتقال به صحنه جدید، context را تنظیم کنید، از جمله اولین context مورد استفاده برای صحنه اولیهتان. شما باید InputContext را پس از ثبت InputMap خود تنظیم کنید.
اگر از InputRemappingListeners برای اطلاعرسانی در مورد رویدادهای تغییر نقشه استفاده میکنید، InputRemappingListener خود را قبل از ثبت InputMappingProvider ثبت کنید، در غیر این صورت بازی شما ممکن است رویدادهای مهم را در زمان اجرا از دست بدهد.
مثال زیر نحوه مقداردهی اولیه API را نشان میدهد:
کاتلین
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) } }
جاوا
@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); } }
سی شارپ
#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 به اندازهی کافی هوشمند است که در صورت عدم انجام این کار، از نشت منابع جلوگیری کند:
کاتلین
override fun onDestroy() { if (isGooglePlayGamesOnPC()) { val inputMappingClient = Input.getInputMappingClient(this) inputMappingClient.clearInputMappingProvider() inputMappingClient.clearRemappingListener() } super.onDestroy() }
جاوا
@Override protected void onDestroy() { if (isGooglePlayGamesOnPC()) { InputMappingClient inputMappingClient = Input.getInputMappingClient(this); inputMappingClient.clearInputMappingProvider(); inputMappingClient.clearRemappingListener(); } super.onDestroy(); }
سی شارپ
public class GameManager : MonoBehaviour { private void OnDestroy() { #if PLAY_GAMES_PC _inputMappingClient.ClearInputMappingProvider(); _inputMappingClient.ClearRemappingListener(); #endif } }
تست
شما میتوانید پیادهسازی Input SDK خود را با باز کردن دستی صفحهی پوششی برای مشاهدهی تجربهی پخشکننده، یا از طریق پوستهی adb برای آزمایش و تأیید خودکار، آزمایش کنید.
شبیهساز بازیهای گوگل پلی روی کامپیوتر، صحت نقشه ورودی شما را در برابر خطاهای رایج بررسی میکند. برای سناریوهایی مانند شناسههای منحصر به فرد تکراری، استفاده از نقشههای ورودی مختلف یا عدم موفقیت در قوانین تغییر نقشه (در صورت فعال بودن تغییر نقشه)، پوشش، پیام خطایی مانند زیر را نشان میدهد:
پیادهسازی 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) از سیستم محلیسازی اندروید استفاده نمیکند. در نتیجه، هنگام ارسال InputMap باید رشتههای محلیسازی شده را ارائه دهید. همچنین میتوانید از سیستم محلیسازی موتور بازی خود استفاده کنید.
پروگارد
هنگام استفاده از 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 on PC ادامه دهید. برای اطلاعات بیشتر، به «شروع با Google Play Games on PC» مراجعه کنید.