-------小基原创,转载请给我一个面子
网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下2个或2个以上按键并没有说明怎么解决,这里小基研究了一下方便大家
(如果你直接写input.GetKey去读输入,直接执行物体移动的话,判断格个方向时逻辑时,如果使用if-elseif这种的话,多按键输入时候,必定只能执行其中一个方向。
如果用if判断各个方向,那么当“上”方向和“右”方向同时按下时,物理轨迹是“右上”方向,而你单个方向速度如果都是v的话,合速度方向为√2,相当于斜着走速度会变快,这两个方式都不能接受)
所以解决思路是当按键按下时,记录状态,抬起时重置状态,根据当前所有输入的按键状态,统一处理得出一个合方向,并且对合速度处理
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4
5 public class MyInput : MonoBehaviour {
6 //移动方向枚举
7 enum MoveDir
8 {
9 None, //不动
10 Up, //上8
11 Down, //下2
12 Left, //左4
13 Right, //右6
14 UL, //左上7
15 UR, //右上9
16 DL, //左下1
17 DR, //右下3
18 }
19
20 //输入按键常量(之后走配置)
21 const KeyCode INPUT_UP = KeyCode.W;
22 const KeyCode INPUT_DOWN = KeyCode.S;
23 const KeyCode INPUT_LEFT = KeyCode.A;
24 const KeyCode INPUT_RIGHT = KeyCode.D;
25
26 //默认移动方向
27 private MoveDir moveDir = MoveDir.None;
28 //按压记录
29 private bool isUpPress = false;
30 private bool isDownPress = false;
31 private bool isLeftPress = false;
32 private bool isRightPress = false;
33
34 //是否可以移动
35 private bool canMove = true;
36 //右移动
37 private Vector3 MOVE_RIGHT = new Vector3(1, 0, 0);
38 //上移动
39 private Vector3 MOVE_UP = new Vector3(0, 1, 0);
40
41 //外部调控速度
42 public float speed = 2f;
43 //移动速度向量
44 private Vector3 move_speed_dir = Vector3.zero;
45 //移动距离
46 private Vector3 move_dis = Vector3.zero;
47
48 //控制目标
49 public Transform target;
50
51 // Use this for initialization
52 void Start () {
53
54 }
55
56 // Update is called once per frame
57 void Update () {
58 CheckInputKey();
59 CheckMoveDir();
60 }
61
62 void FixedUpdate()
63 {
64 CheckMove();
65 }
66
67 //检测输入按键
68 void CheckInputKey()
69 {
70 //检测单一输入
71 foreach (KeyCode kcode in System.Enum.GetValues(typeof(KeyCode)))
72 {
73 if (Input.GetKeyDown(kcode))
74 {
75 //Debug.Log("Single KeyCode: " + kcode);
76 ChangeKeyPressState(kcode, true);
77 }
78
79 if (Input.GetKeyUp(kcode))
80 {
81 //Debug.Log("Single KeyCode: " + kcode);
82 ChangeKeyPressState(kcode, false);
83 }
84 }
85 }
86
87 //记录按键的按压状态
88 void ChangeKeyPressState(KeyCode keyCode, bool isPress)
89 {
90 switch(keyCode)
91 {
92 case INPUT_UP:
93 isUpPress = isPress;
94 break;
95 case INPUT_DOWN:
96 isDownPress = isPress;
97 break;
98 case INPUT_LEFT:
99 isLeftPress = isPress;
100 break;
101 case INPUT_RIGHT:
102 isRightPress = isPress;
103 break;
104 }
105 }
106
107 //确定移动方向
108 void CheckMoveDir()
109 {
110 //确定方向
111 if(isUpPress && isLeftPress)
112 {
113 moveDir = MoveDir.UL;
114 }
115 else if(isUpPress && isRightPress)
116 {
117 moveDir = MoveDir.UR;
118 }
119 else if (isDownPress && isLeftPress)
120 {
121 moveDir = MoveDir.DL;
122 }
123 else if (isDownPress && isRightPress)
124 {
125 moveDir = MoveDir.DR;
126 }
127 else if(isUpPress)
128 {
129 moveDir = MoveDir.Up;
130 }
131 else if (isDownPress)
132 {
133 moveDir = MoveDir.Down;
134 }
135 else if (isLeftPress)
136 {
137 moveDir = MoveDir.Left;
138 }
139 else if (isRightPress)
140 {
141 moveDir = MoveDir.Right;
142 }
143 else
144 {
145 moveDir = MoveDir.None;
146 }
147 }
148
149 //检测是否可以移动
150 void CheckMove()
151 {
152 //某些情况下可能禁止移动,例如暂停,播放CG等
153 if(canMove && moveDir != MoveDir.None)
154 {
155 PlayerMove(target, speed);
156 }
157 }
158
159 //移动
160 void PlayerMove(Transform target, float speed)
161 {
162 move_dis = speed * Time.deltaTime * GetSpeedDir();
163 target.position += move_dis;
164 }
165
166 //速度向量
167 Vector3 GetSpeedDir()
168 {
169 switch(moveDir)
170 {
171 case MoveDir.Up:
172 move_speed_dir = MOVE_UP;
173 break;
174 case MoveDir.Down:
175 move_speed_dir = -MOVE_UP;
176 break;
177 case MoveDir.Left:
178 move_speed_dir = -MOVE_RIGHT;
179 break;
180 case MoveDir.Right:
181 move_speed_dir = MOVE_RIGHT;
182 break;
183 case MoveDir.UL:
184 move_speed_dir = MOVE_UP - MOVE_RIGHT;
185 break;
186 case MoveDir.UR:
187 move_speed_dir = MOVE_UP + MOVE_RIGHT;
188 break;
189 case MoveDir.DL:
190 move_speed_dir = -MOVE_UP - MOVE_RIGHT;
191 break;
192 case MoveDir.DR:
193 move_speed_dir = -MOVE_UP + MOVE_RIGHT;
194 break;
195 }
196 return move_speed_dir.normalized;
197 }
198 }
update()里面每帧检测CheckInputKey(),是否有按键按下或者抬起,ChangeKeyPressState()这个方法里面记下来当前有哪些按键输入。
CheckMoveDir()这个方法就是专门为了根据按下的按键的值来判断,合方向是枚举中的哪一种
CheckMove(),PlayerMove()这两个方法就是检测当前能不能移动,能移动的话就移动
GetSpeedDir()这个方法里面就是根据方向枚举,确定移动的方向向量,确定完合方向后,记得要用.normalized取单位长度,这样就能保证斜方向速度与正交方向速度相同。
-------------------另一种思路解决多按键同时按下控制移动-----------------
上面那种方法,
CheckMoveDir()判断按下按键转换方向时,只处理了一个按键按下,和两个按键同时按下,那么如果我同时按下三个按键或者四个按键时候就会出问题
下面是修改
//移动方向枚举
enum MoveDir
{
None = 0, //不动
Up = 1, //上8
Down = -1, //下2
Left = 10, //左4
Right = -10, //右6
UL = 11, //左上7
UR = -9, //右上9
DL = 9, //左下1
DR = -11, //右下3
}
枚举方向定义了不同的值
//确定移动方向
void CheckMoveDir()
{
moveDirValue = 0;
//确定方向
if(isUpPress)
{
moveDirValue += (int)MoveDir.Up;
}
if (isDownPress)
{
moveDirValue += (int)MoveDir.Down;
}
if (isLeftPress)
{
moveDirValue += (int)MoveDir.Left;
}
if (isRightPress)
{
moveDirValue += (int)MoveDir.Right;
}
target.GetComponent<Player>().TurnDir(moveDirValue);
}
这样同时按下三个按键的时候,必定有两个方向时一对相反的,那么求“合”速度时候,就可以抵消掉,如果四个方向同时按下,就相当于不动了,问题搞定!
做游戏,一定要有爱