Передача строки между SKScenes с использованием UserDefaults
В игре, которую я разрабатываю со Swift, я хочу, чтобы игрок мог выбирать фон в сцене, похожей на магазин, и, таким образом, менять фон каждой сцены SKScene. Я пытаюсь сделать это с помощью UserDefaults, но по какой-то причине это не работает. Вот важный код Shop Scene (я удалил нерелевантный код):
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)")
}
}
Как видите, при нажатии кнопки выбора назад имя сохраняется. Теперь это соответствующий код сцены главного меню:
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)
Когда кнопка "Выбрать" нажата, вы должны перейти в главное меню сцены и увидеть, что фон является тем, который вы выбрали. Тем не менее, я получаю красный X на белом фоне, когда я запускаю это. Ранее я работал с UserDefaults для сохранения результатов, но не могу понять, почему это не работает в этом случае. Любая идея о том, как передавать строки между SKScenes с помощью UserDefaults? Я делаю что-то неправильно?
ПРИМЕЧАНИЕ. Хотя ответ Knight0fDragon помечен как правильный, его ответ работает для передачи строки между сценами, но не для постоянного сохранения этого значения. Если вы хотите передать значение и сохранить его, проверьте мой ответ.
2 ответа
Я бы порекомендовал не делать 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 сделать это
По-видимому, 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)