Unity 游戲框架搭建 2019 (十六、十七) localPosition 簡化與Transform 重置


在上一篇我們收集了一個 屏幕分辨率檢測的一個小工具。今天呢再往下接着探索。

問題

我們今天在接着探索。不管是寫 UI 還是寫 GamePlay,多多少少都需要操作 Transform。

而在筆者剛接觸 Unity 的時候有一個非常不習慣的地方。就是對 transform 的位置、角度、縮放進行賦值。

比如,如果僅僅是對 transform.localPosition.x 進行賦值。

代碼要這樣寫。

var localPosition = transform.localPosition;
localPosition.x = 5.0f;
transform.localPosition = localPosition;

或者這樣寫

transform.localPosition = new Vector3(5.0f,transform.localPosition.y,transform.localPosition.z)

原因是因為 Vector3 是 struct 類型的。我們可以把它理解成值類型,在接收 Vector3 對象的時候是值的拷貝,而不是引用的賦值。這個是 C# 的一點語法細節,如果不明白的童鞋,建議搜索一下。

而在 Quick-Cocos2dx 中只需要一行代碼就夠了。

self:setPositionX(5)

注意:這是 Lua 代碼。

而筆者呢,在接觸 Unity 之前,從學校開始算起就做了 2 年 Cocos2dx,自然很難改掉這個習慣。由於原理很簡單就索性自己寫一個。

代碼如下:

#if UNITY_EDITOR
using UnityEditor;
#endif

using UnityEngine;

namespace QFramework
{
	public class TransformLocalPosImprovements
	{
#if UNITY_EDITOR
		[MenuItem("QFramework/10.Transform 賦值優化")]
#endif
		private static void GenerateUnityPackageName()
		{
			var transform = new GameObject("transform").transform;

			SetLocalPosX(transform, 5.0f);
		}

		public static void SetLocalPosX(Transform transform, float x)
		{
			var localPos = transform.localPosition;
			localPos = x;
			transform.localPosition = localPos;
		}
	}
}

代碼很容易理解,由於考慮到一個 方法名的長度,所以將 Position 縮寫成了 Pos。

代碼的執行結果如下圖所示:
006tNc79gy1fzdi1ise58j31aa0e2n06.jpg

結果是正確的。

支持 Y 和 Z

除了對 transform 支持 X 之外,我們還要支持 Y 和 Z。因為他們同樣使用很頻繁。

代碼如下:

		public static void SetLocalPosY(Transform transform, float y)
		{
			var localPos = transform.localPosition;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosZ(Transform transform, float z)
		{
			var localPos = transform.localPosition;
			localPos.z = z;
			transform.localPosition = localPos;
		}

支持 XY、XZ 和YZ

當然還 XY、XZ 和 YZ 也是同樣需要支持的。但是這里呢,其實可以有兩個選擇:

  1. 調用 SetPositionX、SetPositionY 、SetPositionZ
  2. 邏輯全部實現

第一種好處就是代碼能夠復用,但是每次進行一次調用,其實是一次值類型的復制操作。所以從性能的角度來講不推薦。

第二種的好處就是性能相對更好一點,但是代碼量會增多。

綜合考慮,選擇第二種。

代碼如下:

		public static void SetLocalPosXY(Transform transform, float x, float y)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosXZ(Transform transform, float x, float z)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.z = z;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosYZ(Transform transform, float y, float z)
		{
			var localPosition = localPos;
			localPos.y = y;
			localPos.z = z;
			transform.localPosition = localPos;
		}

代碼沒啥難點。

全部代碼如下:

#if UNITY_EDITOR
using UnityEditor;
#endif

using UnityEngine;

namespace QFramework
{
	public class TransformLocalPosImprovements
	{
#if UNITY_EDITOR
		[MenuItem("QFramework/10.Transform 賦值優化")]
#endif
		private static void GenerateUnityPackageName()
		{
			var transform = new GameObject("transform").transform;

			SetLocalPosX(transform, 5.0f);
			SetLocalPosY(transform, 5.0f);
			SetLocalPosZ(transform, 5.0f);
		}

		public static void SetLocalPosX(Transform transform, float x)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosY(Transform transform, float y)
		{
			var localPos = transform.localPosition;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosZ(Transform transform, float z)
		{
			var localPos = transform.localPosition;
			localPos.z = z;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosXY(Transform transform, float x, float y)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.y = y;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosXZ(Transform transform, float x, float z)
		{
			var localPos = transform.localPosition;
			localPos.x = x;
			localPos.z = z;
			transform.localPosition = localPos;
		}
		
		public static void SetLocalPosYZ(Transform transform, float y, float z)
		{
			var localPos = transform.localPosition;
			localPos.y = y;
			localPos.z = z;
			transform.localPosition = localPos;
		}
	}
}

這個呢,是我們的第十個示例。

我們又可以進行導出了。

Transform 重置

今天我們再往下接着探索,我們的 Transform。

我們經常要寫這樣的邏輯,對一個 Transform 的位置、旋轉、縮放值進行重置。

代碼如下:

transform.localPosition = Vector3.zero;
transform.localScale = Vector3.one;
transform.localRotation = Quaternion.identity;

代碼大家應該經常會寫到。

我們提取后的方法如下:

#if UNITY_EDITOR
using UnityEditor;
#endif

using UnityEngine;

namespace QFramework
{
	public class TransformIdentity : MonoBehaviour
	{
		
#if UNITY_EDITOR
		[MenuItem("QFramework/11.Transform 歸一化")]
#endif
		private static void MenuClicked()
		{
			var transform = new GameObject("transform").transform;

			Identity(transform);
		}

		/// <summary>
		/// 重置操作
		/// </summary>
		/// <param name="trans">Trans.</param>
		public static void Identity(Transform transform)
		{
			transform.localPosition = Vector3.zero;
			transform.localScale = Vector3.one;
			transform.localRotation = Quaternion.identity;
		}
	}
}

代碼的執行結果是正確的。

那么有人會問 Identity 是什么意思呢?Identity 其實是一個矩陣的類型,對角線全部是 1 而其他的部分全部是 0,如下圖所示。
006tNc79gy1fzdi20inapj302b03lgle.jpg

實際上 Transform 本質是一個 4x4 的矩陣,這個矩陣可以記錄矩陣的位置、旋轉和縮放值。而 Identity 矩陣對應的 Transform 就是位置為 0、縮放為 1、Rotation 值為 Quaternion.identity 這樣的矩陣。

這里不太理解的同學不要緊,重點還是以上代碼中的 Identity 方法的實現。

OK,到這里,我們又可以進行一次導出了。

到今天為止,我們收集了十一個示例了。收獲滿滿,大家應該收集了更多的示例了吧?

今天的內容就這些。

轉載請注明地址:涼鞋的筆記:liangxiegame.com

更多內容


免責聲明!

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



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