• 中文
  • 关于使用多个Skeleton后Unity效能下降的问题

Related Discussions
...

大家好,最近在专案内使用多个 Skeleton Animation(在背景中無限Loop)
不管是使用 Graphic 或者 是 Animation在runtime中都有严重的效能问题,
目前json及二進位格式都一樣慢
在這兩個地方有嚴重的消耗

SkeletonRenderer.LateUpdate();
SkeletonAnimation.Update();

不太确定该往哪个方向去做调整,有查过一些资料,是json本身要移除不必要的key?还是减少顶点的使用呢?
但是在制作时的规格,参照其他游戏的建议应该是没有问题的才对。
(我是在手机端上做开发)
模型參數

Unity分析器慢的地方

您使用的是最新版本的 Spine 和 Spine-unity 运行时吗?

您可以在此处找到有关性能的一般信息和建议:
zh.esotericsoftware.com/spine-metrics#Performance

您的骨架指标看起来没有太大问题,但应尽可能避免剪辑。 你有多少骷髅同时处于活动状态? 请注意,可以在 Advanced - Update when Invisible 中的 SkeletonAnimation Inspector 中禁用屏幕外骨骼更新。

此外,请务必在实际设备上测试 Release 版本的性能,因为调试版本的性能可能会更差,而分析器会使事情变得更糟。


Are you using the latest versions of Spine and of the spine-unity runtime?

You can find general information and recommendations regarding performance here:
zh.esotericsoftware.com/spine-metrics#Performance

Your skeleton metrics do not look too problematic, although clipping should be avoided where possible. How many skeletons do you have active at once? Note that off-screen skeleton updates can be disabled in the SkeletonAnimation Inspector in Advanced - Update when Invisible.

Also, please be sure to test the performance in a Release build on the actual device, since debug build performance can be much worse, and the profiler will make matters even worse.

感謝回復,我使用的是spine-unity 3.8 2021-07-12
即便我調整了全部的設置也沒太大的提升

Advanced - Update when Invisible

我可能一次需要20-30個骷髏在畫面中進行更新,但骨架指标通常都是如圖所示。
Release上版本效能的確很差!
我能理解為一個骷髏為一組SkeletonAnimation對吧?
我只要場景中放兩個以上,效能就會開始急遽下降,是已知的問題嗎?還是哪裡需要優化?既然我骨架指标正常的話。
目前就是一個動作循環撥放,還是說需要使用 "烘焙"之類的功能嗎?沒看到相關說明
謝謝!

不幸的是,自动翻译不是很清楚。 你的意思是当场景中只有两个 SkeletonAnimation 游戏对象时性能已经很差了吗? 如果是这样,您能否将您有问题的 Spine 项目(或至少是导出的资产)发送给我们? 您可以通过电子邮件将其发送至 contact@esotericsoftware.com,或将其附加到论坛帖子中。


Unfortunately automatic translation is not very clear. Do you mean that performance is already bad when having only two SkeletonAnimation GameObjects in the scene? If so, could you perhaps send us your problematic Spine project (or at least the exported assets)? You can either send it via email to contact@esotericsoftware.com, or attach it to a forum posting.

Harald escreveu

不幸的是,自动翻译不是很清楚。 你的意思是当场景中只有两个 SkeletonAnimation 游戏对象时性能已经很差了吗? 如果是这样,您能否将您有问题的 Spine 项目(或至少是导出的资产)发送给我们? 您可以通过电子邮件将其发送至 contact@esotericsoftware.com,或将其附加到论坛帖子中。


Unfortunately automatic translation is not very clear. Do you mean that performance is already bad when having only two SkeletonAnimation GameObjects in the scene? If so, could you perhaps send us your problematic Spine project (or at least the exported assets)? You can either send it via email to contact@esotericsoftware.com, or attach it to a forum posting.

沒錯!

你的意思是当场景中只有两个 SkeletonAnimation 游戏对象时性能已经很差了吗?

抱歉,由於是公司的專案所以沒辦法將Spine檔提供給你們,但在測試Spine_Example時就能測出此問題,

