事情的起因還是因為一段代碼,因為在做一個2D TileBase的游戲 所以需要有一個簡單的 Tile坐標到世界坐標的變換
public static Vector3 GetTileWorldPosByTileIndex(int _tileIndexX, int _tileIndexY , Vector3 _result){ if(_result == null) { _result = new Vector3(); } _result.x = TileConst.TILE_WIDTH * _tileIndexX; _result.y = TileConst.TILE_HEIGHT * _tileIndexY; _result.z = 0; return _result;}代碼邏輯很簡單,特殊的地方就是后面?zhèn)魅氲腣ector3,因為函數(shù)會被經(jīng)常調用 所以不想每次都New出來一個新的Vector3. OK 運行..
Warning CS0472: The result of comparing value type `UnityEngine.Vector3' with null is `false'Unreachable code detected
WTF?! 哪里錯了? Vector3 居然不能和null 判等? 嘿經(jīng)過我一通測試 果真發(fā)現(xiàn)一些問題
來看如下的代碼
public class Test01 : MonoBehaviour{ void Start () { int inputInt = 500; int outputInt = SetIntWithRandom (inputInt); Debug.Log (inputInt); } public int SetIntWithRandom(int _input) { _input = Random.Range(-300,300); return _input; }}這段應該很簡單,弄出來一個int 類型然后傳入函數(shù)內(nèi)部, 然后在Log出來 看看是否有發(fā)生改變。 Ok 運行
Log結果 500,
說明沒有發(fā)生任何改變。 也就是說 int 類型的變量是 傳值不是傳址的
再換下一組
public class Test01 : MonoBehaviour{ void Start () { int[] inputIntArray = new int[2]; inputIntArray [0] = 500; int[] outputIntArray = SetIntArrayWithRandom (inputIntArray); Debug.Log (inputIntArray [0]); } public int[] SetIntArrayWithRandom(int[] _inputIntArray) { _inputIntArray[0] = Random.Range(-300,300); return _inputIntArray; }}Log結果 -89 發(fā)生改變. 對于Array來說 是傳址不是傳值的.
Ok 來看 Vector3
public class Test01 : MonoBehaviour{ void Start () { Vector3 inputV3 = new Vector3 (); inputV3.x = 500; Vector3 outputV3 =SetV3ValueWithRandom (inputV3); Debug.Log (inputV3.x); } public Vector3 SetV3ValueWithRandom (Vector3 _result) { _result.x = Random.Range (-300, 300); return _result; }}Log結果 500.
也就是說呢, 雖然Vector3 初始化時候 需要用New 操作符, 但是Vector3 卻是一個基礎類型 和 float,int 一樣
之前有很多類似的地方都是想節(jié)約內(nèi)存不每次進行new操作,于是類中做了一個引用,然后函數(shù)時候將引用傳過去。
Vector3 inputV3 = new Vector3 ();inputV3 =SetV3ValueWithRandom (inputV3)
現(xiàn)在看來,其實一點都沒有省...
這個也解釋了 為什么再給 transfrom的position賦值時候不能
transform.position.x = 100; 這樣去做 會報錯說
Error CS1612: Cannot modify a value type return value of `UnityEngine.Transform.position'. Consider storing the value in a temporary variable (CS1612)
我又做了幾個相關的測試,實在懶得寫了 :) 就把相關結果說一下吧(有興趣可以私聊哈)
1· 每次去New Vector3 對性能開銷大么?
我PRofile了一下, 在一個Update里面 循環(huán)去new 10w個 Vector3, CPU和內(nèi)存都沒有任何的波動.
vod Update(){ Vector3 tmp; for(int i=0 ; i<100000;i++) { Vector3 tmp = new Vector3(); tmp.x = Random.Range (-300, 300); } transform.position = tmp}也就是完全把它當int來看就好了,雖然使用的是New操作符 總感覺 要有很大動靜似的...
vod Update(){ int tmp; for(int i=0 ; i<100000;i++) { tmp = Random.Range (-300, 300); }}2· 雖然開銷很小 但是我還是想類中保留一個引用,然后不用每次去New出來 應該怎么做?
直接在函數(shù)的參數(shù)中改為ref即可, 感覺ref是C# 中很變態(tài)的東西 int啊 float啊什么的 都能ref (之前接觸到得As3,java是不行的 從C++上面繼承來的特性吧 這個應該是)
public static void GetTileWorldPosByTileIndex(int _tileIndexX, int _tileIndexY , ref Vector3 _result){ _result.x = TileConst.TILE_WIDTH * _tileIndexX; _result.y = TileConst.TILE_HEIGHT * _tileIndexY; _result.z = 0;}3· 注意一下 Nullable Type
可以看下這篇文章 http://unitypatterns.com/nullable-types/
兩個問題,一個是說
Vector3 tmp;Debug.Log(tmp.x) // 這里會有結果,結果是0
也就是說 Vector3 在沒有new操作時候 是有默認值的 和 布爾默認值是false, int默認值是0 一個道理
第二個 如果不希望這樣的話 那就要使用 牛逼操作符 問號..
Vector3? tmp;if(tmp.HasValue){ Debug.Log(tmp.Value);}在Vector3后面加一個問號 將其轉變?yōu)镹ullable Type 然后就可以用HasValue判斷是否有值 然后用 xxx.Value獲得這個值了
OK 繼續(xù)搞游戲去了..
Best
Eran
PS: 寫完以后被各種大神教育了一下,Struct問題 呵呵
其實Vector3是一個Struct 所以才有這種特性,如果有興趣可以看下MSDN
https://msdn.microsoft.com/en-us/library/aa288471%28v=vs.71%29.aspx
摘錄一段:
Structs may seem similar to classes, but there are important differences that you should be aware of. First of all, classes are reference types and structs are value types. By using structs, you can create objects that behave like the built-in types and enjoy their benefits as well.
When you call the New Operator on a class, it will be allocated on the heap. However, when you instantiate a struct, it gets created on the stack. This will yield performance gains. Also, you will not be dealing with references to an instance of a struct as you would with classes. You will be working directly with the struct instance. Because of this, when passing a struct to a method, it's passed by value instead of as a reference.
新聞熱點
疑難解答