如何使用 SKPhysicsBody 复制 SKSpriteNode?

Posted

技术标签:

【中文标题】如何使用 SKPhysicsBody 复制 SKSpriteNode?【英文标题】:How to copy SKSpriteNode with SKPhysicsBody? 【发布时间】:2015-02-26 10:32:06 【问题描述】:

我很好奇我今天在尝试取消归档并将 SKSpriteNode 从一个 SKScene 复制到另一个时遇到的情况。在下面操场的输出中,您可以看到 linearDampingangularDamping 在复制后都没有被维护(它们似乎正在恢复到默认值)

// PLAYGROUND_SW1.2 - SKSpriteNode Copy
import UIKit
import SpriteKit

// ORIGINAL
let spriteNode = SKSpriteNode()
spriteNode.name = "HAPPY_NODE"
let size = CGSize(width: 55.0, height: 150.0)
let physics = SKPhysicsBody(rectangleOfSize: size)
physics.linearDamping = 0.123
physics.angularDamping = 0.456
spriteNode.physicsBody = physics

// COPY
let spriteCopy = spriteNode.copy() as! SKSpriteNode

// ORIGINAL
spriteNode.name
spriteNode.physicsBody?.linearDamping
spriteNode.physicsBody?.angularDamping
spriteNode.physicsBody?.area

// COPY
spriteCopy.name
spriteCopy.physicsBody?.linearDamping
spriteCopy.physicsBody?.angularDamping
spriteCopy.physicsBody?.area

操场输出

我不确定我是否正确地复制了这个,SKSpriteNodeSKPhysicsBody 都符合 NSCopying 如果您查看上面的输出,area 属性在复制后保持不变,据我所知,这是基于在创建 SKPhysicsBody 时指定的 size

谁能对此有所了解,或许可以为我提供一个指针,告诉我应该如何深度复制SKSpriteNode

【问题讨论】:

看起来可能是一个错误。 Have you filed one?你试过单独复制物理体吗? 您好,我会尝试进行物理 Body 复制,如果失败也提交错误报告。我还没有报告它,因为我想确保在浪费 Apple 时间之前我没有遗漏一些明显的东西。非常感谢先生。 如果我只创建一个 SKPhysicsBody 并尝试复制它(我正在使用游乐场),我会得到一个 SIGABRT,所以这里肯定有什么问题。我将搜索 Apple 网站并提交错误。 除了 Rickster 之外没有人评论过我已经按照他的建议做了,并向 Apple #20003803 提交了一个错误 【参考方案1】:

我采取一种方法来解决您的问题,可能不是最好的方法,但是

   //COPY
   let spriteCopy = spriteNode.copy() as SKSpriteNode
   let physicsCopy:SKPhysicsBody = spriteNode.physicsBody!;

   ...
   //COPY PHYSICS BODY HARD MODE
   spriteCopy.physicsBody = physicsCopy;

为了解决这个问题,我创建了一个扩展,@mogelbuster 建议覆盖默认 copy(),听起来不错。

extension SKSpriteNode

    override open func copy() -> Any 
        let node = super.copy() as! SKSpriteNode;
        node.physicsBody = super.physicsBody;
        return node;
    

有了这个扩展你就可以做到,默认的copy()方法返回Any,因为你需要转换成SKSpriteNode

// COPY
let spriteCopy = spriteNode.copy() as! SKSpriteNode;

// ORIGINAL
spriteNode.name
spriteNode.physicsBody?.linearDamping
spriteNode.physicsBody?.angularDamping
spriteNode.physicsBody?.area


// COPY
spriteCopy.name
spriteCopy.physicsBody?.linearDamping
spriteCopy.physicsBody?.angularDamping
spriteCopy.physicsBody?.area

【讨论】:

很好的答案! SKSpriteNode 上的扩展绝对是要走的路。重写原始的copy() 方法并调用super 的实现(如在初始化程序中)而不是创建一个新的copyWithPhysicsBody() 方法会更好吗? @mogelbuster 我根据您的提示更改了答案。这是一个很好的观察,我喜欢这个变化。感谢您的观察。 @Fattie 你无论如何都不想这样做,这不会复制SKPhysicsBody,它只是将复制节点的物理体分配给现有的SKPhysicsBody,我猜这要么会崩溃, 或留下没有SKPhysicsBody的原件 我猜这家伙最初的三行代码(就在顶部)会真正复制它 - 但是是的:/“不起作用”我的意思是“不复制属性值”为(我猜)你会希望他们有 NSCopy 在这里做...... 你不应该覆盖 swift 扩展中的属性/函数,你应该阅读文档。

以上是关于如何使用 SKPhysicsBody 复制 SKSpriteNode?的主要内容,如果未能解决你的问题,请参考以下文章

使用“bodyWithTexture”(SpriteKit)时更改 SKPhysicsBody 的中心点

调整使用 SKPhysicsBody(circleOfRadius:) 创建的 SpriteKit SKPhysicsBody

如何将 SKPhysicsBody(texture: size:) 居中于 SKSpriteNode 锚点以外的点

更改 SKPhysicsBody 参数无效

如何从嵌入工作区的 Swift Playground 加载 .sks 文件?

子类化使用 SpriteKit .sks 场景文件创建的 SKNode