NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Input/MigrationGuide.md

235 lines
7.4 KiB
Markdown
Raw Normal View History

# 输入系统迁移指南
本指南将帮助您从旧版 `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 的解释器
### 如何管理之前的优先级系统?
新架构中,优先级是通过显式启用/禁用不同的输入处理器来管理的,而不是隐式的优先级系统。这样可以提供更清晰的控制流和更好的可预测性。
## 结论
迁移到新的输入系统架构将提高代码的可维护性和可扩展性。虽然初始迁移需要一些工作,但长期收益将远远超过投入的成本。如果在迁移过程中遇到问题,请参考示例代码或联系开发团队获取支持。