要做這個效果可以有很多種方法,這邊使用簡單的兩種方法,一種是使用Vector3.SmoothDamp()讓物體一直朝著滑鼠座標移動,一種是使用Rigidbody的AddForce給物體施加一個方向的力道。
第一個方式,讓物件朝著滑鼠座標移動,這邊使用SmoothDamp的原因在於使用這個方法內建的功能來限制最高速度。當然也可以用Lerp或MoveTowards等等看你想要的移動方,這邊就簡單計算滑鼠座標換算成世界座標,然後讓物體往該點移動即可。
(關於攝影機的Z軸參考使用ScreenToWorldPoint的時候,回傳值是camera的position而不是目標點座標的問題)
public Vector3 v; public float maxSpeed = 5.0f; void TowardTarget() { Vector3 targetPos = Camera.main.ScreenToWorldPoint (new Vector3(prePos.x, prePos.y, 10f)); //這邊假設你Camera的Z軸在-10而物體的Z軸在0 transform.position = Vector3.SmoothDamp (transform.position, targetPos, ref v, speedDelta, maxSpeed); }
第二個方式,使用Rigidbody的AddForce,當滑鼠或指標移動的時候,計算當下的移動向量跟速度,然後給物體加上這個方向的力讓物體朝著這個方向移動,這個跟朝著滑鼠座標移動的方式稍有不同,是朝著施力方向移動,並且拖曳滑鼠的速度越快施力越大,移動也就越快。
private Vector3 prePos; void ForceCalculate() { Vector3 curPos = Input.mousePosition; //記錄當前滑鼠座標 Vector3 dir = curPos - prePos; //跟前一個frame的座標來取得向量 float dist = dir.magnitude; //移動的距離 float v = dist / Time.deltaTime; //使用距離跟時間來計算速度 this.rigidbody.AddForce (dir.normalized * v * Time.deltaTime * speedDelta); //給物體施力 prePos = curPos; }
--
實作測試:點選按鈕切換不同的移動方式,滑鼠點選場景中球球然後拖曳即可。
物體須加上Rigidbody,因為使用2D的設定所以取消Gravity避免一開始就往下墜落。
--
拖曳移動的Code
public class MyDrag : MonoBehaviour { public enum DragMethod { Force, SmoothDamp } public DragMethod method = DragMethod.Force; //切換用 public float speedDelta = 1.0f; public float decelerate = 1.0f; private bool startDrag; private Vector3 prePos; void Start() { prePos = Camera.main.WorldToScreenPoint(transform.position); this.rigidbody.drag = decelerate; //使用這個來讓物體逐漸停止,也可以在Rigidbody中設定drag值,這樣就可以移除這行 } void Update () { switch (method) { case DragMethod.Force: if(Input.GetKeyUp(KeyCode.Mouse0)) startDrag = false; if(startDrag) ForceCalculate(); //如果拖曳中,就一直給物體施加滑鼠造成的力 break; case DragMethod.SmoothDamp: if(Input.GetKeyUp(KeyCode.Mouse0)) { if(startDrag) //如果放開滑鼠,就停止物體追隨滑鼠的效果,並讓物體朝著最後移動的向量移動 { this.rigidbody.velocity = v; startDrag = false; v = Vector3.zero; } } if(startDrag) { prePos = Input.mousePosition; TowardTarget (); //如果拖曳中,就讓物體往滑鼠的座標移動 } break; } } void OnMouseDown() //當滑鼠點下物件的時候重設一些數值 { switch(method) { case DragMethod.Force: prePos = Input.mousePosition; break; case DragMethod.SmoothDamp: prePos = Camera.main.WorldToScreenPoint (transform.position); break; } startDrag = true; } //施力的方式移動 void ForceCalculate() { Vector3 curPos = Input.mousePosition; Vector3 dir = curPos - prePos; float dist = dir.magnitude; float v = dist / Time.deltaTime; this.rigidbody.AddForce (dir.normalized * v * Time.deltaTime * speedDelta); prePos = curPos; } //朝著滑鼠的方式移動 public Vector3 v; public float maxSpeed = 5.0f; void TowardTarget() { Vector3 targetPos = Camera.main.ScreenToWorldPoint (new Vector3(prePos.x, prePos.y, 10f)); //Assume your camera's z is -10 and cube's z is 0 transform.position = Vector3.SmoothDamp (transform.position, targetPos, ref v, speedDelta, maxSpeed); } }
4 comments:
您好:想請問一下,在函數中有一個this.rigidbody.drag的部分,我輸入後程式表示錯誤,請問是什麼原因呢?謝謝:)
在Po這篇的時候使用的Unity是4.6版本的,進入5的版本後有修改這部分,沒辦法直接使用rigidbody,所以必須要修改這部分。
你可以把所有this.rigidbody改為 (Rigidbody)GetComponent(typeof(Rigidbody))
或者一開始宣告的field多放一個
Rigidbody r;
然後在Start()裡面起始化 r = (Rigidbody)GetComponent(typeof(Rigidbody));
之後把所有this.rigidbody改為r來用這樣也可以
不好意思我想請問一下 他為什麼會說“speedDelta'這個名字並不在目前的情況下存在
Component裡面我有寫這個變數,不知道你的問題在哪
Post a Comment