找回密码
 立即注册
查看: 565|回复: 0

Unity的坑?

[复制链接]
发表于 2020-12-12 18:00 | 显示全部楼层 |阅读模式
我们平时总是会抱怨Unity有很多坑,但个人觉得出现这种状况的原因并不完全是Unity的坑太多。主要原因还是Unity对于大部分使用者来说是个黑盒,我们并不完全了解引擎的内部实现和调用过程,这很容易产生一些低效的用法,毕竟引擎是允许你那样去用的。
比如这个关于协程WaitForSeconds的经典问题:
IEnumerator MyMethod()
{
    //do something

    yield return new WaitForSeconds(2);

    //do something
}很显然,每一次调用都会new一个WaitForSeconds对象,产生GC Alloc;通常的优化都会是主动创建一个WaitForSeconds对象,这样就不会在每一次调用MyMethod()时产生GC Alloc了。像这样:
WaitForSeconds waitSecond = new WaitForSeconds(2);
IEnumerator MyMethod()
{
    //do something

    yield return waitSecond;

    //do something
}
OK,这没问题,是完全可行的。
然而有一次有一个客户询问如果这样优化的话,如果调用MyMethod()两次,第二次调用在第一次调用一秒钟之后,那么第二次调用会等待多久呢?这本质上是在问yield return 的对象有没有被Unity native层所引用;
    如果有被引用的话,那第二次调用应该只会等待一秒
    如果没有被引用的话,那不管调用时机是怎么样的MyMethod()都会等待2秒钟

根据使用经验或者测试,我们能猜到可能是第二种情况,也就是没有被引用。好,这个问题先放放,我们先来看另一个问题:
private IEnumerator MyLoad(string path)
{
    WWW www = new WWW(path);
    yield return www;

    if (www.isDone)
    {
        // do something
    }
}
问题来了,这里的www对象会被native层引用吗?
显然是会的,不然www.isDone是谁修改的?这么看来yield return的对象是否被引用并不能一概而论。
事实上WaitForSeconds对象确实并没有被引用,它在native层做了特殊处理,可以把它看成是向coroutine发送的一个消息,而native层针对WaitForSeconds消息生成了一个内部结构并保存在列表里。
因此,WaitForSeconds的写法都基于我们是否足够了解Unity的内部细节,而它所谓的优化在了解内部细节的情况下是一种很自然的写法。要回避掉这种坑需要我们对Unity内部有更好的理解。以后我将会不时为大家带来一些内部剖析,希望可以使大家更好的使用Unity。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 11:30 , Processed in 0.128917 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表