In this task we extend our current project with a playback functionality. More precisely it will be more of a “macro” like functionality you would usually find in text editors. The player is able to record a set of movements and then replay these multiple times. To complete this task implement the following classes and methods.
Create new commands:
- RecordCommand - Binds the input button to start or stop recording. This command should not be recorded.
- PlayCommand - Binds the input button to start or stop playing the macro. This command should not be recorded.
- RecordedCommand - The extrinsic state of a recorded command. This decorates any existing or future commands with additional time data.
- Optional: An abstract RecorderInputCommand in heritance chain. Use this to group together RecordCommand and PlayCommand. This will clean up the code when checking which commands to record.
Create a play method for InputHandler
- Starts macro if macro is currently not playing
- Stops macro if macro is currently playing
- Starts macro and stops recording if recording is currently in progress.
Create a record method for InputHandler
- Starts recording if recording is not in progress.
- Stops recording if recording is in progress.
Create a playMacro coroutine method for InputHandler
A coroutine that will be able to replay a collection of RecordedCommands.
What are coroutines?
Coroutines are methods that can be execution concurrently over multiple frames of the game. An example of this type of method is the private IEnumerator Walk(Vector3, float) method in GridMovement. Note that these coroutines are part of Unity and not C# system libraries. There are other coroutine libraries available though.
How to create a coroutine?
- Define the return type of the method as IEnumerator. (See GridMovement.Walk(Vector3, float))
- When returning from the method use yield return instead.
- Start the coroutine in a MonoBehaviour with the StartCoroutine( StartedMethod(parameters) ) method. See the GridMovement.Walk(Vector3) method. Note that StartCoroutine is a public method.
What are some of the more frequen yield values for a coroutine?
- yield return null; - The coroutine will be resumed in the next frame from the next line. Very useful inside loops.
- yield break; - The coroutine will be stopped.
- yield return AnotherIEnumeratorMethod(parameters); - The other coroutine will be started. When the other coroutine finishes, the first method is resumed from the following line.
- yield return new WaitForEndOfFrame(); - The couroutine will be continued at the very end of frame right before rendering. Useful for camera repositioning or cleanup.
- yield return new WaitForSeconds(n); - Continues after n seconds. This uses scaled time so coroutine would not continue when game is paused. For realtime seconds use WaitForSecondsRealtime.
- yield return new WaitUntil( delegate that returns bool ); - Continues when the delegate returns true. Also has an opposite WaitWhile.
Optional challenge:
Turn the macro feature into replay by either saving or recreating the starting state. Consider the differences and benefits of either approach. Which would be better extendible? What about performance?