Как скопировать SKSpriteNode с помощью SKPhysicsBody?

Мне любопытна ситуация, с которой я столкнулся сегодня при попытке разархивировать и скопировать SKSpriteNode из одного SKScene в другой. В выводе с игровой площадки ниже вы можете видеть, что linearDamping и angularDamping или не поддерживаются после копирования (кажется, что они возвращаются к значениям по умолчанию)

// 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

ВЫВОД ИГРОВОЙ ПЛОЩАДКИ введите здесь описание изображения

Я не уверен, что копирую это правильно, и SKSpriteNode, и SKPhysicsBody соответствуют NSCopying. Если вы посмотрите на вывод выше, свойство area сохраняется после копирования, и, насколько мне известно, это основано на size, указанном при создании SKPhysicsBody.

Может ли кто-нибудь пролить свет на это и, возможно, дать мне указатель на то, как я должен глубоко копировать SKSpriteNode?


person fuzzygoat    schedule 26.02.2015    source источник
comment
Похоже на возможную ошибку. Вы подали заявку? Вы пробовали отдельно копировать физическое тело?   -  person rickster    schedule 28.02.2015
comment
Привет, я попробую сделать копию тела физики, а затем отправлю отчет об ошибке, если это тоже не удастся. Я еще не сообщил об этом, потому что хотел убедиться, что не упустил что-то очевидное, прежде чем тратить время Apple. Большое спасибо, сэр.   -  person fuzzygoat    schedule 01.03.2015
comment
Если я создам только один SKPhysicsBody и попытаюсь скопировать его (я использую игровую площадку), я получу SIGABRT, так что здесь определенно что-то не так. Я поищу на сайте Apple и отправлю сообщение об ошибке.   -  person fuzzygoat    schedule 02.03.2015
comment
Поскольку никто, кроме Рикстера, не прокомментировал, я сделал, как он предлагает, и отправил сообщение об ошибке в Apple # 20003803.   -  person fuzzygoat    schedule 04.03.2015


Ответы (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

ИЗОБРАЖЕНИЕ

person ViTUu    schedule 05.03.2015
comment
Отличный ответ! Расширение на SKSpriteNode — это определенно то, что вам нужно. Было бы лучше переопределить исходный метод copy() и вызвать реализацию super (как в инициализаторах) вместо создания нового метода copyWithPhysicsBody()? - person mogelbuster; 09.03.2017
comment
@mogelbuster Я изменил ответ на основе вашего совета. Это хорошее наблюдение, мне понравилось это изменение. Спасибо за наблюдение. - person ViTUu; 10.03.2017
comment
@Fattie Вы бы все равно не хотели этого делать, это не копирует SKPhysicsBody, оно просто присваивает физическое тело копируемого узла существующему SKPhysicsBody, что, как я предполагаю, либо приведет к сбою, либо оставит оригинал без SKPhysicsBody - person Knight0fDragon; 23.10.2017
comment
я предполагаю, что исходные три строки кода парня (справа вверху) действительно скопируют его, но да: / Под не работает, я имел в виду, что не копирует значения свойств, поскольку (я думаю), вы ожидаете, что они будут иметь NSCopy делай здесь... - person Fattie; 23.10.2017
comment
Вы не должны переопределять свойства/функции в быстрых расширениях, вы должны прочитать документы. - person Minimi; 24.08.2018
comment
node.physicsBody = super.physicsBody; вызывает ошибку времени выполнения в Swift 5.3; поменял на node.physicsBody = super.physicsBody?.copy() as? SKPhysicsBody заработало. - person Tien Do; 27.04.2021