作者dklassic (DK)
看板GameDesign
标题Re: [请益] Unity想实现轻量化碰撞,发现效率输内建
时间Mon Oct 7 02:31:36 2024
※ 引述《MasterDoggo (狗狗我的朋友)》之铭言:
: 因为游戏内单位挺多的,想说可以不使用collision,做一个轻量化的碰撞功能
: 结果不管怎麽调整,效率都惨输预设collider
: 还有索敌我原本也是想每段时间调用一次Physics.OverlapSphere搜索就好
: 但後来尝试的结果也是不如一个Collider设置IsTrigger省事又有效率
: 像这类尝试优化却徒劳无功的状况是经常发生的吗?XD
: 我对优化没有经验,不太懂算法
: 这算是我第一次尝试优化,板上大大有没有什麽可以建议的呢
: 或者继续调适内建collider就好?
: 这是我尝试做的推开功能,只要OnTriggerEnter范围内就赋予Rb.AddForce:
: https://i.imgur.com/WduPFDU.png
先说两件事:
-无论什麽事情都是测数字才算数,所以我给的建议我没测数字也不确定当参考就好
-这段程式中有太多微妙的写法让统一给改进建议很困难,我会流水帐点过去
总之轻松看过去参考就好:
32 行
看到你用 collidersToPush.Keys 应该代表你用的是 Dictionary?
Dictionary.Keys 的 forloop 遍历速度很慢,要速度的时候不要用他。
实务上这边的资料结构用法很奇怪,因为至少这段程式中你永远都只指派 = true,而在离
开的时候直接用 Dictionary.RemoveKey。
这部分延伸到 62 行就变得很奇怪,因为既然这边有 key 完全等於 true,实际上这个判
断式是冗余的。
建议改 List 或 Array 存就好,毕竟你只在乎有或没有在清单里面?
56 行
既然每个 PushAway 都要做一次时间判定,看起来时间也是全域的,而不是分开物件的,
应该把 56-58 行直接拿到 32 行前比较实际,就连进入 32 行的 forloop 都不用。
同时 Unity 其实会自动帮你修好所以不太需要在意,但这边因为是 FixedUpdate 所以理
论上要用 Time.fixedTime 而不是 Time.time。
补充:其实看起来这边应该写法是本质上错误?
照你原本的写法的话 collidersToPush 永远只会推动第一个物件,剩下物件没机会推到。
60、67 行
距离只要小於 0.7 就推的话,与其再另外 FixedUpdate 中判断距离,从一开始就只搜索
这个距离范围内比较合理。(球、圆形 Collider 设定半径 0.7 或 OverlapSphere 直接
抓 0.7)
65 行
虽然在这边没到很重要,但 Vector3.magnitude 要多开根号。
用 Vector3.sqrMagnitude 不用开根号算起来比较快,量多的时候会影响不小
40 行
与其抓到 Collider 後假设可能会拿不到 Enemy 或 PlayerAlly,直接调整 Layer 确保只
有挂这两个 Layer 的东西会判定到比较实际。
GetComponent 效能开销不低尽量少做。
参考:
https://docs.unity3d.com/2022.3/Documentation/Manual/LayerBasedCollision.html
其他流水效能节省的碰撞判定方式提供参考的话大概这些:
-能假设物体是球或圆的碰撞范围的话只要做距离判定就好,根本不用使用物理系统。甚
至如果物体根本就不在乎高度差的话做 XZ 的距离判定就好,省下一轴的计算。
-考虑你说的是 OverlapSphere,不确定你知不知道有 OverlapSphereNonAlloc,频繁触
发的话建议使用後者。写法稍微不直觉一点点但因为不会每次都生成新的 Collider[],表
示比较不容易触发 GC。不清楚 GC 是什麽的话参考:
https://docs.unity3d.com/6000.0/Documentation/Manual/
performance-garbage-collector.html
网址太长只能断两截......
-判断目标真的很多的时候可以用 Spatial Hash Grid 做先抓大概有哪些有机会碰撞,再
只针对这些物体做精密碰撞判定(不过这 Unity 物理可能本身就有实作不确定)。
参考:
https://youtu.be/sx4IIQL0x7c
然後一些关於最佳化的建议:
-先用乾净好懂的写法,等效能真的有瓶颈再考虑去做这些细致的最佳化,早期就在做这
些最佳化反而干扰後续的开发顺畅度,最後发现效能瓶颈根本不在这里的话得不偿失。尤
其考虑你的写法应该代表你对 Unity 或者程式撰写都还不够熟练,先增加熟悉度再来考虑
绕过引擎功能去做更好就好。
精神上参考:
https://youtu.be/NAVbI1HIzCE
基本上就是「先用方便的方式写,但随时注意留下可以改写成更理想版本的空间」,但只
要还不是真的开发上有瓶颈就不要先过早动工处理。
-测试的时候要注意编辑器很可能会跟实际建出来的游戏测出不同结果,不要太拘泥於编
辑器内测出的效能问题,除非干扰到开发。
例如说我随便网路上查到有人做过相关测试:
https://www.reddit.com/r/Unity3D/comments/eye8yk/comment/fgh1tyn/
测出来编辑器内 Trigger 比较快,但是建出来反而比较慢。
-可以多使用 Profiler.BeginSample 跟 Profiler.EndSample 来标记效能测试范围,能
明确看到每段程式的相对效能需求。要注意这个动作本身会带来额外的效能开销,所以要
注意解读实际意义。
-补充:因为注意到推文中提起关於问 AI 这件事情,要小心问 AI 的时候的诱导性问句
问题(现行 AI 对话机器人相对容易肯定你的说法)。整体来说要自己写出比 Unity 内建
更精省快速的物理计算是可行的,基本上就奠基於不做不必要的计算或假设性简化。
而如果你问对问题的话,AI 确实可以给你正确答案:
https://chatgpt.com/share/67033fbb-8af0-800e-88e3-4a3cbf6bea67
同时老实说不建议不熟悉程式与 Unity 时做这麽细致的程式处理时仰赖 AI,并不是要提
说 AI 不好,AI 给出正确答案的时候确实可以一口气给出很大块的正确的程式,但是前提
是自己要有能力验证这个答案是对的。长远下来反而容易造成程式架构的难以维护,也让
其他人提供协助的难度大幅提升。
老实说我在巴哈就已经看过一次你的求救文,但因为要完整回答才能提供有效帮助,需要
点出的问题太多到回答的成本很高而放弃回覆,看到这篇才觉得不出来写清楚不行。
大概这样提供参考。
--
(开发中)
《自动混乱》https://store.steampowered.com/app/1274830/
带有部分类 Rogue 要素的极简风双摇杆射击游戏。
https://imgur.com/TQLbXfC.gif
(已推出)
《自动混乱:零式》https://store.steampowered.com/app/1423670/
极简风生存射击游戏,着重在 10 分钟一场的极简循环。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 61.230.75.77 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/GameDesign/M.1728239503.A.0E3.html
※ 编辑: dklassic (61.230.75.77 台湾), 10/07/2024 02:33:13
※ 编辑: dklassic (61.230.75.77 台湾), 10/07/2024 02:51:08
※ 编辑: dklassic (61.230.114.74 台湾), 10/07/2024 09:52:07
※ 编辑: dklassic (61.230.114.74 台湾), 10/07/2024 09:58:17
1F:推 cdfq152313: 太佛,给推 10/07 11:40
2F:推 MasterDoggo: 太感激大大回文了,先推晚点再来消化文章 10/07 12:05
3F:推 tzouandy2818: 真的佛 10/07 13:57
4F:推 gino0717: 佛 10/07 15:51
5F:推 louisalflame: 推认真 10/07 20:11
6F:推 NX9999: 感谢!, 10/07 23:15
7F:推 nicetw20xx: 推 10/08 02:13
8F:推 newyellow: 大大真的太佛了!! 10/08 04:13
9F:推 godot: 是DK大大! 10/08 08:51
10F:推 geken: 推一下 10/08 10:21
11F:推 v86861062: 推推 10/09 12:56
12F:推 lukeatlee: 学习到好多 推! 10/09 23:15
13F:推 ILuvCD: 推 10/10 04:30
14F:推 jackyT: PhysX一定有做broadphase 加上oo写法带来的cache miss损 11/10 16:11
15F:→ jackyT: 耗怎麽想都打不赢物理引擎捏 11/10 16:11
16F:推 howtotell: !!! 11/23 15:33