如何复制带有SKPhysicsBody的SKSpriteNode?

8

今天我在尝试从一个SKScene复制和取消归档一个SKSpriteNode的时候,遇到了一个有趣的情况。从下面游乐场的输出中可以看到,在复制后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

游乐场输出 enter image description here

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

有人能为此提供一些说明,并为我提供有关如何深度复制SKSpriteNode的指针吗?


2
看起来可能是一个bug。你是否已经提交了一个?你尝试过单独复制物理体吗? - rickster
嗨,我会尝试复制物理体并在失败后提交错误报告。我之前还没有报告它,因为我想确保在浪费苹果公司的时间之前,我没有错过任何明显的东西。非常感谢您。 - fuzzygoat
如果我只创建一个SKPhysicsBody并尝试复制它(我正在使用playground),我会得到一个SIGABRT错误,所以这里肯定有什么问题。我将搜索Apple网站并提交一个错误报告。 - fuzzygoat
1
由于除Rickster外没有其他人进行评论,所以我根据他的建议向苹果提交了错误报告#20003803。 - fuzzygoat
1个回答

12

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

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

   ...
   //COPY PHYSICS BODY HARD MODE
   spriteCopy.physicsBody = physicsCopy;
为了解决这个问题,我创建了一个扩展,并且@mogelbuster建议覆盖默认的copy(),听起来很不错。

要解决此问题,我创建了一个扩展,@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

图片


1
很棒的答案!在SKSpriteNode上进行扩展绝对是正确的方法。重写原始的copy()方法并调用super的实现(就像在初始化器中一样)是否比创建一个新的copyWithPhysicsBody()方法更好? - mogelbuster
1
@mogelbuster,我根据你的提示改变了答案。这是一个很好的观察,我喜欢这个改变。感谢你的观察。 - ViTUu
1
@Fattie 无论如何您都不想这样做,因为这并没有复制SKPhysicsBody,它只是将副本节点的物理体赋值给现有的SKPhysicsBody,我猜想这要么会导致崩溃,要么会使原始节点失去SKPhysicsBody - Knight0fDragon
我猜这个人最开始的三行代码(就在顶部)确实会复制它 - 但是是的 :/ "不起作用"是指“不复制属性值”,就像你希望NSCopy在这里做的那样... - Fattie
你不应该在Swift扩展中覆盖属性/函数,你应该阅读文档。 - Minimi
node.physicsBody = super.physicsBody; 在 Swift 5.3 中会导致运行时错误;改为 node.physicsBody = super.physicsBody?.copy() as? SKPhysicsBody 可以解决问题。 - Tien Do

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接