This hasn't been an easy task by any means, though. Given that the tail functioned in some pretty heinous ways (if it looks polished enough move on to the next thing), and that the tail is the better half of all five movement schemes, getting everything going has been a challenge.
Setting Up
We'll start by defining these four variables, publicly modifiable in the editor. These will control the rate at which our movement schemes move. |
The function that lets us switch movement schemes at runtime. When the previous movement type != the current one, we switch contexts to the new one. |
Movement_Behavior abstract class
Now that everything's instantiated, we can get the head moving. I'm only going to post about the base class that our behaviors inherit from:
abstract public class Movement_Behavior : MonoBehaviour
Since all of our movement schemes always move forward (unless paused), we can always move forward in the direction we are facing:
head.velocity = head.transform.forward * mForwardSpeed;
For now, we'll separate the forward motion from the rotation, and just focus on making the tail nodes smoothly look at the node in front of it. A simple LookAt vector can make the dragon function, but making it smoothly function is a bit more difficult.
AngleSigned is a function which returns the angle between two vectors as a value between [-180, 180]. mRigidbody is the dragon's head's Rigidbody component |
Tail_Behavior
In order for the tail nodes to not slowly separate from each other, we use about the same RotateTowards function above. I've found that if the angular velocity of the tail is shorter than that of the head, then the tail will peel apart. This is because the magnitudes of the tail node velocities are the same, but the directions are not, so this slightly-off direction will in a sense steal some of the velocity's speed. These effects are amplified the further away a tail node is from the head.
We tell each tail node about the node in front of it, like a forward linked list. That parent node's position is used as the seekPos parameter we passed into the function above. Here's a snippit from that:
And that's the core of how the dragon moves!