前言

更新於 發佈於 閱讀時間約 7 分鐘

前言

這篇文章會講解如何拖曳 3D 物件。我的代碼實現了二個主要的功能就是拖曳和限制拖曳的方式。不廢話直上代碼。

using UnityEngine;

public class Move : MonoBehaviour
{
private Vector3 _offset;
private float _zCoord;

public Type moveType;
public enum Type
{
normal,
XAxis,
YAxis,
ZAxis,
XYPlane,
YZPlane,
ZXPlane
}

private void OnMouseDown()
{
_zCoord = Camera.main.WorldToScreenPoint(transform.position).z;
_offset = transform.position - GetMouseWorldPos();
}
private Vector3 GetMouseWorldPos()
{
Vector3 mousePoint = Input.mousePosition;
mousePoint.z = _zCoord;
return Camera.main.ScreenToWorldPoint(mousePoint);
}
private void OnMouseDrag()
{
Vector3 newPos = new Vector3(0, 0, 0);
switch (moveType)
{
case Type.normal:
newPos = GetMouseWorldPos() + _offset;
break;
case Type.XAxis:
newPos.x = GetMouseWorldPos().x + _offset.x;
newPos.y = transform.position.y;
newPos.z = transform.position.z;
break;
case Type.YAxis:
newPos.x = transform.position.x;
newPos.y = GetMouseWorldPos().y + _offset.y;
newPos.z = transform.position.z;
break;
case Type.ZAxis:
newPos.x = transform.position.x;
newPos.y = transform.position.y;
newPos.z = GetMouseWorldPos().z + _offset.z;
break;
case Type.XYPlane:
newPos.x = GetMouseWorldPos().x + _offset.x;
newPos.y = GetMouseWorldPos().y + _offset.y;
newPos.z = transform.position.z;
break;
case Type.YZPlane:
newPos.x = transform.position.x;
newPos.y = GetMouseWorldPos().y + _offset.y;
newPos.z = GetMouseWorldPos().z + _offset.z;
break;
case Type.ZXPlane:
newPos.x = GetMouseWorldPos().x + _offset.x;
newPos.y = transform.position.y;
newPos.z = GetMouseWorldPos().z + _offset.z;
break;
}
transform.position = newPos;
}
}

講解

代碼最核心是以下幾句:

private void OnMouseDown()
{
_zCoord = Camera.main.WorldToScreenPoint(transform.position).z;
_offset = transform.position - GetMouseWorldPos();
}

private Vector3 GetMouseWorldPos()
{
Vector3 mousePoint = Input.mousePosition;
mousePoint.z = _zCoord;
return Camera.main.ScreenToWorldPoint(mousePoint);
}

private void OnMouseDrag()
{
transform.position = GetMouseWorldPos() + _offset;
}

有很人都不了解 GetMouseWorldPos 的部分,為甚麼要這樣寫。Input.mousePosition 是一個二維座標(x, y ),而我們現在要是三維座標(x, y, z),所以要補一個 Z座標。

  • Camera.main.WorldToScreenPoint(Vector3 Position): 將位置從世界空間轉換為螢幕空間。
  • Camera.main.ScreenToWorldPoint(Vector3 Position): 將一個點從螢幕空間轉換為世界空間,其中世界空間被定義為遊戲層次結構最頂端的座標系。

拖曳

為甚麼要給予一個 offset ,而不能直接是滑鼠的座標呢。以下是直接是滑鼠的座標的結果。

raw-image

可以見到點擊方塊時會有一個少少移動,有小小不自然的感覺。

限制方向

其實做法十分之簡單,就是將物件的 X Y Z分別計算。當只可以橫向移動,就改 y軸 的數值,而其他二兩個值 Y Z 就固定,就完成了!!!

留言
avatar-img
留言分享你的想法!
avatar-img
夏葉
0會員
7內容數
這裏分享我遊戲開發的記錄,亦會分享開發的小技巧。
夏葉的其他內容
2024/11/27
緣由 生成一個格子是一件十分之簡單的事,但我不知道為甚麼每一次重新寫的時候,都會忘記如何寫。所以我在這裏記錄一下。 代碼 public float num; public GameObject currentGameObject; void Update() { if(Input.G
2024/11/27
緣由 生成一個格子是一件十分之簡單的事,但我不知道為甚麼每一次重新寫的時候,都會忘記如何寫。所以我在這裏記錄一下。 代碼 public float num; public GameObject currentGameObject; void Update() { if(Input.G
2024/01/19
這篇文章深入探討如何利用 Lerp 來實現物體的移動,並介紹透過 Slerp 來獲得更流暢的移動效果。以簡化移動的實現過程。文章將比較 Update 和 IEnumerator 兩種方案,並指導讀者如何設定速度、加速度及移動時間,提供全面的學習資源以助於更佳理解,尤其是對於遊戲開發者。
Thumbnail
2024/01/19
這篇文章深入探討如何利用 Lerp 來實現物體的移動,並介紹透過 Slerp 來獲得更流暢的移動效果。以簡化移動的實現過程。文章將比較 Update 和 IEnumerator 兩種方案,並指導讀者如何設定速度、加速度及移動時間,提供全面的學習資源以助於更佳理解,尤其是對於遊戲開發者。
Thumbnail
2023/11/26
從個連結中下載這個資料夾 https://github.com/h8man/NavMeshPlus 打開剛下載的資料夾,然後將一個名 NavMeshComponents 的資料夾放入你的 Unity 中。 創建一個 Square,作為平面,新增一個名為 Navigation Modifier 的
Thumbnail
2023/11/26
從個連結中下載這個資料夾 https://github.com/h8man/NavMeshPlus 打開剛下載的資料夾,然後將一個名 NavMeshComponents 的資料夾放入你的 Unity 中。 創建一個 Square,作為平面,新增一個名為 Navigation Modifier 的
Thumbnail
看更多