我正在使用IOS SpriteKit
并想知道是否有某种方法可以将客户端数据添加到精灵节点?
例如,我想将特定行为附加到节点、附加属性、与其他节点的关系等。
我不愿意子类化SKNode
,因为这似乎会破坏节点只是“视图”的模型/视图/控制器模型。
目前,我保留了一个单独的控制器对象层次结构,但这感觉很笨拙,而且在性能方面也不是很好。
什么是最佳做法?
我正在使用IOS SpriteKit
并想知道是否有某种方法可以将客户端数据添加到精灵节点?
例如,我想将特定行为附加到节点、附加属性、与其他节点的关系等。
我不愿意子类化SKNode
,因为这似乎会破坏节点只是“视图”的模型/视图/控制器模型。
目前,我保留了一个单独的控制器对象层次结构,但这感觉很笨拙,而且在性能方面也不是很好。
什么是最佳做法?
在这方面,子类化不会改变任何事情。您仍然保留完整的功能,并且不会破坏任何内容。事实上,我认为如果您正在制作大型游戏,这几乎是不可避免的。
但如果你真的不想再使用 userData: SKNode -> userData
所有 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;
虽然这里的其他答案已经提到您可以将userData
字典用于任意键值,但让我补充一点,您可以将SKNode
s 子类化,因为 SpriteKit 首先不是 MVC(或者至少不是 UIKit 的方式) .
SKNode
s 旨在适应常见的游戏架构(组件模式和朋友),实际上可以是模型、视图或控制器。SKNode
例如 不是可显示的对象,但可以保存有关游戏实体/状态或其他子节点的信息。