码迷,mamicode.com
首页 > 其他好文 > 详细

刨根问底U3D---Vector3 你到底是蔬菜呢还是水果呢?

时间:2015-04-09 23:17:05      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

事情的起因还是因为一段代码,因为在做一个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;
}

代码逻辑很简单,特殊的地方就是后面传入的Vector3,因为函数会被经常调用 所以不想每次都New出来一个新的Vector3. OK 运行..

Warning CS0472: The result of comparing value type `UnityEngine.Vector3‘ with null is `false‘
Unreachable code detected

WTF?! 哪里错了? Vector3 居然不能和null 判等? 嘿经过我一通测试 果真发现一些问题

来看如下的代码

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 类型然后传入函数内部, 然后在Log出来 看看是否有发生改变。 Ok 运行

Log结果 500,

说明没有发生任何改变。 也就是说 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 发生改变. 对于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 一样

之前有很多类似的地方都是想节约内存不每次进行new操作,于是类中做了一个引用,然后函数时候将引用传过去。

Vector3 inputV3 = new Vector3 ();
inputV3 =SetV3ValueWithRandom (inputV3)

现在看来,其实一点都没有省...

这个也解释了 为什么再给 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里面 循环去new 10w个 Vector3, CPU和内存都没有任何的波动.

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出来 应该怎么做?

直接在函数的参数中改为ref即可, 感觉ref是C# 中很变态的东西 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后面加一个问号 将其转变为Nullable Type 然后就可以用HasValue判断是否有值 然后用 xxx.Value获得这个值了

 

OK 继续搞游戏去了..

 

Best

Eran 

刨根问底U3D---Vector3 你到底是蔬菜呢还是水果呢?

标签:

原文地址:http://www.cnblogs.com/eran/p/4412254.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!