-------小基原创,转载请给我一个面子
网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下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); }
这样同时按下三个按键的时候,必定有两个方向时一对相反的,那么求“合”速度时候,就可以抵消掉,如果四个方向同时按下,就相当于不动了,问题搞定!