很明顯的可以看到,複製多個SkeletonGraphics Batches數會增加SkeletonAnimation 同理
請問SkeletonGraphics 是沒辦法進行這樣的操作嗎?一個場景只能有一個SkeletonGraphics 運行?
複數個以上就會造成大量的性能消耗?因為我們專案中需要使用可能2030個SkeletonGraphics同時運行的情況(但資產資源都如附近那樣)是不行的嗎?
謝謝

不幸的是,您的再现视频没有帮助,因为您复制了 SkeletonGraphic (Doi),其中还包含两个子 Text 游戏对象,这导致批次的稳定增加。 如果您尝试使用已删除的子项复制 SkeletonGraphic (Doi),您将看到批次根本没有增加。


Unfortunately your reproduction video is not helpful, because you have duplicated SkeletonGraphic (Doi) which also contains two child Text GameObjects which lead to the steady increase in batches. If you try duplicating SkeletonGraphic (Doi) with deleted children, you will see that batches don't increase at all.

Harald escreveu

不幸的是,您的再现视频没有帮助,因为您复制了 SkeletonGraphic (Doi),其中还包含两个子 Text 游戏对象,这导致批次的稳定增加。 如果您尝试使用已删除的子项复制 SkeletonGraphic (Doi),您将看到批次根本没有增加。


Unfortunately your reproduction video is not helpful, because you have duplicated SkeletonGraphic (Doi) which also contains two child Text GameObjects which lead to the steady increase in batches. If you try duplicating SkeletonGraphic (Doi) with deleted children, you will see that batches don't increase at all.

嗯...所以我應該如何操作才能在場景中同時撥放複數個SkeletonGraphic (Doi) 呢?
我只是想要場景中有 SkeletonGraphic (A) SkeletonGraphic (B)``SkeletonGraphic (C)...(更多)
在可視範圍內執行正常,不lag而已。
复制 SkeletonGraphic (Doi)是不被允許的嗎?

好的,我刪除了下面的兩個子Text(batch的確沒增加了),但FPS還是明顯的下降,這是合理的嗎?所以我沒辦法在一個場景中使用2030個大量以上的 SkeletonGraphic?

我并不是说不允许复制 SkeletonGraphic 对象。 我的意思是,当您复制SkeletonGraphic (Doi) 游戏对象时,增加批次计数的问题来自于 Doi 游戏对象的子代。 正如您所说,当只复制没有孩子的 Doi 游戏对象时,批次计数不会增加。

根据您的目标 FPS 和每个骨架的复杂性,数量是有限的,是的。 但是,您必须使用发布版本在目标设备上进行测量。

当我们按照此问题单中的跟踪实现并行化时,性能将会提高:
https://github.com/EsotericSoftware/spine-runtimes/issues/1348
请注意,我们必须在论坛上回答的问题越少,我们就越早实现此功能(这是第二张票)。


I did not mean that copying a SkeletonGraphic object is not allowed. I meant that when you copy the SkeletonGraphic (Doi) GameObject, the problem of increased batch count comes from the children of the Doi GameObjects. As you also said, the batch count does not increase when only copying the Doi GameObject without the children.

Depending on your target FPS and complexity of each Skeleton, the number is limited, yes. You have to measure on the target device using a release build however.

Performance will improve when we get to implement parallelization as tracked under this issue ticket:
https://github.com/EsotericSoftware/spine-runtimes/issues/1348
Please note that the fewer questions we have to answer on the forum, the earlier we get to implement this feature (which is the second issue ticket in line).

不幸的是,我進行發布版本時的情況一樣,fps掉到只剩下8(Release版本Android),儘管我場景中只使用了20個左右相同的SkeletonAnimation。
這令人難以接受,有看到針對開發時的解決情況,是把Spine.cs相關的打包成dll檔案對吧?但這實際上不能解決發布版本時卡頓的問題。


我理解了,查了一下文章發現在spine官方提供的代码中,没有提供动画文件的缓存处理,当同时加载多个动画的时候会卡帧(例如你的游戏中背包里有30个物品,每个物品都有一个相同的特效),动画数据数量越大,卡得越厉害。
所以官方有打算製作一個Spine3.8的補釘包嗎?用於Cache緩存相同的動畫文件?


pontos escreveu

