我正在使用IOS SpriteKit
并想知道是否有某种方法可以将客户端数据添加到精灵节点?
例如,我想将特定行为附加到节点,附加属性,与其他节点的关系等。
我不愿意子类SKNode
,因为这似乎打破了模型/视图/控制器模型,其中节点只是“视图”。
目前我正在保持一个单独的控制器对象层次结构,但这感觉很笨拙,而且性能不是很好。
什么是最佳做法?
答案 0 :(得分:0)
在这方面,子类化不会改变任何内容。您仍然保留完整功能,并且不做任何事情。事实上,我认为如果你正在制作大型游戏,这几乎是不可避免的。
但是如果你真的不想再使用userData: SKNode -> userData
答案 1 :(得分: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
中的拥有节点。
出于这个原因,提供一个初始化器和/或属性是一个好主意,它将拥有节点作为输入。我更喜欢readonly属性和自定义初始化程序,因为通常你不希望所有者在整个对象的生命周期内改变。非常重要:此属性必须为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;
答案 2 :(得分:0)
虽然这里的其他答案已经提到您可以将userData
字典用于任意键值,但我要补充一点,您可以很好地继承SKNode
s,因为SpriteKit在第一个不是MVC地方(或者至少不是UIKit的意思)。
SKNode
旨在适合常见的游戏架构(组件模式和朋友),实际上可以是模型,视图或控制器。例如,SKNode
不是可显示的对象,但可以保存有关游戏实体/状态或其他子节点的信息。