在我的GameScene中,我有一个名为“得分”的变量,我想在MenuScene中使用它来显示最新得分。我已经用UserDefaults尝试过了,但我并没有真正理解它并且它不起作用。有人可以告诉我如何声明得分变量,以便我可以在其他场景中使用它,如果有人能告诉我如何保存变量以便我可以保存高分,那也很好。
我试过这个:
GameScene:
let userDefaults = UserDefaults.standard // Before didMove func
UserDefaults.setValue(score, forKey: "Score") // in gameOver func
MenuScene:
var score = SKLabelNode()
var scoreNumber = UserDefaults.standard.integer(forKey: "Score")
如果我运行游戏,它会加载MenuScene,我可以按下播放,然后进入GameScene。如果我死在GameScene中,游戏崩溃并且我收到此错误:“因未捕获的异常而终止应用程序'NSUnknownKeyException',原因:'[setValue:forUndefinedKey:]:此类不是键值编码兼容的关键分数'。“
答案 0 :(得分:1)
如果您正确使用用户默认值,您应该能够从任何对象读取和写入,因为UserDefaults.standard
是单身。这些方面应该有用:
private let scoreUserDefaultsKey = "scoreUserDefaultsKey"
func save(score: Int)
{
let userDefaults = UserDefaults.standard
userDefaults.set(score, forKey: scoreUserDefaultsKey)
userDefaults.synchronize()
}
func read() -> Int
{
return UserDefaults.standard.integer(forKey: scoreUserDefaultsKey)
}
class GameScene1: SKScene {
func saveFromGameScene1(score: Int) {
save(score: score)
}
}
class GameScene2: SKScene {
func readFromGameScene2() -> Int {
return read()
}
}
说你可以拥有一个更好的架构来实现一个ScoreManager对象并将它注入游戏场景中(而不是对单例有很多依赖)。
<强>更新强>
刚看到你的代码片段。您需要使用set
,而不是setValue
。 setValue
不是UserDefaults的方法,而是KVO的NSObject方法。
func setValue(_ value:Any?,forKey key:String)
将给定键指定的接收器的属性设置为给定 值。如果key标识了一对一关系,则关联该对象 由值指定给接收者,与先前相关的无关 对象,如果有的话。给定一个集合对象和一个密钥 识别多对多关系,关联包含在其中的对象 收集到接收器,如果没有先前相关的对象 有任何。
setValue:forKey:uses的搜索模式在Accessor中描述 “键值编码编程指南”中的搜索模式。
在引用计数环境中,如果实例变量是 直接访问,保留值。
这不是你想要的;)
在致电set
之后,请务必致电synchronize
以确保该值立即存储。
我希望这会有所帮助。
答案 1 :(得分:0)
您可以将import SpriteKit
移至全局,即将其从class GameScene
移除,并通过在NSUserDefault
和let defaults = NSUserDefaults()
var highScoreNumber = defaults.integerForKey("highScoreSaved")
If gameScore > highScoreNumber{
highScoreNumber = gameScore
defaults.setInteger(highScoreNumber, forKey: "highScoreSaved")
}
之间移动来实现通用。之后,您可以像其他人建议的那样使用 public class Employee{
String firstname;
String lastname;
//setters and getter goes here
}
。
更新
好吧,对于我的GameOver场景,我通常在课堂上做这样的事情
public class GsonRequest<T> extends Request<T> {
public final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Response.Listener<T> listener;
private final Object dataIn;
/**
* Make a GET request and return a parsed object from JSON.
*
* @param url URL of the request to make
* @param clazz Relevant class object, for Gson's reflection
* @param headers Map of request headers
*/
public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
this.dataIn = null;
}
public GsonRequest(String url, Object dataIn, Class<T> clazz, Map<String, String> headers,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.dataIn = dataIn;
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
@Override
public byte[] getBody() throws AuthFailureError {
return gson.toJson(dataIn).getBytes();
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
}
您可以在MenuScene中执行此操作。
答案 2 :(得分:0)
如果你想在差异viewcontroller中使用动态变量。并且一直使用它。你在Appdelegate中创建。
在你的AppDelegate.swift
中 var yourVariableName: Any = "Value"
当您想要使用它或更改它时。你
let app: AppDelegate = UIApplication.shared.delegate as! AppDelegate
print(app.youVariableName)
如果您想观察变量值的变化并做一些动作。您可以设置didSet功能。
var yourVariableName: Any = "VALUE" {didSet{observeValueChangeFunction()}}
func didSet{observeValueChangeFunction() {
print("New value: \(yourVariableName)")
}
答案 3 :(得分:0)
我认为您不应该使用UserDefaults来执行此操作,
我想问你的第一个原因是,如果有人关闭应用程序,也许他们在玩游戏时会杀死应用程序,你是如何与得分达成交易的?
当然,你不应该保留这个分数,对吧?或者你应该缓存游戏的所有数据,然后当玩家再次进入游戏时,你可以回到应用程序关闭时的状态。但我认为这样做太复杂了。
所以我认为你应该把这个分数全局或更容易控制,这只是将分数从GameScene
传递给可能被称为ResultScene
的分数。
我认为你的游戏有这些场景:
LoginScene
MapScene
GameScene
ResultScene
RankScene
所以你只需实时使用GameScene
和ResultScene
中的分数,所以你只需在GameScene
中执行此操作:
var score : Int/CGFloat = 0;
func enterFrame(){
//if they got the goal, then
// score = score + 1 or much more;
}
func gameOver(){
let resultScene = ResultScene(score: score);
// or you could just create the empty ResultScene, and pass the score via a public func of the ResultScene
}
然后您可以在ResultScene
中显示分数。
如果您只是制作无服务器游戏,则应将分数保留在UserDefaults
或CoreData
或SQLite
等。
然后你可以在一些关于history records
的场景中显示分数。