Objective c SKSpriteNode的正确子类化和实例初始化

Objective c SKSpriteNode的正确子类化和实例初始化,objective-c,sprite-kit,initialization,subclass,skspritenode,Objective C,Sprite Kit,Initialization,Subclass,Skspritenode,我正在尝试将SKSpriteNode子类化,以便使用它为游戏创建具有不同属性的不同角色。我知道这应该是一项微不足道的任务,但我很难理解在创建实例时如何初始化变量。 在标题中,我有: #import <SpriteKit/SpriteKit.h> @interface MyClass : SKSpriteNode @property int myVariable; @end 在场景中创建节点时: @implementation GameScene { MyClass *m

我正在尝试将SKSpriteNode子类化,以便使用它为游戏创建具有不同属性的不同角色。我知道这应该是一项微不足道的任务,但我很难理解在创建实例时如何初始化变量。 在标题中,我有:

#import <SpriteKit/SpriteKit.h>

@interface MyClass : SKSpriteNode 
@property int myVariable;
@end
在场景中创建节点时:

@implementation GameScene
{
    MyClass *mySprite;
}

- (void)didMoveToView: (SKView *) view
{
    mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
}
myVariable的值是0,我假设这意味着SpritodeWithimageNamed不执行init方法。如果我使用:

mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
mySprite = [MyClass spriteNodeWithImageNamed:@"image.png"];
变量名已正确设置为100,但随后SPRITENODEWITHIMAGENAME将其恢复为0

我也尝试过:

mySprite = [[MyClass alloc] init]; // or mySprite = [MyClass new];
[mySprite setTexture:[SKTexture textureWithImageNamed:@"image.png"]];

在本例中,myVariable的值是正确的,但在将节点添加到场景中时,不会显示任何图像。使用spriteNodeWithImageNamed时调用哪个init方法?我是否错误地重写了SKSpriteNode init方法?

您已经正确地创建了一个类,但是您需要记住,您正在调用工厂方法
spriteNodeWithImageNamed
,然后它自己初始化和分配。因此,如果要使用自定义的
init
方法,还需要重写工厂方法

在MyClass实现内部,重写方法以调用初始值设定项:

+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
    MyClass *newClass = [[MyClass alloc] init];
    SKTexture *spriteTexture = [SKTexture textureWithImageNamed:imageName];
    newClass.size = spriteTexture.size;
    newClass.texture = spriteTexture;
    return newClass;
}
希望这有帮助,如果你有问题,请告诉我

*EDIT:我实际上有点想放弃这个,只是因为SKSpriteNode没有
init
方法(至少我们不知道)。因此,除非你想深入探究苹果的奥秘,否则就这样做:

+ (instancetype) spriteNodeWithImageNamed:(NSString *)imageName{
    MyClass *newClass = [[MyClass alloc] initWithImageNamed:imageName];
    newClass.myVariable = 100;
    return newClass;
}

您可以替代使用
initWithImage
来放入myVariable,但关键是我要避免将
init
初始值设定项与SKSpriteNode一起使用。创建自己的自定义init方法,只需调用默认的spritenode initWithImage

-(id)initShipWithType:(ShipType)type {
    self = [super initWithImageNamed:[self getShipSprite:type]];
    if (self) {

    }
    return self;
}

使用现代的obj-c和Xcode,无需进行
@合成
谢谢。这是有道理的,myVariable的值现在是正确的。但是,节点不会出现在场景中。这与加载纹理有关吗?根据手册:“雪碧套件尽可能延迟加载和准备纹理”。当调用纹理对象上的“大小”方法时,将加载纹理数据。另一种方法是调用需要纹理大小的方法,例如创建使用纹理对象的新SKSpriteNode对象。其中一个预加载方法被调用。因为我们不再从SKSpriteNode调用纹理,这可能是原因?好吧,您调用
[super init]
,所以除了添加的额外变量之外,您确实有一个spriteNode。纹理应该初始化良好。你在看什么?如果是红色的“X”,则图像不存在或名称输入错误。如果您什么也看不到,可能是因为zPosition没有被设置,它位于错误的位置/没有作为子对象添加,或者只是整个对象被释放,而它不在那里。请仔细查看您的代码或在编辑中发布如何处理节点,直到您将其作为子节点添加到您希望看到的位置。再次感谢。节点在那里,但其大小为0。这就是精灵不可见的原因。尽管我可以使用操作:[newClass runAction:[SKAction setTexture:texture resize:YES]]使节点显示;该节点的其他方面仍然无法正常工作:我添加到该节点的子节点不可见,并且未检测到联系人。我想当SKSpriteNode被子类化时,有些工厂初始化不会被复制。看一看工厂实现,了解其方法的更多细节,这将是一件有趣的事情。是的,我认为仅仅使用普通的init会有一些问题。。。检查上面的“我的编辑”^。我只使用spriteNode的initWithImageNamed,它应该执行您遇到问题的后台初始化。好了,现在它可以工作了!我猜initWithImageNamed方法不需要init。非常感谢你的帮助。非常感谢。
-(id)initShipWithType:(ShipType)type {
    self = [super initWithImageNamed:[self getShipSprite:type]];
    if (self) {

    }
    return self;
}