使用 UserDefaults 在 SKScenes 之间传递字符串
Passing a string between SKScenes using UserDefaults
在我用 Swift 开发的游戏中,我希望玩家能够在类似商店的场景中选择背景,从而更改每个 SKScene 的背景。我正在尝试使用 UserDefaults 来完成此操作,但由于某种原因它无法正常工作。下面是Shop场景的重要代码(我去掉了不相关的代码):
import SpriteKit
class ShopScene: SKScene {
var backNumber = 90
var backRemainder = 0
var background = SKSpriteNode()
var backName:String = "back1"
override func didMove(to view: SKView) {
background.texture = SKTexture(imageNamed: "\(backName)")
background.size = self.size
self.addChild(background)
let nextButton: NButton = NButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: nextAction)
addChild(nextButton)
let selectButton: SButton = SButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: selectAction)
addChild(selectButton)
}
func selectAction() {
UserDefaults.standard.set(backName, forKey: "backSaved")
let sceneToMoveTo = MainMenuScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let sceneTransition = SKTransition.fade(withDuration: 0.4)
self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)
}
func nextAction() {
backNumber += 1
backRemainder = backNumber % 3
switch backRemainder {
case 0:
backName = "back1"
case 1:
backName = "back2"
case 2:
backName = "back3"
default:
backName = "back1"
}
background.texture = SKTexture(imageNamed: "\(backName)")
}
}
如您所见,当按下 select 按钮时,返回名称被保存。现在,这是主菜单场景的相关代码:
Import SpriteKit
class MainMenuScene: SKScene {
var backName = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "\(backName)")
background.size = self.size
self.addChild(background)
当按下 'Select' 按钮时,您应该转换到主菜单场景并看到背景是您 select 编辑的那个。但是,当我 运行 这个时,我在白色背景中得到了一个红色的 X。我以前曾使用 UserDefaults 保存分数,但我不明白为什么它在这种情况下不起作用。关于如何使用 UserDefaults 在 SKScenes 之间传递字符串的任何想法?我做错了什么吗?
注意:虽然 Knight0fDragon 的答案被标记为正确,但他的答案适用于在场景之间传递字符串而不是永久保存该值。如果您想传递值并保存它,请查看我的回答。
显然,backName 表现为可选的,因为它可以没有值,因此为 nil。为了使我的代码正常工作,我对 Shop Scene 进行了以下更改:
import SpriteKit
class ShopScene: SKScene {
var backName:String? = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
if backName != nil {
backName = UserDefaults.standard.string(forKey: "backSaved")
} else {
backName = "back1"
}
background.texture = SKTexture(imageNamed: "\(backName!)")
self.addChild(background)
以及对主菜单场景的这些更改:
import SpriteKit
class MainMenuScene: SKScene {
var backName:String? = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
if backName != nil {
backName = UserDefaults.standard.string(forKey: "backSaved")
} else {
backName = "back1"
}
let background = SKSpriteNode(imageNamed: "\(backName!)")
self.addChild(background)
我建议不要这样做 UserDefaults
,这是为了满足您的应用程序的偏好。而是使用 userData
func selectAction() {
let sceneToMoveTo = MainMenuScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
sceneToMoveTo.userData = sceneToMoveTo.userData ?? NSMutableDictionary() //This lets us ensure userdata exists
sceneToMoveTo.userData!["backSaved"] = backName
let sceneTransition = SKTransition.fade(withDuration: 0.4)
self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)
}
然后实现它:
import SpriteKit
class MainMenuScene: SKScene {
lazy var backName:String = {return self.userData?["backSaved"] as? String ?? "back1"}() //This allows us to load backName at the time it is needed, or assign back1 if doesn't exist
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: backName)
self.addChild(background)
请注意,我不确定是不是?需要字符串,不用它试试,看看 Swift 是否可以推断出来
在我用 Swift 开发的游戏中,我希望玩家能够在类似商店的场景中选择背景,从而更改每个 SKScene 的背景。我正在尝试使用 UserDefaults 来完成此操作,但由于某种原因它无法正常工作。下面是Shop场景的重要代码(我去掉了不相关的代码):
import SpriteKit
class ShopScene: SKScene {
var backNumber = 90
var backRemainder = 0
var background = SKSpriteNode()
var backName:String = "back1"
override func didMove(to view: SKView) {
background.texture = SKTexture(imageNamed: "\(backName)")
background.size = self.size
self.addChild(background)
let nextButton: NButton = NButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: nextAction)
addChild(nextButton)
let selectButton: SButton = SButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: selectAction)
addChild(selectButton)
}
func selectAction() {
UserDefaults.standard.set(backName, forKey: "backSaved")
let sceneToMoveTo = MainMenuScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
let sceneTransition = SKTransition.fade(withDuration: 0.4)
self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)
}
func nextAction() {
backNumber += 1
backRemainder = backNumber % 3
switch backRemainder {
case 0:
backName = "back1"
case 1:
backName = "back2"
case 2:
backName = "back3"
default:
backName = "back1"
}
background.texture = SKTexture(imageNamed: "\(backName)")
}
}
如您所见,当按下 select 按钮时,返回名称被保存。现在,这是主菜单场景的相关代码:
Import SpriteKit
class MainMenuScene: SKScene {
var backName = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "\(backName)")
background.size = self.size
self.addChild(background)
当按下 'Select' 按钮时,您应该转换到主菜单场景并看到背景是您 select 编辑的那个。但是,当我 运行 这个时,我在白色背景中得到了一个红色的 X。我以前曾使用 UserDefaults 保存分数,但我不明白为什么它在这种情况下不起作用。关于如何使用 UserDefaults 在 SKScenes 之间传递字符串的任何想法?我做错了什么吗?
注意:虽然 Knight0fDragon 的答案被标记为正确,但他的答案适用于在场景之间传递字符串而不是永久保存该值。如果您想传递值并保存它,请查看我的回答。
显然,backName 表现为可选的,因为它可以没有值,因此为 nil。为了使我的代码正常工作,我对 Shop Scene 进行了以下更改:
import SpriteKit
class ShopScene: SKScene {
var backName:String? = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
if backName != nil {
backName = UserDefaults.standard.string(forKey: "backSaved")
} else {
backName = "back1"
}
background.texture = SKTexture(imageNamed: "\(backName!)")
self.addChild(background)
以及对主菜单场景的这些更改:
import SpriteKit
class MainMenuScene: SKScene {
var backName:String? = UserDefaults.standard.string(forKey: "backSaved")
override func didMove(to view: SKView) {
if backName != nil {
backName = UserDefaults.standard.string(forKey: "backSaved")
} else {
backName = "back1"
}
let background = SKSpriteNode(imageNamed: "\(backName!)")
self.addChild(background)
我建议不要这样做 UserDefaults
,这是为了满足您的应用程序的偏好。而是使用 userData
func selectAction() {
let sceneToMoveTo = MainMenuScene(size: self.size)
sceneToMoveTo.scaleMode = self.scaleMode
sceneToMoveTo.userData = sceneToMoveTo.userData ?? NSMutableDictionary() //This lets us ensure userdata exists
sceneToMoveTo.userData!["backSaved"] = backName
let sceneTransition = SKTransition.fade(withDuration: 0.4)
self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)
}
然后实现它:
import SpriteKit
class MainMenuScene: SKScene {
lazy var backName:String = {return self.userData?["backSaved"] as? String ?? "back1"}() //This allows us to load backName at the time it is needed, or assign back1 if doesn't exist
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: backName)
self.addChild(background)
请注意,我不确定是不是?需要字符串,不用它试试,看看 Swift 是否可以推断出来