我试图在SpriteKit中的场景“SKScene”之间传递数据。例如,我想将分数从A级传递到B级。
也许解决方案是归档,但我希望实现更简单的方式,就像我们使用视图控制器一样。
非常感谢这方面的任何线索。
答案 0 :(得分:15)
如果您要将分数传递到许多不同的场景,您可能希望将其存储在NSUserDefaults
或某些可访问的存储机制中。但是,如果您希望在SpriteKit对象之间传递数据,则每个SKNode
(包括SKScene
)都有一个名为userData
的字典属性,您可以将其用于您想要的任何内容。以下是如何在场景之间传递分数的示例:
- (void)changeScene
{
SKView *spriteView = (SKView *) self.view;
SKScene *currentScene = [spriteView scene];
SKScene *newScene = [MySceneClass scene];
[newScene.userData setObject:[currentScene.userData objectForKey:@"score"] forKey:@"score"];
[spriteView presentScene:newScene];
}
答案 1 :(得分:6)
将分数存储在视图控制器实例中,或者将SKView子类化并存储在那里。这将保留视图生命周期内的任何对象。
如果您需要在应用重新启动之间保留分数,请使用NSUserDefaults
。
Kobold Kit实际上使这样的东西很容易,没有自定义子类。视图具有(并且任何节点都可以)一个KKModel
对象,它是两个整数类型(float,int等通过KKMutableNumber
)和任意对象的键/值存储。
因此,您可以通过将其绑定到视图来持久存取并访问来自任何节点的 :
[self.kkView.model setObject:highscores forKey:@"highscores"];
kkView属性是写(KKView*)self.view
的简写。
对于其生命周期与场景或视图相关联的对象,绝对不需要使用或受益于使用单例。它们属于场景或视图,期间。
答案 2 :(得分:4)
这种方法对我有用,我认为这是正确的。到目前为止,这是在我发现的场景之间传递数据的最简单,最快捷的方式。
<强> 1。有关userData的基本信息:
1.1。按住苹果“Command键”并在“userData”字符串上按下鼠标左键(在Xcode中)(例如“self。 userData ;”)。 您将获得以下信息:
// An optional dictionary that can be used to hold user data pretaining to the node. Defaults to nil.
@property (SK_NONATOMIC_IOSONLY, retain) NSMutableDictionary *userData;
1.2。访问apple docs:userData
1.3 userData是一个NSMutableDictionary,它基本上是一个特殊的数组。除了值之外,它还包含一个绑定到值的键。使用此键,您可以找到值。 这可能会有所帮助:apple docs:NSMuttableDictionary
<强> 2。解决方案:
2.1。 firstScene
//somewhere in firstScene.m
//how the tranisiton from firstScene to secondScene is going to look and how long it is goint to take
SKTransition *reveal = [SKTransition moveInWithDirection:SKTransitionDirectionDown duration:0.5];
SKView * skView = (SKView *)self.view;
SKScene *secondScene = [WBMGameEndsScene sceneWithSize:skView.bounds.size];
//You need to initialize the NSMD since it is by default nil.
secondScene.userData = [NSMutableDictionary dictionary];
这里我通过添加一个作为我得分的对象来引用secondScene的userData。出于测试目的,它只是6.我将添加我的分数实例变量。您可以添加任何您想要的内容,因为它接受“id”类型的对象。关键很重要。您将在secondScene.m中使用它来访问对象值。检查你输错了。
[secondScene .userData setObject:@"6" forKey:@"score"];
//Testing
NSLog(@"Is it finally working -- %@",[secondScene .userData objectForKey:@"score"]);
//The secondScene will scale to fit the whole SKView
secondScene.scaleMode = SKSceneScaleModeAspectFill;
//present the secondScene
[self.scene.view presentScene: secondScene transition:reveal];
* WBMGameEndsScene是我的第二个。我在Xcode中用“File - New File ...”创建了它:SKScene。它将包含稍后显示的userData。
2.2。 secondScene
//secondScene.m ( ex. in my :"@implementation WBMGameEndsScene")
下一行代码检查是否正确添加了值:
-(void)didMoveToView:(SKView *)view
{
NSLog(@"-- -(void)willMoveFromView:(SKView *)view --");
NSLog(@"Working score is : %@",[self.userData valueForKey:@"score"]);
NSLog(@"Working score is : %@",[self.userData objectForKey:@"score"]);
}
控制台输出为:
2014-03-12 15:29:06.804 AppTest[4841:60b] -(id)initWithSize:(CGSize)size
2014-03-12 15:29:06.806 AppTest[4841:60b] scoreLabel
2014-03-12 15:29:06.812 AppTest[4841:60b] successMessage
2014-03-12 15:29:06.815 AppTest[4841:60b] Is it finally working -- 6
2014-03-12 15:29:06.815 AppTest[4841:60b] -- -(void)willMoveFromView:(SKView *)view --
2014-03-12 15:29:06.816 AppTest[4841:60b] Working score is : 6
2014-03-12 15:29:06.816 AppTest[4841:60b] Working score is : 6
如果我出错了,请纠正我:)。 规格:iOS 7.0,Xcode版本5.1(5B130a),OS X 10.9.2
答案 3 :(得分:0)
你在哪里/如何在场景之间转换?如果你能显示你创建新场景的代码,那将有所帮助。我可能会忽略问题的重点,但如果您有某种“场景管理器”/导航器,那么只需将分数暂时保存在本地变量中并将其传递到新场景中。
答案 4 :(得分:0)
Apple文档声明userData是在Sprite Kit Best Practices
中存储节点特定数据的方法使用节点上的userData属性来存储特定于游戏的数据,尤其是在您没有实现自己的子类时。
因此,我会接受@ doctorBroctor的答案作为本地使用Sprite Kit的正确答案。
但是,您应该记住在设置值之前初始化目标节点的userData,因为@ LearnCocos2d在this回答中指出。您可以在要转换到的SKScene子类的initWithSize:方法中执行此操作。
答案 5 :(得分:0)
// First Scene
NSUserDefaults.standardUserDefaults().setInteger(12345, forKey:"SCORE")
// Second Scene
if let myScore: AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("SCORE") {
println(myScore)
finalScore = myScore as IntegerLiteralType
}