合并或展平背景节点以提高游戏性能?
Posted
技术标签:
【中文标题】合并或展平背景节点以提高游戏性能?【英文标题】:Merging or flattening background nodes to improve game performance? 【发布时间】:2017-10-15 20:33:55 【问题描述】:我希望能够通过某种方式“扁平化”我的背景节点来提高我的游戏性能。
This youtube video demonstrates how I build up my background graphics.
但是,我的背景图形是这样设置的。
我使用两种纹理,如邮票,然后重复。 在这种情况下... 一种带有雪顶的山脉纹理... 没有雪的一山纹理。 我改变这些图章的 zPosition 以获得“分层”效果。
然后我使用“填充”,它们只是纯灰色的 SKSpriteNodes 来覆盖需要灰色填充的部分。
例如添加填充节点之前
然后在顶部添加一个带有 alpha 的彩色屏幕,使这座山看起来褪色。
例如前
例如后
游戏有时会死机...但当我删除这些图形时它不会死机。
在加载场景时,有没有办法通过基于 zPosition 合并或展平背景图形节点来提高性能? 我该怎么做?
这会提高性能吗? 或者在我的情况下提高性能的最佳方法是什么?
我认为这个问题很相似...... Merge all SKSpriteNode children into a single SKSpriteNode
但是,我如何在 Swift 中做到这一点并考虑 zPosition 和 alpha,这样我就不会失去分层效果?
【问题讨论】:
您用冲压、重复和分层等词语描述您的意图的方式,听起来与SKTileMapNode
的功能完全一样。
这行不通。 “邮票”以随机方式相互叠加。这是为了改变山丘的大小。不过,平台上的雪部分是 SKTileMapNodes。
哦,天哪,赏金,有一种方法可以合并它们,只要你有足够的纹理内存。请注意,除非您将其添加到图集中,否则这将减少您的绘制次数,但您可以使用view.textureFromNode
将节点树转换为单个纹理。 (注意在执行此操作时将其包装在自动释放池中)现在,如果您使用 xcassets 来执行当前的图集,我建议您回到常规的 .atlas 文件夹,直到苹果修复 xcassets 内导致绘制计数增加的错误剧烈。
@Knight0fDragon 我打算为此做一个答案,但在我看来,背景不应该真的导致性能问题......他需要bitblit还是只是将他的文件移动到不同的文件夹?
我认为他只需将他的图像放入旧的 atlas 文件夹中以减少他的绘制次数。 Apple 尚未就 xcassets 错误回复我
【参考方案1】:
你可能想做的事情:
将您的前景和背景分离成单独的 SKS 文件,然后加载它们
通过SKReferenceNode
进入你的主SKS文件
使用view!.texture(from: node)
通过代码将这些SKS文件转换为纹理而不是SKReferenceNode
s
确保您的图集不会以增加抽奖次数的方式分解
以一种并非所有节点都在场景中的方式设计您的代码,节点越多,您的代码变得越慢。
如果你有SKPhysicsBody
,尽量少用。这可以通过我将多个主体与SKPhysicBody(bodies:)
合并在一起或创建一个带有围绕多个对象的多边形的主体来完成。
另外,如果你的身体没有通过物理运动(不是SKAction
s),那么请确保将isDynamic
设置为false
如果您正在运行SKAction
s,请确保尽可能少地使用这些。例如,如果您有 4 个不同的节点以每秒 10 个点的速度向左移动,您可以将这 4 个节点放入一个父节点,并在父节点上运行该操作。
【讨论】:
如何“设计代码,使并非所有节点都在现场”?您是否只是指不在相机视图中时删除节点?我可以得到一个带代码的例子吗?我一直不愿意这样做……因为我不知道如何以足够快的速度添加和删除节点以使其有意义……例如,玩家向后走,而您只是删除了这些节点。 这由您决定,如果您知道该节点将在几分钟内出现,请不要将其删除,但如果您有一个距离 30000 点的节点,那不会不需要在现场 我问了一个关于地图集问题@Knight0fDragon 的单独问题。如果您想...随意编辑它,以便社区更清楚,因为不完全了解地图集如何导致性能问题。 ***.com/questions/46981858/…【参考方案2】:好的,这是您现在拥有的示例。您的所有节点都像这样:
如何轻松执行bitblit是将所有这些移动到一个名为“background”的新空节点下
现在转到您的 swift 文件,并为我们将在代码中创建的新节点设置一个占位符变量
class GameScene: SKScene
var blitBackground = SKSpriteNode()
override func didMove(to view: SKView)
现在,添加这个方便的功能,如果需要,您可以在所有项目中使用它:
func blit(from node: SKNode) -> SKSpriteNode
return SKSpriteNode(texture: SKView().texture(from: node))
这是我们将用来初始化我们的 bitblit 背景的方法,并从游戏中删除滞后的背景:
func blitTheBackground() // use in didMove
let laggyBackground = childNode(withName: "background")!
blitBackground = blit(from: laggyBackground)
laggyBackground.removeFromParent()
addChild(blitBackground)
这是完成的场景:
class GameScene: SKScene
var blitBackground = SKSpriteNode()
func blit(from node: SKNode) -> SKSpriteNode
return SKSpriteNode(texture: SKView().texture(from: node))
func blitTheBackground()
let laggyBackground = childNode(withName: "background")!
blitBackground = blit(from: laggyBackground)
laggyBackground.removeFromParent()
addChild(blitBackground)
override func didMove(to view: SKView)
blitTheBackground()
它将节点数从 10 个减少到 4 个……希望对您而言,它也有助于您的平局计数!!
注意,这种方法对 shapenodes 非常有效!!
如果您需要在循环中执行此操作,请务必将其放入自动释放池中,以确保在使用后释放内存。从视图创建纹理会占用大量内存,因此如果您不小心,可能会出现错误。
for i in 0..<5
autoreleasepool
let laggyBackground = childNode(withName: "background\(i)")!
blitBackground = blit(from: laggyBackground)
laggyBackground.removeFromParent()
addChild(blitBackground)
【讨论】:
这正是我想要的!惊人的!非常感谢。 注意,包装在你计划循环它的自动释放块中。 @CoreyF,你在你的问题中发布了这个,你正在寻找比这更多的东西 自动释放块对我有什么作用?在上述情况下,我循环它对吗?注意:是的,我仍然需要实施您对性能增强的建议。它们都可能是我想做的事情。此处带有代码答案的分步示例非常清楚。我绝对需要澄清您以某种方式提出的一些建议(例如,什么情况会导致“我的地图集以增加抽奖次数的方式分解”。) 我具体将自动释放包裹在哪个部分? 我什至不知道他在说什么哈哈我认为 KoD 比在 SK 工作的人知道的更多以上是关于合并或展平背景节点以提高游戏性能?的主要内容,如果未能解决你的问题,请参考以下文章