182 lines
4.4 KiB
Markdown
182 lines
4.4 KiB
Markdown
https://zhuanlan.zhihu.com/p/424070778
|
||
|
||
### 游戏输入系统设计总结
|
||
|
||
#### **核心设计思路**
|
||
|
||
1. **输入抽象分层**:
|
||
|
||
- **基础输入层**:将输入抽象为按钮(`IButtonInput`)和轴值(`IAxisInput`)两类
|
||
|
||
- **复合输入层**:支持多个按键绑定到同一行为(`CompoundButtonInput`/`CompoundAxisInput`)
|
||
|
||
- **行为映射层**:将输入状态转化为游戏行为(`InputButtonProcessor`)
|
||
|
||
2. **关键接口设计**:
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
// 按钮输入
|
||
public interface IButtonInput {
|
||
bool GetButton(); // 获取按钮状态
|
||
}
|
||
|
||
// 轴值输入
|
||
public interface IAxisInput {
|
||
float AxisValue(); // 获取轴值(-1~1)
|
||
}
|
||
|
||
|
||
#### **核心组件实现**
|
||
|
||
1. **基础输入实现**:
|
||
|
||
- `KeyCodeButtonInput`:封装Unity键值检测
|
||
|
||
- `ButtonAxisInput`:将按钮转为轴值(正/负方向)
|
||
|
||
2. **复合输入容器**:
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
// 复合按钮(OR逻辑)
|
||
public class CompoundButtonInput : IButtonInput {
|
||
public bool GetButton() {
|
||
foreach(var btn in Buttons)
|
||
if(btn.GetButton()) return true;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 复合轴值(取极值叠加)
|
||
public class CompoundAxisInput : IAxisInput {
|
||
public float AxisValue() {
|
||
float max=0, min=0;
|
||
foreach(var axis in Axis) {
|
||
float val = axis.AxisValue();
|
||
if(val<0) min = Mathf.Min(min, val);
|
||
else max = Mathf.Max(max, val);
|
||
}
|
||
return max + min;
|
||
}
|
||
}
|
||
|
||
3. **行为状态机**:
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
public class InputButtonProcessor {
|
||
// 状态记录
|
||
public bool WasPressed; // 上一帧状态
|
||
public bool IsPressed; // 当前帧状态
|
||
|
||
// 状态查询属性
|
||
public bool OnPressed => IsPressed && !WasPressed; // 刚按下
|
||
public bool OnReleased => !IsPressed && WasPressed; // 刚释放
|
||
|
||
// 状态更新
|
||
public void Update(bool isPressed) {
|
||
WasPressed = IsPressed;
|
||
IsPressed = isPressed;
|
||
}
|
||
}
|
||
|
||
|
||
#### **系统工作流程**
|
||
|
||
1. **初始化绑定**(PlayerInput):
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
public void AddKeyboardControls() {
|
||
// 水平轴:A/D/左右箭头
|
||
HorizontalDigiPad.Add(new ButtonAxisInput(
|
||
new KeyCodeButtonInput(KeyCode.A),
|
||
ButtonAxisInput.Mode.Negative
|
||
));
|
||
|
||
// 跳跃:空格/Z/Y
|
||
Jump.Add(new KeyCodeButtonInput(KeyCode.Space));
|
||
}
|
||
|
||
2. **状态更新**(每帧):
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
void RefreshControls() {
|
||
// 1. 更新轴值输入
|
||
Input.HorizontalValue = HorizontalDigiPad.AxisValue();
|
||
|
||
// 2. 更新按钮状态机
|
||
for(int i=0; i<buttonInputs.Count; i++) {
|
||
bool pressed = buttonInputs[i].GetButton();
|
||
buttonProcessors[i].Update(pressed);
|
||
}
|
||
}
|
||
|
||
3. **游戏逻辑使用**:
|
||
|
||
csharp
|
||
|
||
复制
|
||
|
||
下载
|
||
|
||
void Update() {
|
||
if(Input.Jump.OnPressed) {
|
||
// 处理跳跃触发
|
||
}
|
||
|
||
if(Input.Right.Pressed) {
|
||
// 处理持续右移
|
||
}
|
||
}
|
||
|
||
|
||
#### **设计优势**
|
||
|
||
1. **多键位绑定**:一个行为支持多个触发键(如跳跃可用空格/Z/Y)
|
||
|
||
2. **输入抽象**:统一处理键盘/鼠标/手柄等输入设备
|
||
|
||
3. **状态封装**:提供精细的输入状态检测(按下/持续/释放)
|
||
|
||
4. **动态配置**:运行时切换控制方案(`RefreshControlScheme()`)
|
||
|
||
5. **行为解耦**:游戏逻辑只依赖抽象行为而非具体按键
|
||
|
||
|
||
#### **扩展建议**
|
||
|
||
1. **输入重映射**:添加键位配置保存/加载功能
|
||
|
||
2. **输入缓冲**:实现指令缓冲窗口提升操作手感
|
||
|
||
3. **设备扩展**:集成手柄输入(`GamepadButtonInput`)
|
||
|
||
4. **组合键**:支持Ctrl+Jump等组合键检测
|
||
|
||
5. **输入事件**:改用事件驱动减少每帧状态查询
|
||
|
||
|
||
> 该设计通过分层抽象解决了多键位绑定问题,核心价值在于将**物理输入**到**游戏行为**的映射关系标准化,为复杂输入需求提供了可扩展框架。 |