Subclass SKNode que no mueve niños

Tengo un sprite que no puede existir en mi juego sin un emparejamiento SKFieldNode así que mi solución fue crear una subclass de SKSpriteNode y crear una propiedad para SKFieldNode pero no funcionó porque el SKSpriteNode estaba actuando extraño (no lo hago restring exactamente lo que pasó). Entonces, mi siguiente enfoque fue cambiar la subclass a SKNode y luego convertiría el SKSpriteNode y el SKFieldNode una propiedad de este nuevo SKNode . Pero resulta que touchesMoved solo moverá una de las properties (lo que esté en la parte superior) que resulta ser siempre SKSpriteNode .

¿Cuál es el mejor enfoque para este problema y cómo puedo solucionarlo para que pueda tener un SKFieldNode para cada SKSpriteNode mientras se asegura de que las acciones y los methods sigan funcionando correctamente?

Código actual de la subclass SKNode :

 @interface Whirlpool : SKNode - (instancetype)initWithPosition:(CGPoint)pos region:(float)region strength:(float)strength falloff:(float)falloff; @property (nonatomic, strong) SKFieldNode *gravityField; @end #import "Whirlpool.h" #import "Categories.h" @implementation Whirlpool - (instancetype)initWithPosition:(CGPoint)pos region:(float)region strength:(float)strength falloff:(float)falloff { if (self = [super init]) { // whirlpool sprite SKSpriteNode *whirlpoolSprite = [[SKSpriteNode alloc] initWithImageNamed:@"whirlpool"]; whirlpoolSprite.size = CGSizeMake(100, 100); whirlpoolSprite.position = pos; //removing physicsBody and associated attributes for now so that the boat does not collide with the whirlpool //whirlpoolSprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:whirlpoolSprite.size.width / 2]; //whirlpoolSprite.physicsBody.dynamic = NO; whirlpoolSprite.zPosition = 1; whirlpoolSprite.name = @"whirlpool"; [whirlpoolSprite runAction:[SKAction repeatActionForever:[self shanetworkingRotateAction]]]; // whirlpool gravity field _gravityField = [SKFieldNode radialGravityField]; _gravityField.position = pos; _gravityField.strength = strength; _gravityField.falloff = falloff; _gravityField.region = [[SKRegion alloc] initWithRadius:region]; _gravityField.physicsBody.categoryBitMask = gravityFieldCategory; _gravityField.zPosition = 1; [self addChild:whirlpoolSprite]; [self addChild:_gravityField]; } return self; } - (SKAction *)shanetworkingRotateAction { static SKAction *rotateWhirlpool; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ rotateWhirlpool = [SKAction rotateByAngle:-M_PI * 2 duration:4.0]; }); return rotateWhirlpool; } @end 

 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // we don't want the player to be able to move the whirlpools after the button is pressed if (_isRunning) { return; } for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self]; SKNode *node = [self nodeAtPoint:location]; // if the finger touches the boat or the whirlpool, update its location if ([node.name isEqualToString:@"boat"]) { node.position = CGPointMake(location.x, node.position.y); } else if ([node.name isEqualToString:@"whirlpool"]) { node.position = location; } } } 

Creo que sus problemas se deben a que "whirlpool" es hijo de su subclass SKNode. Entonces, cuando identifica que efectivamente está tocando un "remolino", lo está moviendo dentro de su elemento primario (la subclass SKNode) y el SKFieldNode y los elementos principales permanecen en order. Este pequeño ajuste a su código original debería funcionar … si entiendo el problema correctamente.

 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // we don't want the player to be able to move the whirlpools after the button is pressed if (_isRunning) { return; } for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self]; SKNode *node = [self nodeAtPoint:location]; // if the finger touches the boat or the whirlpool, update its location if ([node.name isEqualToString:@"boat"]) { node.position = CGPointMake(location.x, node.position.y); } else if ([node.name isEqualToString:@"whirlpool"]) { //move the SKNode subclass the whirlpool is a child of node.parent.position = location; } } } 

Espero que eso ayude.

Sí, el problema aquí es la forma en que estás agarrando nodos, es posible que estés agarrando los nodos incorrectos debido a todos los niños. En cambio, tome este enfoque:

Ya sabemos que estás subclassando tus sprites, así que en tus subclasss, agrega el siguiente código:

 //Whirlpool - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self.parent];//Unless you are retaining the scene in the child, then use that self.position = location; } } 

Entonces:

 //Boat - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch *touch in touches) { CGPoint location = [touch locationInNode:self.parent];//Unless you are retaining the scene in the child, then use that self.position.x = location.x; } } 

Entonces, para tu escena, haz esto:

 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // we don't want the player to be able to move the whirlpools after the button is pressed if (_isRunning) { return; } //At this point it should call the children on touch events [super.touchesMoved: touches withEvent:event]; }