-------小基原创,转载请给我一个面子
小基认为电子游戏与电影最重要的区别就是交互,如果电子游戏没有让你输入的交互功能的话,全程都“只可远观,而不可鼓捣”的话,你可能是在看视频,怕不是玩了假游戏。所以小基来讲讲如何输入并控制物体移动
首先双击unity
点击NEW,给你的工程(游戏)起个有意思的名字(突发发现小基随便起的这个Test1856有《教团1886》的既视感XD)
创建之后就是一个空场景,右上角的布局小基习惯用2by3这种风格,你可以自行选择。
点击create,里面可以创建各种基本的物体(2d,3d等)这里随便创建一个3d的cube
之后在Project下,选中Assets,点击create创建一个C#Script脚本,起名叫做MyInput好了
下面上代码
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class MyInput : MonoBehaviour { 6 //移动方向枚举(这里列举8方向的移动,注释里面的数字是用小键盘数字的物理位置指代方向,格斗游戏术语) 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 }
!!!!网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下2个或2个以上按键并没有说明怎么解决,这里小基研究了一下方便大家!!!!!
(如果你直接写input.GetKey去读输入,直接执行物体移动的话,判断格个方向时逻辑时,如果使用if-elseif这种的话,多按键输入时候,必定只能执行其中一个方向。
如果用if判断各个方向,那么当“上”方向和“右”方向同时按下时,物理轨迹是“右上”方向,而你单个方向速度如果都是v的话,合速度方向为√2,相当于斜着走速度会变快,这两个方式都不能接受)
update()里面每帧检测CheckInputKey(),是否有按键按下或者抬起,ChangeKeyPressState()这个方法里面记下来当前有哪些按键输入。
CheckMoveDir()这个方法就是专门为了根据按下的按键的值来判断,合方向是枚举中的哪一种(这个有另一种思路,后面单独说)
CheckMove(),PlayerMove()这两个方法就是检测当前能不能移动,能移动的话就移动
target.position += move_dis;这个代码意思是把target这个物体的位置移动到新位置,a += b就相当于a = a + b,理解为在原来位置基础上再偏移move_dis就好
GetSpeedDir()这个方法里面就是根据方向枚举,确定移动的方向向量,确定完合方向后,记得要用.normalized取单位长度,这样就能保证斜方向速度与正交方向速度相同。
接下来把MyInput脚本拖到cube上,Target也绑定cube,设置好speed,点击三角开始按钮(变为蓝色表示运行)
试试单一按键,两个按键一起按下,都能正常移动
--------------------------------------另一种思路解决多按键同时按下控制移动----------------------------------------------------
上面那种方法,判断按下按键转换方向时,只处理了一个按键按下,和两个按键同时按下,那么如果我同时按下三个按键或者四个按键时候就会出问题
下面上代码,区别看下面解释
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class MyInput2 : MonoBehaviour { 6 //移动方向枚举 7 enum MoveDir 8 { 9 None = 0, //不动 10 Up = 1, //上8 11 Down = -1, //下2 12 Left = 10, //左4 13 Right = -10, //右6 14 UL = 11, //左上7 15 UR = -9, //右上9 16 DL = 9, //左下1 17 DR = -11, //右下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 int moveDirValue = 0; 30 //按压记录 31 private bool isUpPress = false; 32 private bool isDownPress = false; 33 private bool isLeftPress = false; 34 private bool isRightPress = false; 35 36 //是否可以移动 37 private bool canMove = true; 38 //右移动 39 private Vector3 MOVE_RIGHT = new Vector3(1, 0, 0); 40 //上移动 41 private Vector3 MOVE_UP = new Vector3(0, 1, 0); 42 43 //外部调控速度 44 public float speed = 2f; 45 //移动速度向量 46 private Vector3 move_speed_dir = Vector3.zero; 47 //移动距离 48 private Vector3 move_dis = Vector3.zero; 49 50 //控制目标 51 public Transform target; 52 53 // Use this for initialization 54 void Start () { 55 56 } 57 58 // Update is called once per frame 59 void Update () { 60 CheckInputKey(); 61 CheckMoveDir(); 62 } 63 64 void FixedUpdate() 65 { 66 CheckMove(); 67 } 68 69 //检测输入按键 70 void CheckInputKey() 71 { 72 //检测单一输入 73 foreach (KeyCode kcode in System.Enum.GetValues(typeof(KeyCode))) 74 { 75 if (Input.GetKeyDown(kcode)) 76 { 77 Debug.Log("Single KeyCode: " + kcode); 78 ChangeKeyPressState(kcode, true); 79 } 80 81 if (Input.GetKeyUp(kcode)) 82 { 83 Debug.Log("Single KeyCode: " + kcode); 84 ChangeKeyPressState(kcode, false); 85 } 86 } 87 } 88 89 //记录按键的按压状态 90 void ChangeKeyPressState(KeyCode keyCode, bool isPress) 91 { 92 switch(keyCode) 93 { 94 case INPUT_UP: 95 isUpPress = isPress; 96 break; 97 case INPUT_DOWN: 98 isDownPress = isPress; 99 break; 100 case INPUT_LEFT: 101 isLeftPress = isPress; 102 break; 103 case INPUT_RIGHT: 104 isRightPress = isPress; 105 break; 106 } 107 } 108 109 //确定移动方向 110 void CheckMoveDir() 111 { 112 moveDirValue = 0; 113 //确定方向 114 if(isUpPress) 115 { 116 moveDirValue += (int)MoveDir.Up; 117 } 118 if (isDownPress) 119 { 120 moveDirValue += (int)MoveDir.Down; 121 } 122 if (isLeftPress) 123 { 124 moveDirValue += (int)MoveDir.Left; 125 } 126 if (isRightPress) 127 { 128 moveDirValue += (int)MoveDir.Right; 129 } 130 } 131 132 //检测是否可以移动 133 void CheckMove() 134 { 135 //某些情况下可能禁止移动,例如暂停,播放CG等 136 if(canMove && moveDirValue != (int)MoveDir.None) 137 { 138 PlayerMove(target, speed); 139 } 140 } 141 142 //移动 143 void PlayerMove(Transform target, float speed) 144 { 145 move_dis = speed * Time.deltaTime * GetSpeedDir(); 146 target.position += move_dis; 147 } 148 149 //速度向量 150 Vector3 GetSpeedDir() 151 { 152 switch(moveDirValue) 153 { 154 case (int)MoveDir.Up: 155 move_speed_dir = MOVE_UP; 156 break; 157 case (int)MoveDir.Down: 158 move_speed_dir = -MOVE_UP; 159 break; 160 case (int)MoveDir.Left: 161 move_speed_dir = -MOVE_RIGHT; 162 break; 163 case (int)MoveDir.Right: 164 move_speed_dir = MOVE_RIGHT; 165 break; 166 case (int)MoveDir.UL: 167 move_speed_dir = MOVE_UP - MOVE_RIGHT; 168 break; 169 case (int)MoveDir.UR: 170 move_speed_dir = MOVE_UP + MOVE_RIGHT; 171 break; 172 case (int)MoveDir.DL: 173 move_speed_dir = -MOVE_UP - MOVE_RIGHT; 174 break; 175 case (int)MoveDir.DR: 176 move_speed_dir = -MOVE_UP + MOVE_RIGHT; 177 break; 178 } 179 return move_speed_dir.normalized; 180 } 181 }
枚举方向定义了不同的值,这样同时按下三个按键的时候,必定有两个方向时一对相反的,那么求“合”速度时候,就可以抵消掉。如果四个方向同时按下,就相当于不动了,问题搞定!
没有经验的同学按照这个流程一步一步做,应该也能实现移动物体这个效果的。
顺便祝愿你们都有三次元会动的“对象”(来自单身狗的真诚祝福)
工程下载https://pan.baidu.com/s/1opWziUOW7QdzMpn3hcaQ4A