asp网站安全,全屏网站,网站开发都用什么语言,大数据获客系统1.Avoid retrieving string properties from GameObjects
通常来讲#xff0c;从C#的object中获取string 属性没有额外的内存开销#xff0c;但是从Unity中的Gameobject获取string属性不一样#xff0c;这会产生上一篇讲到的 Native-Managed Bridge#xff08;Native内存和…1.Avoid retrieving string properties from GameObjects
通常来讲从C#的object中获取string 属性没有额外的内存开销但是从Unity中的Gameobject获取string属性不一样这会产生上一篇讲到的 Native-Managed BridgeNative内存和托管内存间的传递
tag和name是GameObject中会产生这种现象的两个属性我们应该尽量少的在运行时调用这两个属性比如用在Editor编程中更合适。但是Tag这个东西太常用也非常有用在运行时经常会用到这会经常带来麻烦举个栗子下边的代码在每次迭代中都会产生额外的内存开销
for (int i 0; i listOfObjects.Count; i)
{ if (listOfObjects[i].tag Player) { // do something with this object }
}
还好Unity提供了 CompareTag(这个方法来用来tag间的比较这个方法避免了Native-Managed Bridg不知道咋避免的没有讲原理
来让我们测试下 通过键盘我们可以控制使用哪个函数来瞅瞅结果 分别运行1000万次可以看到使用.tag方法时会有很多内存分配如果分配过多会进而产生GC。并且.tag方法运行大概消耗2000毫秒而ComparTag方法大概消耗1000毫秒速度也慢于CompareTag方法。所以结论就是不要使用.tag方法。
很不幸的是Unity对于name属性没有提供不消耗内存的方法所以有的时候需要调用name属性去判断时不如考虑考虑用tag来代替。值得一提的是ComparTag方法调用时传入的字符串比如Player并不会产生额外的内存开销因为在初始化时已经分配好这些硬编码的字符串这里这是运行时的引用。
2. Use appropriate data structures
C#在System.Collection中提供了很多不同的数据结构最常用的俩个就是ListT和DictionaryK, V。
如果我们想要做的是遍历数据集那List更合适一些因为List在内存中的分布式连续的因此遍历会更准确更快的命中内存位置。
Dictionary最合适的情况是两个objects相互关联我们更多的是用来查询插入删除等操作。
如果既想要遍历速度快又想增删改查快不好意思没有这种美事儿目前没有这种数据结构书作者的建议是。。。如果有这种硬性需求那就两个一起用一个list一个dict比如一个playerList 一个 playerDict
3.Avoid re-parenting Transforms at runtime
在Unity的早期版本中5.3更早之前Transform的引用在内存中的排布和Dict很像也是随机排布。但是新版本后Unity对于在同一个parent下的所有Transforms内存排布变成了连续的类似动态数组这会给例如物理系统和动画系统等许多系统带来非常大的性能提升因为这加快了Transform的遍历。万事肯定不是完美的想获得速度的提升就会有所牺牲。当我们想给一个GameObject 换个爹parent时新的爹parent必须从自己已预先分配好的内存空间中分出一部分给这个新移过来的Transform并且重新根据depth排序如果这个新爹parent没有足够的空间去适应新来的儿子child那它只好扩展自己的内存buffer这有可能会消耗不好少时间。
当我们 instantiate 一个新的GameObject时要处理的一件事就是给这个GameObject认个爹如果不处理的话默认是null也就是孤儿会直接在Hierarchy的root下存放。Hierarchy 根目录下的所有Transform都需要分配一段内存buffer去存储自己现有的儿子们以及未来还可能新有的但是如果当我们Instantiate后立刻给一个GameObject认个爹就可以避免分配这部分内存buffer因此我们可以 在调用GameObject.Instantiate(时传入parent的Transform而避免分配内存这步。
另一种方法是在我们需要之前就给root Transform提前分配更大的内存buffer从而避免在同一帧里既需要重新给GameObject认爹还需要扩展内存Buffer,这个操作可以通过修改Transform的hierarchyCapacity属性达到如果我们可以提前就预估好有多少个儿子那就可以节省很多的内存分配操作。 4.Consider caching Transform changes
Transform脚本存储了它相对于其parent的数据这意味着如果获取和修改一个Transform脚本的positionrotation或者scale属性都将引起许多额外的矩阵运算类似坐标空间变换。这个object在Hierarchy Window中所处层级越深那就需要计算的越多。
然而这也意味着如果使用localPosionlocalRotation和localScale不会有这部分开销因为这些值已经是直接存储在了Transform上可以直接获得因此能用local属性的时候就尽可能的使用local。
不幸的是世界坐标和本地坐标的变换在很多时候会简化和解决3D的一些问题因此有时候也有必要牺牲一些小性能来解决复杂的3d数学运算问题。
另外一个要注意的就是要尽量避免不断的对Transform脚本的属性进行更改因为每次更改都会调用Unity内部的消息机制Unity需要把更改的消息发送给例如ColliderRigidbodyLightCamera等等以保证物理和渲染系统能知道新的Transform属性从而进行对应的更新。
我们会经常看到在同一帧中对Transform的属性进行了多次的修改这每次修改都会带来内部消息的传递即使是在同一帧里。因此我们应该尽可能减少修改次数比如先用变量缓存在帧的最后再调用比如下边这个例子: