235 lines
7.4 KiB
Markdown
235 lines
7.4 KiB
Markdown
|
|
# 输入系统迁移指南
|
|||
|
|
|
|||
|
|
本指南将帮助您从旧版 `InputManager` 迁移到新的基于 `InputProcessor` 的输入系统架构。
|
|||
|
|
|
|||
|
|
## 为什么要迁移?
|
|||
|
|
|
|||
|
|
新的输入系统架构提供了以下优势:
|
|||
|
|
|
|||
|
|
1. **更好的关注点分离** - 输入处理器只负责特定的输入领域,例如 UI 输入、游戏玩法输入或相机控制
|
|||
|
|
2. **更精细的控制** - 可以独立启用或禁用不同的输入处理器
|
|||
|
|
3. **简化的设计** - 直接的解释器和处理器连接,移除了多余的中间层
|
|||
|
|
4. **灵活的组合** - 可以根据需要组合不同类型的解释器和处理器
|
|||
|
|
|
|||
|
|
## 迁移步骤概述
|
|||
|
|
|
|||
|
|
1. 识别您的应用程序中的不同输入域(UI 输入、游戏玩法输入等)
|
|||
|
|
2. 为每个域创建专用的输入处理器
|
|||
|
|
3. 设置 `InputProcessor` 组件并配置适当的解释器类型
|
|||
|
|
4. 将对 `InputManager.Instance` 的引用替换为相应的 `InputProcessor` 实例
|
|||
|
|
5. 进行测试并确保功能正常
|
|||
|
|
|
|||
|
|
## 详细迁移步骤
|
|||
|
|
|
|||
|
|
### 步骤 1:识别输入域
|
|||
|
|
|
|||
|
|
识别您的应用程序中的不同输入需求。常见的域包括:
|
|||
|
|
|
|||
|
|
- UI 交互(按钮点击、拖动等)
|
|||
|
|
- 游戏玩法控制(角色移动、操作等)
|
|||
|
|
- 相机控制(平移、缩放、旋转)
|
|||
|
|
- 特殊工具或模式(例如编辑模式、调试模式)
|
|||
|
|
|
|||
|
|
### 步骤 2:创建输入处理器
|
|||
|
|
|
|||
|
|
为每个输入域创建专用的处理器类,这些类应实现 `IMobileInputEventHandler` 接口:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class GameplayInputHandler : MonoBehaviour, IMobileInputEventHandler
|
|||
|
|
{
|
|||
|
|
// 实现接口方法
|
|||
|
|
public void OnFingerDown(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 处理按下事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnFingerUp(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 处理抬起事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnFingerMove(Vector2 delta)
|
|||
|
|
{
|
|||
|
|
// 处理移动事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnFingerTap(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 处理点击事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnFingerLongPress(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 处理长按事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnFingerLongPressUp(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 处理长按释放事件
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnZoom(float delta)
|
|||
|
|
{
|
|||
|
|
// 处理缩放事件
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤 3:设置 InputProcessor
|
|||
|
|
|
|||
|
|
在相应的场景或控制器中设置 `InputProcessor` 实例:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 在游戏控制器或管理器中
|
|||
|
|
private InputProcessor gameplayInputProcessor;
|
|||
|
|
private GameplayInputHandler gameplayInputHandler;
|
|||
|
|
|
|||
|
|
private void Start()
|
|||
|
|
{
|
|||
|
|
// 创建输入处理器
|
|||
|
|
gameplayInputHandler = gameObject.AddComponent<GameplayInputHandler>();
|
|||
|
|
|
|||
|
|
// 创建 InputProcessor 并配置其输入解释器类型
|
|||
|
|
// 对于游戏玩法,可能使用 PC 或 Touch 解释器
|
|||
|
|
gameplayInputProcessor = InputProcessor.Create(
|
|||
|
|
"GameplayInput",
|
|||
|
|
InputInterpreterType.PC, // 在 PC 平台上
|
|||
|
|
gameplayInputHandler
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤 4:替换 InputManager 引用
|
|||
|
|
|
|||
|
|
找到代码中对 `InputManager.Instance` 的所有引用,并替换为相应的 `InputProcessor` 实例和方法调用:
|
|||
|
|
|
|||
|
|
**旧代码**:
|
|||
|
|
```csharp
|
|||
|
|
// 检查触摸状态
|
|||
|
|
if (InputManager.Instance.HasTouch())
|
|||
|
|
{
|
|||
|
|
// 获取触摸位置
|
|||
|
|
Vector2 touchPos = InputManager.Instance.GetTouchPosition();
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 订阅事件
|
|||
|
|
InputManager.Instance.OnFingerMove += OnFingerMoveHandler;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**新代码**:
|
|||
|
|
```csharp
|
|||
|
|
// 检查触摸状态
|
|||
|
|
if (gameplayInputProcessor.HasTouch())
|
|||
|
|
{
|
|||
|
|
// 获取触摸位置
|
|||
|
|
Vector2 touchPos = gameplayInputProcessor.GetTouchPosition();
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 事件处理现在直接在 GameplayInputHandler 中实现
|
|||
|
|
// 不再需要单独的事件订阅
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤 5:添加特殊处理
|
|||
|
|
|
|||
|
|
在某些情况下,您可能需要特定的输入处理逻辑:
|
|||
|
|
|
|||
|
|
#### UI 排除处理
|
|||
|
|
|
|||
|
|
如果您需要排除 UI 区域的输入:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 使用排除 UI 的解释器类型
|
|||
|
|
UIExcludedInputProcessor = InputProcessor.Create(
|
|||
|
|
"GameplayInput",
|
|||
|
|
InputInterpreterType.PC_ExcludeUI, // 排除 UI 区域的输入
|
|||
|
|
gameplayInputHandler
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 组织多个 InputProcessor
|
|||
|
|
|
|||
|
|
对于复杂应用程序,您可以创建一个管理类来组织多个输入处理器:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class GameInputSystem : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
[SerializeField] private InputInterpreterType uiInputInterpreterType = InputInterpreterType.PC_ExcludeUI;
|
|||
|
|
[SerializeField] private InputInterpreterType gameplayInputInterpreterType = InputInterpreterType.PC;
|
|||
|
|
[SerializeField] private InputInterpreterType cameraInputInterpreterType = InputInterpreterType.PC;
|
|||
|
|
|
|||
|
|
private InputProcessor uiInputProcessor;
|
|||
|
|
private InputProcessor gameplayInputProcessor;
|
|||
|
|
private InputProcessor cameraInputProcessor;
|
|||
|
|
|
|||
|
|
private UIInputHandler uiInputHandler;
|
|||
|
|
private GameplayInputHandler gameplayInputHandler;
|
|||
|
|
private CameraInputHandler cameraInputHandler;
|
|||
|
|
|
|||
|
|
private void Awake()
|
|||
|
|
{
|
|||
|
|
CreateHandlers();
|
|||
|
|
CreateInputProcessors();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CreateHandlers()
|
|||
|
|
{
|
|||
|
|
uiInputHandler = gameObject.AddComponent<UIInputHandler>();
|
|||
|
|
gameplayInputHandler = gameObject.AddComponent<GameplayInputHandler>();
|
|||
|
|
cameraInputHandler = gameObject.AddComponent<CameraInputHandler>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CreateInputProcessors()
|
|||
|
|
{
|
|||
|
|
uiInputProcessor = InputProcessor.Create("UIInput", uiInputInterpreterType, uiInputHandler, transform);
|
|||
|
|
gameplayInputProcessor = InputProcessor.Create("GameplayInput", gameplayInputInterpreterType, gameplayInputHandler, transform);
|
|||
|
|
cameraInputProcessor = InputProcessor.Create("CameraInput", cameraInputInterpreterType, cameraInputHandler, transform);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void EnableUIInput(bool enable) => uiInputProcessor.IsEnable = enable;
|
|||
|
|
public void EnableGameplayInput(bool enable) => gameplayInputProcessor.IsEnable = enable;
|
|||
|
|
public void EnableCameraInput(bool enable) => cameraInputProcessor.IsEnable = enable;
|
|||
|
|
|
|||
|
|
public bool HasTouch() => gameplayInputProcessor.HasTouch() || uiInputProcessor.HasTouch() || cameraInputProcessor.HasTouch();
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 常见问题解答
|
|||
|
|
|
|||
|
|
### 如何处理输入处理器之间的交互?
|
|||
|
|
|
|||
|
|
在 `GameInputSystem` 类中管理输入优先级和交互。例如,可以在 UI 交互期间禁用游戏玩法输入:
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// 在 UIInputHandler 中
|
|||
|
|
public void OnFingerDown(Vector2 screenPosition)
|
|||
|
|
{
|
|||
|
|
// 通知 GameInputSystem UI 交互开始
|
|||
|
|
GameInputSystem.Instance.OnUIInteractionStarted();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 在 GameInputSystem 中
|
|||
|
|
public void OnUIInteractionStarted()
|
|||
|
|
{
|
|||
|
|
// 暂时禁用游戏玩法输入
|
|||
|
|
EnableGameplayInput(false);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 如何选择合适的解释器类型?
|
|||
|
|
|
|||
|
|
- **PC** - 处理所有鼠标和键盘输入,不考虑 UI 状态
|
|||
|
|
- **PC_ExcludeUI** - 只处理非 UI 区域的鼠标和键盘输入
|
|||
|
|
- **Touch** - 处理所有触摸输入,不考虑 UI 状态
|
|||
|
|
- **Touch_ExcludeUI** - 只处理非 UI 区域的触摸输入
|
|||
|
|
- **AutoPlatform** - 根据平台自动选择解释器(PC 或 Touch)
|
|||
|
|
- **AutoPlatform_ExcludeUI** - 自动选择排除 UI 的解释器
|
|||
|
|
|
|||
|
|
### 如何管理之前的优先级系统?
|
|||
|
|
|
|||
|
|
新架构中,优先级是通过显式启用/禁用不同的输入处理器来管理的,而不是隐式的优先级系统。这样可以提供更清晰的控制流和更好的可预测性。
|
|||
|
|
|
|||
|
|
## 结论
|
|||
|
|
|
|||
|
|
迁移到新的输入系统架构将提高代码的可维护性和可扩展性。虽然初始迁移需要一些工作,但长期收益将远远超过投入的成本。如果在迁移过程中遇到问题,请参考示例代码或联系开发团队获取支持。
|