1. 程式人生 > >Unity 遊戲框架搭建 2019 (十六、十七) localPosition 簡化與Transform 重置

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

在上一篇我們收集了一個 螢幕解析度檢測的一個小工具。今天呢再往下接著探索。 ### 問題 我們今天在接著探索。不管是寫 UI 還是寫 GamePlay,多多少少都需要操作 Transform。 而在筆者剛接觸 Unity 的時候有一個非常不習慣的地方。就是對 transform 的位置、角度、縮放進行賦值。 比如,如果僅僅是對 transform.localPosition.x 進行賦值。 程式碼要這樣寫。 ```cs var localPosition = transform.localPosition; localPosition.x = 5.0f; transform.localPosition = localPosition; ``` 或者這樣寫 ```cs transform.localPosition = new Vector3(5.0f,transform.localPosition.y,transform.localPosition.z) ``` 原因是因為 Vector3 是 struct 型別的。我們可以把它理解成值型別,在接收 Vector3 物件的時候是值的拷貝,而不是引用的賦值。這個是 C# 的一點語法細節,如果不明白的童鞋,建議搜尋一下。 而在 Quick-Cocos2dx 中只需要一行程式碼就夠了。 ```lua self:setPositionX(5) ``` 注意:這是 Lua 程式碼。 而筆者呢,在接觸 Unity 之前,從學校開始算起就做了 2 年 Cocos2dx,自然很難改掉這個習慣。由於原理很簡單就索性自己寫一個。 程式碼如下: ```lua #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](http://file.liangxiegame.com/eba64ab4-36bf-4491-ae2c-7372b10b4dd7.png) 結果是正確的。 ### 支援 Y 和 Z 除了對 transform 支援 X 之外,我們還要支援 Y 和 Z。因為他們同樣使用很頻繁。 程式碼如下: ```cs 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. 邏輯全部實現 第一種好處就是程式碼能夠複用,但是每次進行一次呼叫,其實是一次值型別的複製操作。所以從效能的角度來講不推薦。 第二種的好處就是效能相對更好一點,但是程式碼量會增多。 綜合考慮,選擇第二種。 程式碼如下: ```cs 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; } ``` 程式碼沒啥難點。 全部程式碼如下: ```cs #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 的位置、旋轉、縮放值進行重置。 程式碼如下: ```cs transform.localPosition = Vector3.zero; transform.localScale = Vector3.one; transform.localRotation = Quaternion.identity; ``` 程式碼大家應該經常會寫到。 我們提取後的方法如下: ```cs #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); } /// /// 重置操作 /// /// Trans. public static void Identity(Transform transform) { transform.localPosition = Vector3.zero; transform.localScale = Vector3.one; transform.localRotation = Quaternion.identity; } } } ``` 程式碼的執行結果是正確的。 那麼有人會問 Identity 是什麼意思呢?Identity 其實是一個矩陣的型別,對角線全部是 1 而其他的部分全部是 0,如下圖所示。 ![006tNc79gy1fzdi20inapj302b03lgle.jpg](http://file.liangxiegame.com/cc202d0a-3bcd-4892-8080-799d0cf783d3.png) 實際上 Transform 本質是一個 4x4 的矩陣,這個矩陣可以記錄矩陣的位置、旋轉和縮放值。而 Identity 矩陣對應的 Transform 就是位置為 0、縮放為 1、Rotation 值為 Quaternion.identity 這樣的矩陣。 這裡不太理解的同學不要緊,重點還是以上程式碼中的 Identity 方法的實現。 OK,到這裡,我們又可以進行一次匯出了。 到今天為止,我們收集了十一個示例了。收穫滿滿,大家應該收集了更多的示例了吧? 今天的內容就這些。 轉載請註明地址:涼鞋的筆記:[liangxiegame.com](http://liangxiegame.com) ## 更多內容 * QFramework 地址:[https://github.com/liangxiegame/QFramework](https://github.com/liangxiegame/QFramework) * QQ 交流群:[623597263](http://shang.qq.com/wpa/qunwpa?idkey=706b8eef0fff3fe4be9ce27c8702ad7d8cc1bceabe3b7c0430ec9559b3a9ce66) * **Unity 進階小班**: * 主要訓練內容: * 框架搭建訓練(第一年) * 跟著案例學 Shader(第一年) * 副業的孵化(第二年、第三年) * 權益、授課形式等具體詳情請檢視[《小班產品手冊》](https://liangxiegame.com/master/intro):https://liangxiegame.com/master/intro * 關注公眾號:liangxiegame 獲取第一時間更新通知及更多的免費內容。 ![](http://file.liangxiegame.com/38eccb55-40b2-4845-93d6-f5fb50ff94