2015年2月12日 星期四

【Unity】滑鼠點擊地板的人物移動

延伸:使用導航網格(NavMesh)實踐滑鼠點擊地板的人物移動

這次來寫透過滑鼠點擊的人物移動,在世紀帝國或星海爭霸等等的戰略遊戲,是常見移動人物的方式,或是英雄聯盟、dota等的多人線上合作遊戲也多是採用這種操控,以下是簡略的圖片描述。
MoveByMouseClick
google圖片搜尋
條列式的敘述一下要做什麼:
1. 玩家透過滑鼠點擊地板的動作將人物移動到點擊的位置。
2. 在移動過程中播放角色的移動動畫。
3. 以及將角色旋轉至面向點擊位置。

這裡就針對人物移動和角色旋轉來做說明,至於角色模型和動畫等等的步驟參考這裡就不多細談,然後這次完成的結果點這裡

首先做好人物和動畫的前置步驟後,新增作為滑鼠點擊用的地板,在這裡使用3D物件Cube作為地板物件,再作大小和位置的調整並新增Tag命名為floor,接著在地板物件物件上新增Box Collider
MoveByMouseClick

接著在攝影機(Main Camera)上新增移動控制用的腳本(MouseClickMove.cs):
using UnityEngine;
using System.Collections;

public class MouseClickMove : MonoBehaviour {
 
    public GameObject model;
    private bool moveState = false;
    private Vector3 target = new Vector3();
    public float speed = 1;

    void Update () {
        Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);////(1)
        RaycastHit hit;
        if (Physics.Raycast (ray, out hit)){////(2)
            if (Input.GetMouseButtonDown (0) && hit.transform.gameObject.tag == "floor"){
                moveState = true;////(3)
                target = new Vector3 (hit.point.x, hit.point.y, hit.point.z);
            }
        }
        float step = speed * Time.deltaTime;////(4)
        ////(7)
        if(moveState){////(5)
            if(Vector3.Distance(model.transform.position,target)<0.1f){
                moveState = false;
            }
            model.transform.position = Vector3.MoveTowards(model.transform.position,target,step);////(6)
        }
    }
}
在人物移動分成兩個部分,第一部分是滑鼠點擊的位置投射到地板,
(1)使用Unity內Ray變數將Camera位置到滑鼠位置轉換成一條3D射線,
(2)將射線投到物件上,這裡使用物件的Tag名稱以及是否按下滑鼠左鍵作為判斷,
(3)若上述條件成立則儲存移動目的點的位置至變數target,並且將移動狀態的布林變數moveState設為true,

接著來到人物移動,
(4) 移動速度使用Time.deltaTime,以避免不同效能的電腦移動速度不一樣,
(5)判斷moveState,當成立時才做移動的動作,並且在模型與目標點小於一定範圍時將 moveState設為false,
(6)移動時使用Vector3.MoveTowards,將模型(model)移動到目標點(target)上。

做完移動後會發現到人物模型雖然會移動了,但卻不會"朝著"目標點的方向移動,所以下一步要處理旋轉的問題,在做完目標點的存取後在(7)的地方加入下列程式碼:
Vector3 targetDir = target - model.transform.position;
Vector3 newDir = Vector3.RotateTowards(model.transform.forward, targetDir, step*10, 0.0F);
model.transform.rotation = Quaternion.LookRotation(newDir);
計算出模型到目標點的向量,使用Vector3.RotateTowards算出每次Update時需要旋轉多少度,存到newDir變數內,最後透過Quaternion.LookRotation實際去旋轉就完成了。

以下是實際運行起來的結果圖,把動畫切換、移動旋轉再加上點擊位置提示後可以做出的結果,執行檔點這裡
MoveByMouseClick

以下是這次的素材,謝謝!!
時雨改二2.0&夕立改二1.0
 by ブラスターB
https://bowlroll.net/file/32178
結月ゆかりVer3.5
 by お宮
https://bowlroll.net/file/6518
Click Effect
http://piposozai.blog76.fc2.com/category7-2.html
歩く・走るをちょっと変化させたモーション by ミイサhttps://bowlroll.net/file/38066

在基本的移動大致上就這樣,至於在實作的時候有考量到繞過障礙物和雙擊切換跑步等等的功能,就留到以後再說吧。


9 則留言:

  1. 程式碼 public floor speed = 1;
    那邊 出現錯誤
    找不到型別或命名空間名稱'floor'(您是六using只是詞或組件參考?
    動作基本上都是照著這篇動作的
    不知道錯誤出在哪邊

    回覆刪除
    回覆
    1. 我是使用unity5.2.0的版本 會有差嗎

      刪除
    2. 你好:
      那個地方是我的筆誤,正確是float浮點數,不是floor。
      目前已經更正。

      刪除
    3. 不好意思 再繼續請教
      雖然會移動了 但是我卻沒辦法在移動時撥放動畫

      刪除
    4. 人物動畫的部分沒有在這一篇文章裡,
      http://jerrard-liu.blogspot.tw/2014/11/unity-animator-mecanim-example-scenes.html
      你可以參考這一篇。

      刪除
    5. 因為在程式方面還是生手 自己嘗試過了一些方法
      動畫還是無法和移動同步
      另外自己在設定人物那邊Character Controller加下去
      人物會開始抖動 所以我是用形狀一樣的那個來設定碰撞說

      刪除
    6. 無法同步的情況是?
      是靜止轉換成移動時,不會即時切換嗎?
      可能是動畫轉換設定的問題,點動畫之間的轉換箭頭:
      https://dl.dropboxusercontent.com/u/90403802/set.png

      刪除
  2. 你好 我想問一下,人物雖然會移動了但是卻不會做出移動的動畫有可能是什麼原因呢 ~.~

    回覆刪除
    回覆
    1. 你好
      本文章不包含動畫的製作喔,
      可以找右邊Animator的標籤,看看有沒有你需要的文章。

      刪除

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...