-------小基原創,轉載請給我一個面子
網上有很多講輸入控制如何移動,但是多數都是講單一按下,對於同時按下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); }
這樣同時按下三個按鍵的時候,必定有兩個方向時一對相反的,那么求“合”速度時候,就可以抵消掉,如果四個方向同時按下,就相當於不動了,問題搞定!