我正在使用IOS SpriteKit
,並想知道是否有某種方式將客戶端數據添加到精靈節點?如何將客戶端數據添加到SKNode/SKSpriteNode?
例如,我想具體的行爲附加到一個節點,附加屬性,與其他節點等關係
我不願意SKNode
子類,因爲這將出現打破模型/視圖/控制器模型中節點只是「視圖」。
目前我正在保持控制器對象的單獨層次結構,但這感覺很笨拙,並且它在性能方面並不是很好。
什麼是最佳實踐?
我正在使用IOS SpriteKit
,並想知道是否有某種方式將客戶端數據添加到精靈節點?如何將客戶端數據添加到SKNode/SKSpriteNode?
例如,我想具體的行爲附加到一個節點,附加屬性,與其他節點等關係
我不願意SKNode
子類,因爲這將出現打破模型/視圖/控制器模型中節點只是「視圖」。
目前我正在保持控制器對象的單獨層次結構,但這感覺很笨拙,並且它在性能方面並不是很好。
什麼是最佳實踐?
子類化在這方面不會改變任何東西。你仍然保留完整的功能,並且什麼也不破。事實上,我認爲如果你正在製作一款大型遊戲,這幾乎是不可避免的。
但如果你真的不想再使用用戶數據: 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;
謝謝 - 這非常有幫助。我已經結束了分類作爲一個快速解決方案。在SKNode上閱讀時我錯過了userData! – RikMaxSpeed
雖然這裏的其他答案已經提到,您可以使用userData
字典任意鍵值,讓我補充說你很好地繼承了SKNode
,因爲SpriteKit首先不是MVC(或者至少不是UIKit的方式)。
SKNode
小號設計適合普通遊戲架構(零部件陣列和朋友),而且實際上是對自己的模型,視圖或控制器。例如,SKNode
不是可顯示對象,但可以保存關於遊戲實體/狀態或其他子節點的信息。
我發現最好是在它自己的類中實現特定於節點的行爲。但是,如果您只想將信息存儲在控制器對象可以作出決策的基礎上,則可以使用userData屬性。 – ZeMoon