unity零基礎開始學習做游戲(三)鼠標輸入,來個虛擬搖桿怎么樣?


 

 

-------小基原創,轉載請給我一個面子

  現在移動游戲越來越火,大家都拿手機平板玩游戲,沒有鍵盤和手柄輸入,所以就不得不看看虛擬搖桿怎么搞?(小基對於沒有實體反饋不是很喜歡呢)

首先要清楚,鼠標操作輸入,應該在2d的UI平面上做一個虛擬搖桿,如下圖

 

Hierarchy面板下點Create創建一個UI里面的Image

會自動創建一個Canvas(畫布),UI方面的東西都在這里面顯示

我們再創建一個專門處理UI的攝像機(這個主要處理鼠標點擊時候,獲取屏幕坐標,來處理移動邏輯,如果使用默認的MainCamera的話,正交模式下,沒法體現3D,投影模式下,鼠標點擊輸入坐標處理起來也有點惡心,這些坑我會單獨在另一個技術文章里細說,對於新手來講,先知道這里單做一個UICamera可以避免坑就行。踩坑的方式,花樣可多了

Hierarchy面板下用Create創建一個UI里面的Camera,改名為UICamera

 

設置成這樣,記得把AudioListener這個組件移除掉,因為MainCamera上面已經有一個接收聲音的了。紅框內切記,不然待會都找不到你的搖桿Orz

(具體參數細節這里不展開講了,這個系列以實現功能為目標,講原理的話,太枯燥了,怕不是看睡着了)

 

接下來是制作虛擬搖桿,兩張圖片,大圈里面放個小圈。

 

在Canvas下創建兩個Image,分別起名,小圓作為大圓的子物體(這樣就可以成為整體,一起移動了)

使用unity自帶的圖片湊合用,一個白色,一個紅色,效果明顯點

 

最后效果就是這樣,好吧,原諒我的美術是體育老師教的XD

 

 接下來在創建一個空物體Main,用來掛腳本MyInput2(基於上一篇的控制移動,在加點東西就非常實用了)

下面上代碼

  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 
 54     //鼠標按下時的坐標
 55     private Vector3 mouseStartPos = Vector3.zero;
 56     //鼠標是否按下
 57     private bool isMousePress = false;
 58     //鼠標枚舉
 59     const KeyCode INPUT_MOUSE = KeyCode.Mouse0;
 60     //鼠標拖動范圍
 61     const float MOUSE_RADIUS = 20;
 62     //鼠標移動向量
 63     private Vector3 mouseDir = Vector3.zero;
 64     //鼠標速度衰減
 65     private float mouseSpeedRate = 0;
 66     //鼠標速度
 67     public float mouseSpeed = 2;
 68     //搖桿底
 69     public RectTransform joyStickDown;
 70     //搖桿頂
 71     public RectTransform joyStickUp;
 72     //攝像機
 73     public Camera camera;
 74 
 75 
 76     // Update is called once per frame
 77     void Update () {
 78         CheckInputKey();
 79         CheckMoveDir();
 80         CheckMouseDir();
 81     }
 82 
 83     void FixedUpdate()
 84     {
 85         CheckMove();
 86     }
 87 
 88     //檢測輸入按鍵
 89     void CheckInputKey()
 90     {
 91         //檢測單一輸入
 92         foreach (KeyCode kcode in System.Enum.GetValues(typeof(KeyCode)))
 93         {
 94             if (Input.GetKeyDown(kcode))
 95             {
 96                 //Debug.Log("Single KeyCode Down: " + kcode);
 97                 ChangeKeyPressState(kcode, true);
 98             }
 99 
100             if (Input.GetKeyUp(kcode))
101             {
102                 //Debug.Log("Single KeyCode Up: " + kcode);
103                 ChangeKeyPressState(kcode, false);
104             }
105         }
106     }
107 
108     //記錄按鍵的按壓狀態
109     void ChangeKeyPressState(KeyCode keyCode, bool isPress)
110     {
111         switch(keyCode)
112         {
113             case INPUT_UP:
114                 isUpPress = isPress;
115                 break;
116             case INPUT_DOWN:
117                 isDownPress = isPress;
118                 break;
119             case INPUT_LEFT:
120                 isLeftPress = isPress;
121                 break;
122             case INPUT_RIGHT:
123                 isRightPress = isPress;
124                 break;
125             case INPUT_MOUSE:
126                 MouseStateChange(isPress);
127                 break;
128         }
129     }
130 
131     //鼠標按鍵輸入
132     void MouseStateChange(bool isPress)
133     {
134         isMousePress = isPress;
135         mouseStartPos = isPress ? Input.mousePosition : Vector3.zero;
136         joyStickDown.gameObject.SetActive(isPress);
137         joyStickDown.position = camera.ScreenToWorldPoint(mouseStartPos);
138     }
139 
140     //鼠標移動
141     void CheckMouseDir()
142     {
143         if(isMousePress)
144         {
145             mouseDir = Input.mousePosition - mouseStartPos;
146             mouseSpeedRate = Mathf.Min(mouseDir.magnitude / MOUSE_RADIUS, 1);
147             move_dis = mouseSpeed * mouseSpeedRate * Time.deltaTime * mouseDir.normalized;
148             target.position += move_dis;
149             joyStickUp.localPosition = mouseDir.normalized * mouseSpeedRate * MOUSE_RADIUS;
150         }
151     }
152 
153     //確定移動方向
154     void CheckMoveDir()
155     {
156         moveDirValue = 0;
157         //確定方向
158         if(isUpPress)
159         {
160             moveDirValue += (int)MoveDir.Up;
161         }
162         if (isDownPress)
163         {
164             moveDirValue += (int)MoveDir.Down;
165         }
166         if (isLeftPress)
167         {
168             moveDirValue += (int)MoveDir.Left;
169         }
170         if (isRightPress)
171         {
172             moveDirValue += (int)MoveDir.Right;
173         }
174     }
175 
176     //檢測是否可以移動
177     void CheckMove()
178     {
179         //某些情況下可能禁止移動,例如暫停,播放CG等
180         if(canMove && moveDirValue != (int)MoveDir.None)
181         {
182             PlayerMove(target, speed);
183         }
184     }
185 
186     //移動
187     void PlayerMove(Transform target, float speed)
188     {
189         move_dis = speed * Time.deltaTime * GetSpeedDir();
190         target.position += move_dis;
191     }
192 
193     //速度向量
194     Vector3 GetSpeedDir()
195     {
196         switch(moveDirValue)
197         {
198             case (int)MoveDir.Up:
199                 move_speed_dir = MOVE_UP;
200                 break;
201             case (int)MoveDir.Down:
202                 move_speed_dir = -MOVE_UP;
203                 break;
204             case (int)MoveDir.Left:
205                 move_speed_dir = -MOVE_RIGHT;
206                 break;
207             case (int)MoveDir.Right:
208                 move_speed_dir = MOVE_RIGHT;
209                 break;
210             case (int)MoveDir.UL:
211                 move_speed_dir = MOVE_UP - MOVE_RIGHT;
212                 break;
213             case (int)MoveDir.UR:
214                 move_speed_dir = MOVE_UP + MOVE_RIGHT;
215                 break;
216             case (int)MoveDir.DL:
217                 move_speed_dir = -MOVE_UP - MOVE_RIGHT;
218                 break;
219             case (int)MoveDir.DR:
220                 move_speed_dir = -MOVE_UP + MOVE_RIGHT;
221                 break;
222         }
223         return move_speed_dir.normalized;
224     }
225 }

 

 在按鍵輸入控制的基礎上,加上鼠標輸入就ok了

思路就是:按下時候記錄此時坐標,然后拖動后的當前坐標與起始坐標的向量差值,就是物體應該移動的方向

先把變量都定義好

核心就是鼠標左鍵按下的記錄狀態(這里做了個有意思的處理,第一次按下的位置,搖桿就會出現在那個位置,拖動的時候,小圓在大圓內部移動)

 

接下來把腳本綁定好

 

運行游戲,類似於這個效果,鼠標移動,紅圈在白圈內移動,移動方向就是白方塊(主角)移動方向 

 

ok,通過兩篇介紹,除了腳本稍稍有點難理解之外,其他應該都能一步一步做出來了,零基礎的你看到自己做的“小游戲”,是不是已經成就感爆棚了?

最基本的控制移動都完成了,不如下篇博客小基介紹一下“打飛機”ლ(╹◡╹ლ)

 

emmm,小基是說如何發射子彈(¬_¬”)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM