Dynamic Runtime Animation

Problem:
Dynamic animations based upon the speed of movement.

Assets used:
Futuristic, floating basketball hoop, hung in air by thrusters

First the hoop rotates a certain angle to point its thrusters in the desired move direction. Before this rotation finishes, it starts moving.
Towards the end of the movement, it reverses rotation direction to point the thrusters in the opposite direction to simulate stopping force. This rotation should end before the hoop arrives at the final location.
Finally, when the hoop finishes the movement, it rotates back to the idle position.

Flowchart for reference:

Movement Flowchart
Movement Flowchart

Naturally, the hoop’s speed should start slow, gain speed as it moves, then slow down towards the end. The rotations should do the same, to simulate real world movement.

Each movement cycle needs a certain angle to rotate based upon desired speed, which is based upon move distance. If the hoop moves a very small amount, it only needs to rotate a small angle to accomplish this.

My initial thought was to use Unity’s Animation.SetCurve, but that got real messy real quick. It seemed like I was playing with something I shouldn’t. Also, the transform of the object cannot be moved if an animation is applied to the transform.

The alternative: Coroutines!

First the rotation animation. Since the only difference between the 3 rotations is the angle, I just need one method which takes the angle as a parameter:

This method will rotate the object within a specific time. If you look at the flowchart, you’ll see the object movement will start during the initial rotation. Therefore we need to implement a flag to tell a movement script to begin movement. This can simply be a bool which a movement script constantly checks to see if it’s true. We’ll call this startMoving. Another variable we need is a float that represents the time the startMoving bool should be turned on. This can be called startMovementPosition. Finally, we implement it by placing a if statement in the while statement:

Since each of these steps in the movement process are all associated with the same, singular, movement, it makes sense to be in a Finite State Machine. Explanation of this is beyond the scope of this post, but there are plenty of resources out there on the internet.
A state machine contains individual steps, which are represented by each box in the flowchart. In each step, an enter method is initially run once, then an execute method is run continuously, and finally an exit method is run when the state is changed:

For the first initial rotation:

Which is implemented like:

Now the Moving State:

And again, the HoopLateralMovementController:

The CheckReadyForReverseRotation method that the MovingState continuously checks is key for the animation to behave, and thus look correct. The timeRemaining is the time left in the object movement. The rotationTimeNeeded is the amount of time needed to perform the reverse rotation. Since the reverse rotation needs to finish before the movement finishes, the timeRemaining is multiplied by 0.9f, which is 90% of the time. Then, if the new timeRemaining is less than or equal to the rotation time needed, the reverse rotation is started. The rotation will then finish right before the movement finishes.

The ReverseRotate state:

And subsequent methods in HoopLateralMovementController:

In the HoopRotation script:

Like the startMoving flag set in the initial rotation, a similar flag called currentlyRotating in the movement coroutine is set to false, which signals the final rotation to trigger.

Leave a Reply

Your email address will not be published. Required fields are marked *