این سند نحوه راهاندازی و نمایش Input SDK را در بازیهایی که از بازیهای Google Play در رایانه شخصی پشتیبانی میکنند، توضیح میدهد. این کارها شامل افزودن SDK به بازی شما و ایجاد یک نقشه ورودی است که شامل تخصیصهای ورودی عملکردهای بازی به کاربر است.
قبل از اینکه شروع کنید
قبل از اینکه Input SDK را به بازی خود اضافه کنید، باید از ورودی صفحه کلید و ماوس با استفاده از سیستم ورودی موتور بازی خود پشتیبانی کنید.
Input SDK اطلاعاتی را در مورد کنترلهایی که بازی شما استفاده میکند در اختیار بازیهای Google Play در رایانه شخصی قرار میدهد تا بتوان آنها را به کاربر نمایش داد. همچنین می تواند به صورت اختیاری امکان نقشه برداری مجدد صفحه کلید را برای کاربران فراهم کند.
هر کنترل یک InputAction
است (به عنوان مثال "J" برای "Jump") و شما InputActions
خود را در InputGroups
سازماندهی می کنید. یک InputGroup
ممکن است حالت متفاوتی را در بازی شما نشان دهد، مانند "رانندگی" یا "پیاده روی" یا "منوی اصلی". همچنین می توانید از InputContexts
برای نشان دادن اینکه کدام گروه ها در نقاط مختلف بازی فعال هستند استفاده کنید.
میتوانید نقشهبرداری مجدد صفحهکلید را فعال کنید تا به صورت خودکار برای شما انجام شود، اما اگر ترجیح میدهید رابط نقشهبرداری مجدد کنترلی خود را ارائه دهید، میتوانید نقشهبرداری مجدد SDK ورودی را غیرفعال کنید.
نمودار توالی زیر نحوه عملکرد API Input SDK را شرح می دهد:
وقتی بازی شما Input SDK را اجرا میکند، کنترلهای شما در بازیهای Google Play روی رایانه شخصی نمایش داده میشوند.
بازیهای Google Play روی رایانه شخصی
بازیهای Google Play روی رایانه شخصی ("پوشش") کنترلهای تعریفشده توسط بازی شما را نمایش میدهد. کاربران در هر زمان با فشار دادن Shift + Tab به پوشش دسترسی پیدا می کنند.
بهترین روش ها برای طراحی اتصالات کلید
هنگام طراحی اتصالات کلیدی خود، بهترین شیوه های زیر را در نظر بگیرید:
-
InputActions
خود را درInputGroups
منطقی مرتبط گروه بندی کنید تا ناوبری و قابلیت کشف کنترل ها را در طول بازی بهبود بخشد. - هر
InputGroup
حداکثر به یکInputContext
اختصاص دهید. یکInputMap
دانه بندی شده، تجربه بهتری را برای پیمایش کنترل های شما در پوشش ایجاد می کند. - برای هر نوع صحنه مختلف از بازی خود یک
InputContext
ایجاد کنید. معمولاً میتوانید از یکInputContext
برای تمام صحنههای «منو مانند» خود استفاده کنید. ازInputContexts
مختلف برای هر مینی بازی در بازی خود یا برای کنترل های جایگزین برای یک صحنه استفاده کنید. - اگر دو عمل برای استفاده از یک کلید در یک
InputContext
طراحی شده اند، از رشته برچسب مانند "Interact / Fire" استفاده کنید. - اگر دو کلید برای اتصال به یک
InputAction
طراحی شدهاند، از 2InputActions
مختلف استفاده کنید که عملکرد یکسانی را در بازی شما انجام میدهند. شما ممکن است از یک رشته برچسب برای هر دوInputActions
استفاده کنید، اما شناسه آن باید متفاوت باشد. - اگر یک کلید اصلاح کننده روی مجموعهای از کلیدها اعمال میشود، به جای چندین
InputActions
که کلید اصلاحکننده را ترکیب میکنند، یکInputAction
واحد با کلید اصلاحکننده داشته باشید (مثال: از Shift و W، A، S، D به جای Shift + W، Shift + استفاده کنید. A، Shift + S، Shift + D ). - وقتی کاربر در فیلدهای متنی می نویسد، نگاشت مجدد ورودی به طور خودکار غیرفعال می شود. بهترین روشها را برای پیادهسازی فیلدهای متنی Android دنبال کنید تا مطمئن شوید که Android میتواند فیلدهای متنی را در بازی شما شناسایی کند و از تداخل کلیدهای تغییر نقشه با آنها جلوگیری کند. اگر بازی شما مجبور است از فیلدهای متنی غیر متعارف استفاده کند، می توانید از
setInputContext()
با یکInputContext
حاوی لیست خالی ازInputGroups
استفاده کنید تا نقشه برداری مجدد را به صورت دستی غیرفعال کنید. - اگر بازی شما از نقشهبرداری مجدد پشتیبانی میکند، بهروزرسانی اتصالات کلید خود را یک عملیات حساس در نظر بگیرید که میتواند با نسخههای ذخیرهشده کاربر در تضاد باشد. در صورت امکان از تغییر شناسه کنترل های موجود خودداری کنید.
ویژگی نقشه برداری مجدد
«بازیهای Google Play» روی رایانه شخصی از نقشهبرداری مجدد کنترل صفحهکلید بر اساس اتصالهای کلیدی که بازی شما با استفاده از Input SDK ارائه میکند، پشتیبانی میکند. این اختیاری است و می توان آن را به طور کامل غیرفعال کرد. به عنوان مثال، ممکن است بخواهید رابط نقشه برداری مجدد صفحه کلید خود را ارائه دهید. برای غیرفعال کردن remapping برای بازی خود، فقط باید گزینه remapping غیرفعال برای InputMap
خود را مشخص کنید (برای اطلاعات بیشتر به ساخت InputMap مراجعه کنید).
برای دسترسی به این ویژگی، کاربران باید همپوشانی را باز کنند و سپس روی عملکردی که میخواهند دوباره نقشهبرداری کنند کلیک کنند. پس از هر رویداد نقشهبرداری مجدد، «بازیهای Google Play» در رایانه شخصی، هر کنترلی را که توسط کاربر بازنگری شده است به کنترلهای پیشفرضی که بازی شما انتظار دریافت آن را دارد، نگاشت میکند، بنابراین نیازی نیست بازی شما از نقشهبرداری مجدد بازیکن آگاه باشد. میتوانید بهصورت اختیاری داراییهای مورد استفاده برای نمایش کنترلهای صفحهکلید در بازی خود را با افزودن یک تماس برای نقشهبرداری مجدد رویدادها بهروزرسانی کنید.
«بازیهای Google Play» در فروشگاههای رایانههای شخصی، کنترلها را بهصورت محلی برای هر کاربر بازنگری میکند، و امکان کنترل پایدار در جلسات بازی را فراهم میکند. این اطلاعات فقط برای پلتفرم رایانه شخصی بر روی دیسک ذخیره می شود و تأثیری بر تجربه تلفن همراه ندارد. پس از حذف یا نصب مجدد بازیهای Google Play در رایانه شخصی، دادههای کنترل حذف میشوند. این داده ها در چندین دستگاه رایانه شخصی ثابت نیستند.
برای پشتیبانی از ویژگی remapping در بازی خود، از محدودیت های زیر اجتناب کنید:
محدودیت های نقشه برداری مجدد
در صورتی که پیوندهای کلیدی حاوی هر یک از موارد زیر باشد، میتوان ویژگیهای نگاشت مجدد را در بازی شما غیرفعال کرد:
- چند کلید
InputActions
که توسط یک کلید اصلاح کننده + یک کلید غیر اصلاح کننده تشکیل نشده اند. برای مثال، Shift + A معتبر است اما A + B ، Ctrl + Alt یا Shift + A + Tab معتبر نیست. -
InputMap
شاملInputActions
،InputGroups
یاInputContexts
با شناسههای منحصر به فرد مکرر است.
محدودیت های نقشه برداری مجدد
هنگام طراحی پیوندهای کلیدی خود برای نقشه برداری مجدد، محدودیت های زیر را در نظر بگیرید:
- نگاشت مجدد به ترکیب کلیدها پشتیبانی نمی شود. برای مثال، کاربران نمیتوانند Shift + A را به Ctrl + B یا A را به Shift + A تغییر دهند.
- Remapping برای
InputActions
با دکمه های ماوس پشتیبانی نمی شود. به عنوان مثال، Shift + کلیک راست را نمی توان دوباره نقشه برداری کرد.
نقشه برداری مجدد کلید را در بازی های Google Play در شبیه ساز رایانه شخصی آزمایش کنید
با صدور دستور adb زیر میتوانید ویژگی remapping را در بازیهای Google Play در شبیهساز رایانه شخصی در هر زمان فعال کنید:
adb shell dumpsys input_mapping_service --set RemappingFlagValue true
تغییر پوشش مانند تصویر زیر:
SDK را اضافه کنید
Input SDK را با توجه به پلتفرم توسعه خود نصب کنید.
جاوا و کاتلین
با افزودن یک وابستگی به فایل build.gradle
سطح ماژول خود، SDK ورودی جاوا یا کاتلین را دریافت کنید:
dependencies {
implementation 'com.google.android.libraries.play.games:inputmapping:1.1.1-beta'
...
}
وحدت
Input SDK یک بسته استاندارد Unity با چندین وابستگی است.
نصب بسته با تمام وابستگی ها الزامی است. راه های مختلفی برای نصب بسته ها وجود دارد.
.unitypackage
را نصب کنید
فایل Input SDK unitypackage را با تمام وابستگی های آن دانلود کنید . با انتخاب Assets > Import package > Custom Package و مکان یابی فایلی که دانلود کرده اید، می توانید .unitypackage
را نصب کنید.
با استفاده از UPM نصب کنید
همچنین می توانید بسته را با استفاده از Unity's Package Manager با دانلود .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.1-beta
با استفاده از 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 را برای همه InputActions
خود غیرفعال کنید، اما Input SDK به اندازه کافی هوشمند است که اگر در InputMap
خود از آن پشتیبانی نمی کنید، Remapping را خاموش کنید.
این مثال نقشه برداری می کند
کاتلین
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
را ذخیره می کند (برای اطلاعات بیشتر به شناسه های کلید ردیابی مراجعه کنید). -
InputRemappingOption
: یکی ازInputEnums.REMAP_OPTION_ENABLED
یاInputEnums.REMAP_OPTION_DISABLED
. مشخص می کند که آیا عملکرد برای نقشه برداری مجدد فعال است یا خیر. اگر بازی شما از نقشهبرداری مجدد پشتیبانی نمیکند، میتوانید این فیلد را نادیده بگیرید یا به سادگی آن را غیرفعال کنید. -
RemappedInputControls
: شیءInputControls
فقط خواندنی که برای خواندن کلید remapped تنظیم شده توسط کاربر در نگاشت مجدد رویدادها استفاده می شود (برای دریافت اطلاع از رویدادهای نقشه برداری مجدد استفاده می شود).
InputControls
ورودی های مرتبط با یک عمل را نشان می دهد و شامل فیلدهای زیر است:
-
AndroidKeycodes
: لیستی از اعداد صحیح است که ورودی های صفحه کلید مرتبط با یک عمل را نشان می دهد. اینها در کلاس KeyEvent یا کلاس AndroidKeycode برای Unity تعریف شده اند. -
MouseActions
: فهرستی از مقادیرMouseAction
است که ورودیهای ماوس مرتبط با این عمل را نشان میدهد.
گروه های ورودی خود را تعریف کنید
InputActions
با کنشهای منطقی مرتبط با استفاده از InputGroups
گروهبندی میشوند تا ناوبری را بهبود ببخشند و قابلیت کشف را در پوشش کنترل کنند. هر شناسه InputGroup
باید در همه InputGroups
بازی شما منحصر به فرد باشد.
با سازماندهی اقدامات ورودی خود در گروهها، یافتن کلید صحافی صحیح را برای یک بازیکن آسانتر میکنید.
اگر از remapping پشتیبانی میکنید، میتوانید تعریف کنید که چه InputGroups
میتوان دوباره ترسیم کرد. اگر بازی شما از remapping پشتیبانی نمیکند، باید گزینه remapping را برای همه InputGroups
های خود غیرفعال کنید، اما Input SDK به اندازهای هوشمند است که اگر از آن در 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
را ذخیره می کند. برای اطلاعات بیشتر به ردیابی شناسه های کلید مراجعه کنید. -
InputRemappingOption
: یکی ازInputEnums.REMAP_OPTION_ENABLED
یاInputEnums.REMAP_OPTION_DISABLED
. اگر غیرفعال باشد، تمام اشیاءInputAction
متعلق به این گروه، remapping غیرفعال خواهند شد، حتی اگر گزینه remapping آن را فعال کنند. اگر فعال باشد، تمام کنشهای متعلق به این گروه را میتوان مجدداً اضافه کرد، مگر اینکه توسط کنشهای فردی غیرفعال شده باشد.
زمینه های ورودی خود را تعریف کنید
InputContexts
به بازی شما اجازه می دهد تا از مجموعه ای متفاوت از کنترل های صفحه کلید برای صحنه های مختلف بازی شما استفاده کند. به عنوان مثال:
- شما می توانید مجموعه های مختلفی از ورودی ها را برای پیمایش منوها در مقابل حرکت در بازی مشخص کنید.
- شما ممکن است مجموعه های مختلفی از ورودی ها را بسته به حالت حرکت در بازی خود، مانند رانندگی در مقابل پیاده روی، مشخص کنید.
- میتوانید مجموعههای مختلفی از ورودیها را بر اساس وضعیت فعلی بازی خود تعیین کنید، مانند پیمایش در جهان در مقابل بازی در سطح فردی.
هنگام استفاده از InputContexts
، روکش ابتدا گروههای زمینه مورد استفاده را نشان میدهد. برای فعال کردن این رفتار، setInputContext()
را فراخوانی کنید تا هر زمان که بازی شما وارد صحنه دیگری شد، زمینه را تنظیم کنید. تصویر زیر این رفتار را نشان می دهد: در صحنه "رانندگی"، اقدامات کنترل های جاده در بالای پوشش نشان داده شده است. هنگام باز کردن منوی "فروشگاه"، اقدامات "کنترل های منو" در بالای همپوشانی نمایش داده می شود.
این بهروزرسانیهای همپوشانی با تنظیم InputContext
متفاوت در نقاط مختلف بازی شما به دست میآیند. برای انجام این کار:
-
InputActions
خود را با اقدامات منطقی مرتبط با استفاده ازInputGroups
گروه بندی کنید - این
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
را ذخیره می کند (برای اطلاعات بیشتر به شناسه های کلید ردیابی مراجعه کنید). -
ActiveGroups
: لیستی ازInputGroups
که در زمانی که این زمینه فعال است استفاده می شود و در بالای همپوشانی نمایش داده می شود.
یک نقشه ورودی بسازید
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
را ذخیره می کند (برای اطلاعات بیشتر به شناسه های کلید ردیابی مراجعه کنید). -
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
: یک رشته نسخه قابل خواندن توسط انسان برای شناسایی نسخه ای از داده های ورودی بین 2 نسخه از تغییرات داده های ورودی.
از رویدادهای نقشه برداری مجدد مطلع شوید (اختیاری)
در مورد رویدادهای remap اعلان دریافت کنید تا از کلیدهای استفاده شده در بازی خود مطلع شوید. این به بازی شما اجازه میدهد تا داراییهای نشاندادهشده در صفحه بازی را که برای نمایش کنترلهای اکشن استفاده میشود، بهروزرسانی کند.
تصویر زیر نمونه ای از این رفتار را نشان می دهد که پس از نقشه برداری مجدد کلیدها
این عملکرد با ثبت یک پاسخ تماس 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
استفاده می کنید، زمینه را برای هر انتقال به یک صحنه جدید، از جمله اولین زمینه استفاده شده برای صحنه اولیه خود، تنظیم کنید. شما باید 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 برای آزمایش و تأیید خودکار آزمایش کنید.
شبیه ساز Google Play Games در رایانه صحت نقشه ورودی شما را در برابر خطاهای رایج بررسی می کند. برای سناریوهایی مانند شناسههای منحصربهفرد تکراری، استفاده از نقشههای ورودی مختلف یا شکست در قوانین نگاشت مجدد (در صورت فعال بودن نقشهبرداری مجدد)، همپوشانی پیام خطای زیر را نشان میدهد:
اجرای 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 خود اضافه کنید تا مطمئن شوید SDK از بسته نهایی شما حذف نمی شود:
-keep class com.google.android.libraries.play.hpe.** { *; }
-keep class com.google.android.libraries.play.games.inputmapping.** { *; }
بعدش چی
پس از اینکه Input SDK را در بازی خود ادغام کردید، میتوانید با هر بازی Google Play باقیمانده در رایانه شخصی خود ادامه دهید. برای اطلاعات بیشتر، به شروع با بازیهای Google Play در رایانه شخصی مراجعه کنید.