Home > Enterprise >  Dynamic name with SKAction
Dynamic name with SKAction

Time:06-20

I have SKActions defined in my class, eg:

let CSound = SKAction.playSoundFileNamed("C3.mp3", waitForCompletion: false)
let DSound = SKAction.playSoundFileNamed("D3.mp3", waitForCompletion: false)

I want to be able to call a function to play sounds, and I want to adjust the name dynamically, like this:

func playSound(noteName: String) {

    print(noteName) // "C"
    var name = noteName   "Sound"
    print(name) // "CSound"
        
    run(SKAction(named: name)!)
        
}

This causes a fatal error on the run(SKAction(named: name)!) line:

Fatal error: Unexpectedly found nil while unwrapping an Optional value

Why is this? How is it nil? The variable name has the value CSound, and an SKAction does exist with that name. How can I use a dynamic name like this?

CodePudding user response:

You can store the sounds in a dictionary:

let sounds = [
    "C": SKAction.playSoundFileNamed("C3.mp3", waitForCompletion: false),
    "D": SKAction.playSoundFileNamed("D3.mp3", waitForCompletion: false),
]

let sounds = Dictionary(uniqueKeysWithValues:
    ["C", "D"]
        .map { ($0, SKAction.playSoundFileNamed("\($0)3.mp3", waitForCompletion: false)) }
)

If there are many sounds and you don't want to repeat playSoundFileNamed too many times, you can do a map:

let sounds = Dictionary(uniqueKeysWithValues:
    ["A", "B", "C", "D", "E", "F", "G"]
        .map { ($0, SKAction.playSoundFileNamed("\($0)3.mp3", waitForCompletion: false)) }
)

Then you can access it like this:

func playSound(noteName: String) {
    if let action = sounds[noteName] {
         run(action)
    } else {
        // there is no sound with the given name...
    }
}

The SKAction(named:) creates an SKAction from a .sks file in your app's bundle. You can add such a file in Xcode by doing File -> New -> File... -> SpriteKit Action. You pass in the file name as the parameter, and it creates the action encoded in the file.

  • Related