Xamarin.Forms游戏适配Razer Kishi及跨平台游戏控制器方案咨询
Xamarin.Forms游戏控制器支持解决方案
Android平台支持Razer Kishi输入:可行,实现步骤如下
Razer Kishi属于标准HID游戏控制器,Android原生支持,可通过Xamarin.Forms的依赖服务调用Android原生API实现输入监听:
- 声明游戏手柄支持
在Android项目的AndroidManifest.xml中添加特性声明(非必须,但能帮助应用商店分类):
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
- 定义共享接口
在Xamarin.Forms共享项目中创建统一的游戏控制器服务接口:
public interface IGameControllerService { event EventHandler<GamepadInputEventArgs> GamepadInputReceived; void StartListening(); void StopListening(); } public class GamepadInputEventArgs : EventArgs { public int ButtonCode { get; set; } public bool IsPressed { get; set; } public float LeftStickX { get; set; } public float LeftStickY { get; set; } public float RightStickX { get; set; } public float RightStickY { get; set; } }
- Android平台实现接口
创建Android平台的依赖服务实现,利用系统InputDevice和MotionEvent监听输入:
[assembly: Dependency(typeof(AndroidGameControllerService))] namespace YourGame.Droid.Services { public class AndroidGameControllerService : IGameControllerService, Java.Lang.Object, View.IOnGenericMotionListener, View.IOnKeyListener { private readonly Activity _currentActivity; public event EventHandler<GamepadInputEventArgs> GamepadInputReceived; public AndroidGameControllerService() { _currentActivity = Platform.CurrentActivity; _currentActivity.Window.DecorView.SetOnGenericMotionListener(this); _currentActivity.Window.DecorView.SetOnKeyListener(this); } public void StartListening() { } public void StopListening() { _currentActivity.Window.DecorView.SetOnGenericMotionListener(null); _currentActivity.Window.DecorView.SetOnKeyListener(null); } public bool OnGenericMotion(View v, MotionEvent e) { if ((e.Source & InputSourceType.Gamepad) != 0) { var inputArgs = new GamepadInputEventArgs { LeftStickX = e.GetAxisValue(Axis.X), LeftStickY = e.GetAxisValue(Axis.Y), RightStickX = e.GetAxisValue(Axis.Z), RightStickY = e.GetAxisValue(Axis.Rz) }; GamepadInputReceived?.Invoke(this, inputArgs); return true; } return false; } public bool OnKey(View v, Keycode keyCode, KeyEvent e) { if ((e.Source & InputSourceType.Gamepad) != 0 && e.Action == KeyEventActions.Down) { var inputArgs = new GamepadInputEventArgs { ButtonCode = (int)keyCode, IsPressed = true }; GamepadInputReceived?.Invoke(this, inputArgs); return true; } return false; } } }
- 共享项目调用
在游戏逻辑中通过依赖服务获取实例,处理输入:
var controllerService = DependencyService.Get<IGameControllerService>(); controllerService.GamepadInputReceived += (sender, args) => { // 处理A键按下 if (args.ButtonCode == (int)Keycode.ButtonA && args.IsPressed) { // 执行游戏操作,比如跳跃 } // 处理左摇杆移动 if (Math.Abs(args.LeftStickX) > 0.1f) { // 控制角色左右移动 } }; controllerService.StartListening();
跨平台(Android+iOS)解决方案:存在,实现方式如下
通过依赖服务分别实现Android和iOS的原生游戏控制器监听,共享统一接口,实现跨平台输入处理:
复用共享接口
直接使用上述的IGameControllerService和GamepadInputEventArgs接口。iOS平台实现接口
利用iOS原生GCController框架实现输入监听:
[assembly: Dependency(typeof(iOSGameControllerService))] namespace YourGame.iOS.Services { public class iOSGameControllerService : IGameControllerService { private GCController _connectedController; public event EventHandler<GamepadInputEventArgs> GamepadInputReceived; public void StartListening() { GCController.DidConnect += OnControllerConnected; GCController.DidDisconnect += OnControllerDisconnected; GCController.StartWirelessControllerDiscovery(); } public void StopListening() { GCController.DidConnect -= OnControllerConnected; GCController.DidDisconnect -= OnControllerDisconnected; if (_connectedController != null) { _connectedController.ExtendedGamepad.ValueChanged -= OnGamepadValueChanged; _connectedController = null; } } private void OnControllerConnected(object sender, GCControllerEventArgs e) { _connectedController = e.Controller; if (_connectedController.ExtendedGamepad != null) { _connectedController.ExtendedGamepad.ValueChanged += OnGamepadValueChanged; } } private void OnControllerDisconnected(object sender, GCControllerEventArgs e) { if (_connectedController == e.Controller) { _connectedController.ExtendedGamepad.ValueChanged -= OnGamepadValueChanged; _connectedController = null; } } private void OnGamepadValueChanged(GCGamepad pad, GCControllerElementChangedEventArgs e) { var inputArgs = new GamepadInputEventArgs { LeftStickX = pad.LeftThumbstick.XAxis.Value, LeftStickY = pad.LeftThumbstick.YAxis.Value, RightStickX = pad.RightThumbstick.XAxis.Value, RightStickY = pad.RightThumbstick.YAxis.Value }; // 处理A键 if (pad.ButtonA.Pressed) { inputArgs.ButtonCode = (int)GCInputButton.A; inputArgs.IsPressed = true; GamepadInputReceived?.Invoke(this, inputArgs); } // 其他按键(B、X、Y等)同理处理 } } }
- 跨平台统一调用
共享项目中的调用逻辑与Android完全一致,无需额外修改,依赖服务会自动匹配当前平台的实现。
注意事项
- Android端:Razer Kishi符合标准Android游戏手柄映射,直接使用
Keycode.ButtonA等常量即可识别按键。 - iOS端:Razer Kishi iOS版本为Lightning接口,无需蓝牙权限;若支持无线控制器,需在
Info.plist中添加NSBluetoothAlwaysUsageDescription权限说明。
内容的提问来源于stack exchange,提问作者Tommi Gustafsson
相关产品推荐
相关产品推荐

