Triggering Animations and States
There are two types of animations that can be played,
To simplify this guide, I will cover the triggering of the animation first for both short term and long term animations, then cover how to actually play the animation using both Legacy and Mecanim animation systems.
Triggering the Animation
An example copy of a script is available in Atavism project in Assets/Scripts directory.
Looking at that file you will see the Update() function some input checks. These will run one of the functions when the matching key is pressed.
Short Term
Short term animations are done via the Coordinated Effect system. This is because they do not need to be saved to the character, they only need to be shown to other players nearby while the animation plays. In the example script there is the following function:
public void PlayWave() { Dictionary<string, object> props = new Dictionary<string, object> (); props.Add ("coordEffect", "PlayWaveAnimation"); // Put name of Coord Effect Prefab to play here props.Add ("hasTarget", false); NetworkAPI.SendExtensionMessage (ClientAPI.GetPlayerOid(), false, "ao.PLAY_COORD_EFFECT", props); }
The code inside the function sends a command to the server telling it to play a coordinated effect with the name “PlayWaveAnimation”. The server will then send down a message to all players near the player who sent the command telling the client to play the specified Coordinated Effect. To play a different animation, just create a new Coordinated Effect and create a copy of that example function, but changing the name of the “
To create a new Coordinated Effect, go into the Resources/Content/CoordinatedEffects folder and duplicate one of the existing prefabs. I recommend duplicating the PlayWaveAnimation prefab as it is already set up with the correct component, all that needs
Long Term
For this tutorial, I have decided to create a new player property called “
public void PlayLieDown() { // First check if the player is already lying down bool playerLyingDown = false; if (ClientAPI.GetPlayerObject().PropertyExists("currentAnim")) { if ((string)ClientAPI.GetPlayerObject().GetProperty("currentAnim") == "lie") playerLyingDown = true; } if (playerLyingDown) { // Player is lying down so reset anim back to normal NetworkAPI.SendTargetedCommand (ClientAPI.GetPlayerOid(), "/setStringProperty currentAnim null"); } else { // Player is not lying down so set anim to lie NetworkAPI.SendTargetedCommand (ClientAPI.GetPlayerOid(), "/setStringProperty currentAnim lie"); } }
To do this for other animations, the bare minimum is to replace the two instances of the
Now the other tricky part to this is to handle state interruptions. That is to say, what happens if the player moves while lying down? Should it automatically clear the state back to null? This will be covered in the sections below.
Playing the Animations
Legacy
The Legacy system is much harder to add new animations to as it requires code changes to make it work. When selecting a mob prefab that uses the “Atavism Legacy Animation Mob Controller” you will see a list of animation properties such as “Idle Animation” and “Walk Animation”. That mob controller file will need to be edited to include new properties for your new animations, then some code added to work out when those animations should be played.
Open up the AtavismLegacyAnimationMobController3D.cs file and near the top of the file add new lines for your new animations after line 15:
public AnimationClip mountAnimation;
for example, for the new Wave and Lie animations you would put:
public AnimationClip waveAnimation; public AnimationClip lieAnimation;
From here the code will be a little bit different based on short term or long term animations.
Short Term
To get
if (animationName == "attack_normal" || animationName == "Attack") { overrideAnimation = unarmedAttackedAnimation; }
To add a new animation, such as the wave one from above, add in the following code string after it:
else if (animationName == "Waving") { overrideAnimation = waveAnimation; }
My function now looks like this:
I got the “Waving” from the Animation Name property on the PlayWaveAnimation Coordinated Effect shown above. The “waveAnimation” is
Long Term
As we are using a new player property (called “
public void HandleCurrentAnim (object sender, PropertyChangeEventArgs args) { // Get the value of the currentAnim property string currentAnim = (string)AtavismClient.Instance.WorldManager.GetObjectNode(oid).GetProperty("currentAnim"); // Check if the value is "null", if so, set the overrideAnimationExpires time to -1 to reset it if (currentAnim == "null") { overrideAnimationExpires = -1; } else { // Otherwise call the PlayAnimation function with a very large amount of time PlayAnimation(currentAnim, float.MaxValue); } }
Note you will need to follow the steps in the “Short Term” section just above to convert the animation name to an Animation object.
Finally, this property handler function needs to be registered so it will run when the
GetComponent<AtavismNode>().RegisterObjectPropertyChangeHandler("currentAnim", HandleCurrentAnim); // If the currentAnim property already exists, run the handler now if (GetComponent<AtavismNode>().PropertyExists("currentAnim")) { HandleCurrentAnim(null, null); }
So it will now look like:
Note that you will need to now add in your AnimationClips to the Animation and AtavismLegacyMobController3D components on your mob prefab.
Clearing CurrentAnim when Moving
At the end of the Update() function you can do a check to see if the players
if (isPlayer && controller.velocity.sqrMagnitude > 0.1 && ClientAPI.GetPlayerObject().PropertyExists("currentAnim")) { if ((string)ClientAPI.GetPlayerObject().GetProperty("currentAnim") != "null") NetworkAPI.SendTargetedCommand (ClientAPI.GetPlayerOid(), "/setStringProperty currentAnim null"); }
To help you place it in the right spot, here is how mine looks: