iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Software Development

Unity Trick 30 - 提升遊戲開發效率和質感的30個技巧系列 第 2

Unity Trick 2 - 快速轉換坐標系統的方法

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20240814/20119470lIkDz258PX.png

Unity 提供了多種不同的座標系統
每個座標有自己的計算方法
彼此之間也可以互相轉換
但是剛接觸時會很容易混淆彼此之間的關係。


下面介紹 Unity 中常見的幾種座標系統:

1. 世界座標(World Coordinates):

世界座標是整個場景的全局參考系統
所有物體的位置都是相對於這個全局坐標來定義的。

一般來說這裡的1 Unit 代表現實物理世界的1m

這個系統的原點是 (0, 0, 0)

三個軸分別是 X、Y 和 Z 軸
X 軸通常表示左右
Y 軸表示上下
Z 軸表示前後

注意美術的模型默認面相是+Z座標。

2.本地座標(Local Coordinates):

https://ithelp.ithome.com.tw/upload/images/20240814/20119470ZrlyOXRKJs.png

本地座標是把物體放物件層級下後的坐標。
物體的本地坐標會隨著父物體的旋轉和平移而改變。

3.螢幕座標(Screen Coordinates):

https://ithelp.ithome.com.tw/upload/images/20240814/20119470gEKms3KJcL.png

螢幕座標系是 2D 螢幕的位置
通常用於 UI 元素或 2D 遊戲中。
這個系統的原點通常在螢幕的中心。

在Canvas UI中
座標以Rect Transform表示

4.攝影機座標(Viewport Coordinates):

攝影機座標是相對於攝像機的座標。
這個系統的原點在攝像機的左下角,範圍通常是從 (0, 0) 到 (1, 1)。
攝影機座標常用於將 3D 空間中的物體轉換到 2D 螢幕空間。

- 透視座標(Perpective Coordinates):

正交座標系主要用於正交攝像機。
這種攝像機不會考慮透視效果,所有物體看起來的大小與距離攝像機的遠近無關。
這個系統適用於 2D 遊戲和一些特定的 3D 場景。
這些座標系統在 Unity 開發中各有用途,理解它們之間的轉換和使用方式是開發過程中的重要一環。

- 正交座標(Orthographic Coordinates):

正交座標系主要用於正交攝像機。
這種攝像機不會考慮透視效果,所有物體看起來的大小與距離攝像機的遠近無關。
這個系統適用於 2D 遊戲和一些特定的 3D 場景。
這些座標系統在 Unity 開發中各有用途,理解它們之間的轉換和使用方式是開發過程中的重要一環。


在Unity中可以透過上放的工具欄切換座標:
https://ithelp.ithome.com.tw/upload/images/20240814/201194707EBcqIa1l9.png

在 Unity 中,不同座標系之間的轉換是非常常見的操作。Unity 提供了多種方法來進行這些轉換,以下是一些常用的轉換方法:

  1. 世界座標系和本地座標系之間的轉換

    • Transform.TransformPoint(Vector3 localPosition):將本地座標轉換為世界座標。
    • Transform.InverseTransformPoint(Vector3 worldPosition):將世界座標轉換為本地座標。
    • 例如:
      Vector3 localPos = new Vector3(1, 2, 3);
      Vector3 worldPos = transform.TransformPoint(localPos);
      Vector3 backToLocalPos = transform.InverseTransformPoint(worldPos);
      
  2. 世界座標系和螢幕座標系之間的轉換

    • Camera.WorldToScreenPoint(Vector3 worldPosition):將世界座標轉換為螢幕座標。
    • Camera.ScreenToWorldPoint(Vector3 screenPosition):將螢幕座標轉換為世界座標。
    • 例如:
      Vector3 worldPos = new Vector3(1, 2, 3);
      Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
      Vector3 backToWorldPos = Camera.main.ScreenToWorldPoint(screenPos);
      
  3. 世界座標系和視口座標系之間的轉換

    • Camera.WorldToViewportPoint(Vector3 worldPosition):將世界座標轉換為視口座標。
    • Camera.ViewportToWorldPoint(Vector3 viewportPosition):將視口座標轉換為世界座標。
    • 例如:
      Vector3 worldPos = new Vector3(1, 2, 3);
      Vector3 viewportPos = Camera.main.WorldToViewportPoint(worldPos);
      Vector3 backToWorldPos = Camera.main.ViewportToWorldPoint(viewportPos);
      
  4. 螢幕座標系和視口座標系之間的轉換

    • Camera.ScreenToViewportPoint(Vector3 screenPosition):將螢幕座標轉換為視口座標。
    • Camera.ViewportToScreenPoint(Vector3 viewportPosition):將視口座標轉換為螢幕座標。
    • 例如:
      Vector3 screenPos = new Vector3(100, 200, 0);
      Vector3 viewportPos = Camera.main.ScreenToViewportPoint(screenPos);
      Vector3 backToScreenPos = Camera.main.ViewportToScreenPoint(viewportPos);
      

這些方法可以幫助你在不同的座標系之間進行轉換,從而更靈活地控制和操作遊戲物體的位置和顯示。了解這些轉換方法對於處理 3D 空間中的物體、UI 元素以及攝像機的操作非常重要。


實際應用:

  • 製作一個可以跟著3D物體移動的UI代碼

https://ithelp.ithome.com.tw/upload/images/20240814/201194704R4y417R4o.png

public class FollowObjOnUI : MonoBehaviour
{
	public Camera mainCamera; // 主攝像機
	public RectTransform uiElement; // 要在Canvas上顯示的UI元素
	public Transform targetObject; // 3D物體

	public bool followX = true;
	public bool followY = true;
	public Vector2 offset = Vector2.zero; // 偏移量

	void Update()

	{

		// 獲取3D物體的世界坐標
		Vector3 worldPosition = targetObject.position;

		// 將世界坐標轉換為屏幕坐標
		Vector3 screenPosition = mainCamera.WorldToScreenPoint(worldPosition);

		// 檢查物體是否在屏幕視野內
		if (screenPosition.z > 0)
		{
			// 計算UI元素的新位置
			Vector3 newPosition = uiElement.position;
			if (followX)
			{
				newPosition.x = screenPosition.x + offset.x;
			}
			if (followY)
			{
				newPosition.y = screenPosition.y + offset.y;
			}
			uiElement.position = newPosition;

			// 確保UI元素是可見的
			if (!uiElement.gameObject.activeSelf)
			{
				uiElement.gameObject.SetActive(true);
			}
		}
		else
		{
			// 如果物體不在屏幕視野內,可以隱藏或處理其他邏輯
			if (uiElement.gameObject.activeSelf)
			{
				uiElement.gameObject.SetActive(false);
			}
		}
	}
}

上一篇
Unity Trick 1 - 提升編輯器開發效率的4個插件
下一篇
Unity Trick 3 - 了解Unity代碼的生命週期
系列文
Unity Trick 30 - 提升遊戲開發效率和質感的30個技巧9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言