0

我正在使用IOS SpriteKit并想知道是否有某种方法可以将客户端数据添加到精灵节点?

例如,我想将特定行为附加到节点、附加属性、与其他节点的关系等。

我不愿意子类化SKNode,因为这似乎会破坏节点只是“视图”的模型/视图/控制器模型。

目前,我保留了一个单独的控制器对象层次结构,但这感觉很笨拙,而且在性能方面也不是很好。

什么是最佳做法?

4

3 回答 3

0

在这方面,子类化不会改变任何事情。您仍然保留完整的功能,并且不会破坏任何内容。事实上,我认为如果您正在制作大型游戏,这几乎是不可避免的。

但如果你真的不想再使用 userData: SKNode -> userData

于 2014-03-07T09:27:23.240 回答
0

所有 SKNode 类都提供了一个userData可以用于此目的的属性。

您可以编写一个 Objective-C 类别,通过它您可以添加其他属性而无需子类化。下面是一个经过验证的模式。

界面:

#import "YourCustomObject.h"

@interface SKNode (customObject)
@property (nonatomic) YourCustomObject* yourCustomObject;
@end

执行:

static NSString* YourCustomObjectUserDataKey = @"YourCustomObjectUserDataKey";

@implementation SKNode (customObject)
-(NSMutableDictionary*) internal_getOrCreateUserData
{
    NSMutableDictionary* userData = self.userData;
    if (userData == nil)
    {
        userData = [NSMutableDictionary dictionary];
        self.userData = userData;
    }

    return userData;
}

-(void) setYourCustomObject:(YourCustomObject*)customObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    [userData setObject: customObject forKey:YourCustomObjectUserDataKey];
}

-(YourCustomObject*) yourCustomObject
{
    NSMutableDictionary* userData = [self internal_getOrCreateUserData];
    return (YourCustomObject*)[userData objectForKey:YourCustomObjectUserDataKey];
}
@end

替换YourCustomObject为您的实际班级名称。

当然,该类别可以扩展为托管多个属性,您不必为每个属性编写单独的类别。该类别也不必在 SKNode 上,如果您需要其他属性但仅在 SKSpriteNode 上,您可以将此作为 SKSpriteNode 上的类别。

很多时候,您需要访问YourCustomObject.

出于这个原因,提供一个将拥有节点作为输入的初始化程序和/或属性是一个好主意。我更喜欢只读属性和自定义初始化程序,因为通常您不希望所有者在对象的整个生命周期内更改。非常重要:此属性必须weak不创建保留循环。

@interface YourCustomObject
@property (weak, readonly) SKNode* owningNode;
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode;
@end

@implementation YourCustomObject
+(instancetype) customObjectWithOwningNode:(SKNode*)owningNode
{
    return [[self alloc] initWithOwningNode:owningNode];
}
-(id) initWithOwningNode:(SKNode*)owningNode
{
    self = [super init];
    if (self) 
    {
        _owningNode = owningNode;
    }
    return self;
}
@end

然后,您可以在节点类中创建和分配您的自定义对象:

YourCustomObject* customObject = [YourCustomObject customObjectWithOwningNode:self];
self.yourCustomObject = customObject;
于 2014-03-07T09:27:44.943 回答
0

虽然这里的其他答案已经提到您可以将userData字典用于任意键值,但让我补充一点,您可以将SKNodes 子类化,因为 SpriteKit 首先不是 MVC(或者至少不是 UIKit 的方式) .

SKNodes 旨在适应常见的游戏架构(组件模式和朋友),实际上可以是模型、视图或控制器。SKNode例如 不是可显示的对象,但可以保存有关游戏实体/状态或其他子节点的信息。

于 2014-03-07T10:05:42.120 回答