查看: 109|回复: 11

为什么在Unity中要尽量避免使用静态变量?

[复制链接]
发表于 2021-5-4 11:03 | 显示全部楼层 |阅读模式
为什么在Unity中要尽量避免使用静态变量?
发表于 2021-5-4 11:11 | 显示全部楼层
先问是不是,再问为什么。
并非要尽量避免使用,而是要知道什么时候适合用,什么时候不适合用
静态变量适合存储一些全局都用得到的公共数据。由于静态的变量不会随对象的回收而释放内存,若是大量滥用则会使内存空间被挤占,代码结构混乱复杂,难于维护等问题。但遇到需要的时候,该用还是得用。
这个问题不局限于静态变量,每一种语法或者是数据结构、代码结构之类的,都有其适合使用的情况。一个好的程序员要做的就是理解其原理,找到这个适合使用的环境。
发表于 2021-5-4 11:15 | 显示全部楼层
“不要用静态变量”这句话本身不用太当真,关键是理解使用静态变量后,该变量的生命期是否和你想要的一致。
先退一步说。在Unity中,由于总是可以用各种方法找到一个对象,所以静态变量想不用,总是可以不用。比如你在根节点创建一个名为GameMode的GameObject,那么想用静态变量的地方,都可以改成非静态的扔到GameMode里面。访问的时候先找到唯一的那个GameObject对象再访问变量,用起来和静态变量区别不大。


再说关键的“对象生命周期”的问题,静态变量可以用类名直接访问,感觉写起来很方便,比如如果游戏客户端只有唯一一个玩家对象,类型为class Player,那么Player的血量就可以设计成直接用:
Player.Hp 来访问。
这样写很多时候没问题,但是严格来说,必须注意:
Player.Hp在什么时候开始可用,什么时候失效?
由于Player对象肯定是在某个时刻创建,某个时刻销毁的(最晚是在游戏结束时销毁)。那么在Player创建之前、结束之后,Player.Hp是不可访问的,不应该被访问。
这就是带来一个隐患:作为静态变量,Player.Hp可以随时访问,大不了读出来是0,但是原则上来讲,Player对象没有创建好的时候,Hp是不存在的。


游戏中的绝大部分物体都有这个问题,因为基本上,场景中所有对象都有着出生、死亡的时刻,包括各种管理器对象,用static静态变量,则它的语法与事实会存在出入。(因为static静态变量是绑定在类上,从逻辑上看,类比任何对象出现都早,结束都晚。哪怕一个对象都没有的时候,也已经有类了。)
这个问题在什么时候变得明显不对呢?就是不同类型的对象之间有相互依赖的时候。
比如UI界面用到了任务管理器对象,Player用到了UI对象,任务管理器又在某些时候会访问Player的数据。这时候用静态变量很难理清哪个对象在什么时候能用、什么时候不能用。虽然这些对象大部分时候都不销毁,但未来项目变化的时候,东一个西一个的静态变量,就可能变成滋生BUG的温床。


有些回答提到了单例。
单例这种模式我也很不喜欢用,但是单例有一个非常大的好处:它把以上讨论的,访问某种唯一对象的模式规范化了。规范化就意味着统一、好查。如果搞错了生命期,发现某个管理器找不到了,你就可以到创建、销毁的地方去查它,很容易就发现设计上的漏洞。
以上解释写了一大堆,感觉似乎说的都是静态变量的缺点。但话说回来,只要你能把对象生命期想清楚,想怎么写都是可以接受的。
发表于 2021-5-4 11:21 | 显示全部楼层
静态变量的缺点是不能控制生命周期,如果有一堆静态变量,他们之间存在相互依赖的关系,那么你必须保证正确处理他们初始化的顺序,项目如果很大的话,每个人都自己使用自己的静态变量,最后很可能会存在数据污染问题。静态变量本身使用是没有问题的,只是用的太多容易出 bug,说到底还是使用者的问题。
发表于 2021-5-4 11:28 | 显示全部楼层
应该用。多用。别搞单件。
发表于 2021-5-4 11:34 | 显示全部楼层
看你项目类型吧,我用unity写应用基本上是静态变量,如果是写游戏你用那么多静态变量,你忙的过来吗。
发表于 2021-5-4 11:35 | 显示全部楼层
多次查询的时候使用,会省很多效率
不然需要写很多没用的接口,转来转去非常容易出错。


该挂起来,所有地方都能查询到的,比如主角 ,主摄像机 ,游戏模式类,游戏操作遥感 之类的
发表于 2021-5-4 11:36 | 显示全部楼层
静态变量不会被释放,项目大了可能会有变量状态没清干净。还有可能引起引用泄漏。用单例,我直接new一个新的就好了。简单多了
发表于 2021-5-4 11:36 | 显示全部楼层
以下特指Unity里的C#
静态变量意味着不会被自动回收,需要手动置空,如果不置空就意味着持续占用内存。
而用Unity做项目,例如游戏项目,对内存的掌控是一件很重要的事情。
尤其是Unity中,由于存在MonoBehaviour和GameObject等处于语法之上逻辑概念。
新手在不熟悉机制的情况下,贸然使用静态变量来管理这些东西,容易发生不在自己掌控之中的内存泄露。
当然了,在熟悉这一些机制的前提下,可以使用部分静态变量来使整个架构更易于使用。
如果不熟悉,则尽量避免使用之。
发表于 2021-5-4 11:36 | 显示全部楼层
不是说要避免使用静态变量, 而是说, 需要你在适合的地方使用它。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则