Cutscenes are a labor of love, so it is hard accepting that some people just don’t care. That story that took months to bring together may be amazing to you, but to others it is just an inconvenience. So, for that reason, we have to make cutscenes skippable. However, I didn’t want to just settle at skipping the entire scene. I wanted to also make it skimmable for the speed readers, or those who are mildly interested.
Watching the video above, you can see how skimmable cutscenes could bring about all sorts of complications. The worst of those challenges is how to handle placement of the camera. Take this example:
- 1. Camera starts zooming to character A
- 2. Dialogue A
- 3. Pan camera to character B
- 4. Dialogue B
How would you solve the problem if the user skips step 1 and 2? My first attempt was to store information inside of step 4 that contained the expected camera position. Then, if the camera wasn’t at that position, immediately jump it there. That solution worked just fine, but it caused me to duplicate the information. Step 3 and 4 both had to know the ending position of the camera.
An alternate solution to this problem is to use
timingFunction. When an action is running, it will immediately fast forward to the end when the
timingFunction returns 1. For example:
Now that we know how to end an action, the next step is to make it dynamic. In my findings,
timingFunction can not be altered once the action starts running. So, I had to make a class for each cutscene action, and use a member variable to determine when it should finish.
In the code above, the timing function will work as expected until the member variable
finishEarly is set to true. Once set, the
SKAction will instantly run to completion. This can be taken much further to accommodate sound, in game items, and other events. I plan to break it down one a line by line basis to give granular control. But, we’ve got a good starting point for now. The example below shows my original scene being skimmed, which saves 5 seconds off of reading time.