【问题标题】:Reducing number of draw counts (passes) in SpriteKit减少 SpriteKit 中的绘制次数(通过次数)
【发布时间】:2019-12-01 23:19:50
【问题描述】:

我想优化抽奖次数,但不知道从哪里开始。

有人可以简要解释(或指出正确的方向)哪些因素会影响绘图,有没有办法查看/调试它们,是否有任何优化提示?抽奖的最佳次数是多少?

例如,我的游戏为整个 ui 加载一个纹理图集,并使用子节点作为不同游戏菜单的容器(而不是单独的场景)。但是一屏draw count 20+,fps下降10-15,这是个问题。

【问题讨论】:

    标签: sprite-kit sknode


    【解决方案1】:

    OK 认为游戏场景的领域是由层组成的。每个 zPosition 引用属于层的节点。 (属性被称为 zPosition 的原因是因为它的节点位置沿 zAxis)

    如果您有一个带有 4 个 SKSpriteNodes 的 gameScene,并如上图所示为节点指定 zPositions,那么系统会将您的意图解释为上图所示。渲染系统时,绘制计数为 4。在绘制计数为 1 时,将渲染 zPosition 为 1 的所有节点。在绘制计数 2 中,将渲染 zPosition 为 2 的所有节点,依此类推。这被称为画家算法。就像画家画画一样。

    现在说,在我们的游戏场景中,我们想将另一个 SKSpriteNode 添加到节点 3。如果我们将其作为子节点添加到节点 3,那么这就是

    var ignoresSiblingOrder: Bool { get set }
    

    开始发挥作用。如果设置为 false,那么我们的新节点将在父节点 3 之后呈现。所以它的 zPosition 应该是 3.5。我们的绘制计数现在增加到 5。如果设置为 true,系统将忽略子/父关系,我们的绘制计数将再次下降到 4,但不能保证系统将首先渲染什么。节点 3 或我们的新节点。这是结果是不确定的,这意味着它不会返回相同的结果。有时 node3 将呈现在其子节点之上。其他时候子节点将呈现在父节点之上。

    最后一个非常重要的一点是,只有当两个节点之间发生重叠时,系统才会考虑 zPosition。

    优化的一个好方法是尽可能制作单个纹理。如果不需要单独的节点,那就不要!创建一个纹理并使用它。

    这是关键,可能也是最重要的一点。如果可能,请避免节点重叠。 zPosition 仅在节点覆盖期间考虑。如果您有 1000 个节点,所有节点都具有不同的 zPosition,但没有一个节点重叠,猜猜是什么......您的绘制计数为 1。

    如果节点覆盖无法避免,而且在某些情况下大多数情况下也无法避免。将 ignoreSiblingOrder 设置为 true。 (您实际上并不需要这样做,但它使事情变得更简单,并允许您指定绘制周期)确保为所有节点设置 zPositions。但 KEY 请记住,每次创建新的 zPosition 时,只要该节点与另一个节点相交,就会将绘制次数增加 1。

    希望对你有帮助

    【讨论】:

    • 等等,所以如果ignoresSiblingOrdertrue 并且设置了zPositions,那么draw count 会很低,但是缺点是渲染的顺序?如果一个游戏有 1 层和多个不同 zPos 的节点,draw count 仍然是 1?
    • No ignoreSigblingOrder 永远不会覆盖设置的 zPosition。抽奖次数就是您拥有的不同 zPosition 的数量。 ignoreSigblingOrder 只影响渲染的子/父关系
    • 你的意思是,如果我有 100 个节点,每个节点都有自己的 zPosition ( 0..
    • 是的!!!!我不能说其他任何方式......节点 zPosition 会影响绘制调用计数,因为通常,不同 zPosition 的节点必须在后续传递中呈现。例如,相互重叠的节点必须在单独的绘制调用中完成。如果启用 SKView ignoresSiblingOrder 属性,则可以在相同的绘制调用中呈现相同 zPosition 的重叠节点。 developer.apple.com/documentation/spritekit/sknode/…
    • 我已经标记了 Georges 的答案,因为它对我有帮助,而且它是第一个。但你也帮助了我,所以我赞成你的回答。
    【解决方案2】:

    绘制计数是需要以正确的顺序对场景进行分层的结果,例如,如果某些节点具有一定的透明度,则它们可能会依赖于其背后的内容。

    1: 减少绘制次数的最大方法之一是一次渲染多个节点 - 这可以通过将您想要在同一层中的子节点添加到父节点来实现。例如,有一个名为nodeCollection 的父节点并使用addChild() 添加多个要一起渲染的节点以降低性能损失。

    2:您可以做的另一件事是在SKView 上将ignoresSiblingOrder 设置为true,并在每个节点上使用zPosition - 这意味着SpriteKit 需要做的工作更少因为你更明确。

    3:不要将 SpriteKit 用于 UI!这就是 UIKit 的用途!你有你的SKView,它拥有你的SKSceneSKViewUIView 的子类,这意味着您将它放置在您的一个视图控制器中。您需要做的就是在 SKView 顶部的视图控制器中添加移动视图或按钮或任何您想要的东西,然后就可以了!

    我建议查看更多优化:Hacking with Swift - 15 tips to optimize your SpriteKit game

    【讨论】:

    • 您确定第 1 点吗?如果您添加一个连接了多个节点的节点,每个节点都有不同的 zPosition 值,那么绘制计数不会减少。即使考虑成本,也可能更糟(只是略微......但仍然)
    • 加上 Georges 点我想说最重要的事情是看看你在做什么,并认为我真的需要在那里有一个不同的 zPosition。如果答案是肯定的,那就这样吧。如果不摆脱它。抽奖次数基于您拥有的不同 zPosition 的数量。编译器操作系统足够聪明,不会使用未引用的 zPositions,所以如果你有 2 个节点。 zPosition 1 处的节点 1 和 zPosition 100 处的节点 2 你仍然只有 2 个绘制计数。
    • ignoresSiblingOrder 设置为 true。但现在我很困惑。 zPosition 是否会影响绘图,或父/子关系,或两者都影响?我应该使用委托将节点传递给 1 个节点并在那里使用 addChild(),还是尽可能减少 zPos,或两者兼而有之?
    • @elektricni ignoresSiblingOrder 是节点的位置和层次决定渲染顺序的时候。如果您有一个大型节点树,这可能会非常昂贵。仅在 ignoresSiblingOrder = true 时使用 zPositionzPosition 只是在右边的渲染层放了一个节点,并没有减少draw call。当场景中的节点较少时,绘制调用会减少(这就是为什么您可以将多个节点添加到父节点,因此 SpriteKit 知道它们要一起渲染)。
    • @hoboBob 我想说只是不要将节点的zPosition 设置为全部是父节点的子节点。我不确定这方面的性能,但父节点应该代表整个层(例如,有 64 个节点作为胸板网格的父节点不需要zPosition)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多