這令人難以接受,有看到針對開發時的解決情況,是把Spine.cs相關的打包成dll檔案對吧?但這實際上不能解決發布版本時卡頓的問題。

这对发布版本没有帮助,您的假设是正确的。

pontos escreveu

没有提供动画文件的缓存处理,当同时加载多个动画的时候会卡帧(例如你的游戏中背包里有30个物品,每个物品都有一个相同的特效),动画数据数量越大,卡得越厉害。

不幸的是,机器翻译对上述段落非常含糊。 你的意思是你一次加载很多骨架的时候会遇到fps问题吗? 一般来说,您应该尽可能在游戏的非关键部分加载骨架,而不是在正常游戏过程中。

你的意思是一些骨架资产被加载了两次? 或者您认为应该缓存多次加载的内容?

pontos escreveu

所以官方有打算製作一個Spine3.8的補釘包嗎?用於Cache緩存相同的動畫文件?

不幸的是,我们不会再发布 3.8 的补丁,只会发布 4.0 的补丁。


pontos escreveu

這令人難以接受,有看到針對開發時的解決情況,是把Spine.cs相關的打包成dll檔案對吧?但這實際上不能解決發布版本時卡頓的問題。

This will not help in Release builds, your assumption is correct.

pontos escreveu

没有提供动画文件的缓存处理,当同时加载多个动画的时候会卡帧(例如你的游戏中背包里有30个物品,每个物品都有一个相同的特效),动画数据数量越大,卡得越厉害。

Unfortuantely machine translation was very ambiguous regarding the above paragraph. Do you mean that you encounter fps problems when loading many skeletons at once? In general, you should perform loading of skeletons in non-critical sections of your game where possible, not during normal gameplay.

Do you mean that some skeleton assets were loaded twice? Or what was loaded multiple times that should be cached in your opinion?

pontos escreveu

所以官方有打算製作一個Spine3.8的補釘包嗎?用於Cache緩存相同的動畫文件?

Unfortunately we will not release patches for 3.8 anymore, only for 4.0 going forward.

感谢您发送复制项目。

问题是您正在使用具有 8 个顶点的裁剪多边形,不幸的是,这非常昂贵。

通过不使用此处不需要的 Spine 裁剪多边形,可以轻松解决此问题。 相反,您可以简单地使用 Unity 的 UI Mask 组件。


Thanks for sending the reproduction project.

The problem is that you are using a clipping polygon with 8 vertices, which is unfortunately very costly.

This problem can easily be fixed by not using a Spine clipping polygon which is not necessary here. Instead you can simply use Unity's UI Mask Component.

Harald escreveu

感谢您发送复制项目。

问题是您正在使用具有 8 个顶点的裁剪多边形,不幸的是,这非常昂贵。

通过不使用此处不需要的 Spine 裁剪多边形,可以轻松解决此问题。 相反,您可以简单地使用 Unity 的 UI Mask 组件。


Thanks for sending the reproduction project.

The problem is that you are using a clipping polygon with 8 vertices, which is unfortunately very costly.

This problem can easily be fixed by not using a Spine clipping polygon which is not necessary here. Instead you can simply use Unity's UI Mask Component.

看到問題解決了我很開心!非常謝謝你們的回覆 😃

很高兴我们可以解决问题,感谢您回复我们! 🙂
Glad we could resolve the issue, thanks for getting back to us! 🙂

um mês depois

如果你想存在多个完全相同的SkeletonGrahpic,包括播放的进度,可以尝试使用复制Mesh的方式来实现。
场景中只保留一个SkeletonGraphic,其他的不使用SkeletonGraphic,而是通过向CanvasRenderer中设置那个SkeletonGraphic的Mesh、Mat、Texture来实现。

public SkeletonGraphic root;

private void Start()
{
    this.canvasRenderer = this.GetComponent<CanvasRenderer>();
}

private void Update()
{
    this.canvasRenderer.materialCount = 1;
    this.canvasRenderer.SetMaterial(root.material, 0);
    this.canvasRenderer.SetMesh(root.GetLastMesh());
    this.canvasRenderer.SetTexture(root.mainTexture);
}

private void OnDisable()
{
    this.canvasRenderer.Clear();
}