Has exit time unity là gì

Indeed, a clip is just a sheet containing informations on how to animate an object. It’s never called or triggered.

Enter the “Animator”.

An “Animator” is a component that you put on an object, which itself references an “Animator Controller”. The “Animator Controller” is a state machine that manages all the animations of an object and the relations between them.

In this chapter, we are going to add the “Boss” object into the scene and animate it. By doing so, we will learn how to use the “Animator”. Plus, we will have some scripts to add in order to have a proper behavior for this special character: stop the level, create a pattern for the shots and trigger the animations.

Warning: this part of the tutorial has not been updated to Unity 5.

Animator

You may have seen that your “Boss” object you were working on had automatically received a new component: an “Animator”.

At the same time, you may also have seen that a new file was added to your “Animations” folder, named just like your object. It’s an “Animator Controller”.

Now, observe the “Controller” property of your “Animator” component:

The file “Boss” is the controller. You can check that by clicking onto the controller field — it will highlight the linked file:

This controller is where we will define how and when Unity should play the animation clips.

Basically, the “Animator” component is simply a link between an object and an “Animator Controller”. This component can be retrieved and manipulated through the code.

If your “Boss” prefab has no “Animator” component, add it manually and drag the “Boss” controller inside the property.

Options: the “Animator” component has some other options. The “Apply Root Motion” should probably be disabled when using the animations the way we do in this tutorial. Yet, it doesn’t matter here because we have a very simple object with no gravity.

Inside an animator

As it was not confusing enough, we need to open the window called “Animator” [and not “Animation” this time].

You can double click on the controller file [“Animations/Boss”] to open the controller, or you can find it in the “Window” menu:

You should get something like this:

You can see that we have some states [the rectangles] created automatically with our clips, plus a special one called “Any State”.

Remember when you used the “Create New Clip” button of the “Animation” view ? Unity was in fact adding a state in the controller of the object, linked to the animation file you had created.

Click on each state of the animator and rename them to remove the “Boss_” prefix:


An “Animator Controller” is a state machine. Each state can be an animation, and you can define transitions between them.

A transition tells to Unity when and why it should move from a state to another.

In this image, we have created a link between two states. In order to animate the object with the “Hit” animation, we have to be in the “Idle” state first.

We will focus a bit more on transitions in a moment. For now, let’s look at the three different types of states.

1. Default state

The orange state is the default one: the initial state when the game is launched.

In this case, the “Idle” state is the default one [if it’s not, right click and “Set As Default”].

That means that when the game is started, the “Boss” object will automatically play the “Idle” animation [indefinitely if “Loop Time” is enabled in the animation “Inspector” — as it should be for this tutorial].

2. “Any State”

The green state, called “Any State”, is a special case.

It’s a good way to simplify a state machine. It represents [as its name says so well] any state at a given time. In our “Boss” state machine, this state is, at the same time, the “Idle”, the “Hit” and the “Attack” states.

Let’s explain this with a few examples.

Imagine we have this state machine:

In order to “Jump”, you have to “Walk” first, then “Run” and FINALLY “Jump”. It means that the “Jump” animation won’t be played unless your object is in the “Run” state before. If you never “Run”, you will never “Jump”.

It’s not ideal, is it? We should be able to “Jump” when we “Walk” too!

Okay, let’s try this:

Great, we are now able to “Jump” from the “Walk” and “Run” states. However, if you add a few more states, you will need to create a lot of transitions to “Jump” from every state.

The solution is to use “Any State”:

With this state machine, any state can transition to a “Jump” state. Perfect, no?

3. Normal state

The gray states are the normal ones, holding zero or one animation.



On the bottom left corner of the “Animator” view, you can find a parameters list. These parameters are used for the conditions of the transitions. More on that below.

[Contrary to the image above, it should be empty currently]


On the top left, you can see the layers. This is a way to have multiple state machines for one object. We will not use this feature in this tutorial.


And finally, the button “Auto live Link” on the top right is a cool Unity feature which allows you to see in real-time which state is currently played. Leave it enabled.

Adding parameters

A parameter is a value or a trigger for our state machine. Later, we will use these in the conditions of our transitions.

A parameter has 4 types available:

  • Int — simple integer number.
  • Float — simple float number.
  • Booltrue or false value.
  • Trigger — a flag which stays enabled until it is used. Then, it becomes unchecked.

Numbers are interesting for special use cases like an horizontal or vertical speed. You may want a different animation for walk or run, but they both rely on the movement speed of the player, which could be a parameter.

For our game, let’s add two new parameters:

  1. “Hit”, a trigger
  2. “Attack”, a boolean

[Sadly, the editor doesn’t differentiate triggers from booleans visually]

Now, let’s see why we need them.

Transitions

A transition is a link between two states, telling to the state machine how we go from one to another.

1. “Idle to Attack”

To create a transition, make a right click on the source state.

Let’s do it for “Idle to Attack” first:

  1. Right click on “Idle” state.
  2. Select “Make transition”:

  1. Now click on the destination state:

And that’s it!

You can select the transition by clicking on the link. The “Inspector” will reveal a lot of interesting parameters, especially the entry conditions:

Exit Time: the “Exit Time” condition is the default condition for a transition. It means that the transition is valid [and can be executed] when the source animation is over.

This is what we will edit. Change “Exit Time” for the “Attack” parameter that we have defined earlier.

This condition means “If

  private Animator animator;

  // ...

  void Awake[]
  {
      // ...
      animator = GetComponent[];
      //...
  }
0 is true then play “Attack” animation”.

The same way, add a transition between “Attack” and “Idle” with the condition “

  private Animator animator;

  // ...

  void Awake[]
  {
      // ...
      animator = GetComponent[];
      //...
  }
0 is false”.

It means “If

  private Animator animator;

  // ...

  void Awake[]
  {
      // ...
      animator = GetComponent[];
      //...
  }
0 is false then stop “Attack” animation and go back to Idle”.

You can observe that we had to define both transitions. Otherwise, the state machine would not have come back to the “Idle” state after an attack.

We will do nearly the same for the Idle animation.

2. “Idle to Hit”

Remember the “Any State” special state? We are going to use it now.

Make two new connections:

  1. “Any State” to “Hit”, condition
      private Animator animator;
    
      // ...
    
      void Awake[]
      {
          // ...
          animator = GetComponent[];
          //...
      }
    
    6.
  2. “Hit” to “Idle”, condition
      private Animator animator;
    
      // ...
    
      void Awake[]
      {
          // ...
          animator = GetComponent[];
          //...
      }
    
    7.

If the trigger “Hit” is set, we play the animation “Hit” once and go back to “Idle”.

“Any State” is useful here because

  private Animator animator;

  // ...

  void Awake[]
  {
      // ...
      animator = GetComponent[];
      //...
  }
6 can be triggered when the “Boss” is “Idle” or in an “Attack”. Instead of defining two relations, we just use “Any State”.

Trigger: as you can see, when you use a trigger, you don’t have to specify a value. Indeed, a trigger is just a way to tell to the state machine “If

  private Animator animator;

  // ...

  void Awake[]
  {
      // ...
      animator = GetComponent[];
      //...
  }
9 Then transition”.

Final graph

Our animator graph should now look like that:

The last thing we need is some code to make it react in-game [the parameters are never triggered currently, so the animator will stay on “Idle”].

Animator graph: creating a graph in the animator is not an exact science. Depending on your code implementation, what you want to achieve or a precise sequence of actions, you may want to proceed differently. For example, in our case, we could also transition the “Attack” from the “Any State” state. But with only three short animations, it don’t make a difference to be honest.

When your graph will grow, you will have to make some choices that will impact your game.

Who’s the Boss?

Before we jump into the interesting stuff, we should have the boss ready to be inserted in the game.

We are going to be quick since this chapter is about animations.

Preparing the prefab

Settings and Scripts

  1. Add a “HealthScript” to the big bad guy and grant him a lot of health points [like
      // Set or unset the attack animation
      animator.SetBool["Attack", isAttacking];
    
    0].
  2. Add a “MoveScript”. For a good behavior, try a speed of
      // Set or unset the attack animation
      animator.SetBool["Attack", isAttacking];
    
    1.

Projectile

We need a new projectile when the boss try to hit the player.

Duplicate the “EnemyShot1” and change the image with this new one:

[Right click to save the image]

  1. Set the scale to
      // Set or unset the attack animation
      animator.SetBool["Attack", isAttacking];
    
    2.
  2. Save it as a new prefab.

You should get something like this:

Weapon

As we did for the “Poulpi”, add a weapon child to the boss [an empty game object with a “WeaponScript”].

Okay! We are ready for the script and the animations!

New script

Here is the full script of the boss. Call it “BossScript”.

We’ll divide the explanations in two parts below: those related to the animations and those related to the boss.

using UnityEngine;

/// 
/// Enemy generic behavior
/// 
public class BossScript : MonoBehaviour
{
  private bool hasSpawn;

  //  Component references
  private MoveScript moveScript;
  private WeaponScript[] weapons;
  private Animator animator;
  private SpriteRenderer[] renderers;

  // Boss pattern [not really an AI]
  public float minAttackCooldown = 0.5f;
  public float maxAttackCooldown = 2f;

  private float aiCooldown;
  private bool isAttacking;
  private Vector2 positionTarget;

  void Awake[]
  {
    // Retrieve the weapon only once
    weapons = GetComponentsInChildren[];

    // Retrieve scripts to disable when not spawned
    moveScript = GetComponent[];

    // Get the animator
    animator = GetComponent[];

    // Get the renderers in children
    renderers = GetComponentsInChildren[];
  }

  void Start[]
  {
    hasSpawn = false;

    // Disable everything
    // -- Collider
    collider2D.enabled = false;
    // -- Moving
    moveScript.enabled = false;
    // -- Shooting
    foreach [WeaponScript weapon in weapons]
    {
      weapon.enabled = false;
    }

    // Default behavior
    isAttacking = false;
    aiCooldown = maxAttackCooldown;
  }

  void Update[]
  {
    // Check if the enemy has spawned
    if [hasSpawn == false]
    {
      // We check only the first renderer for simplicity.
      // But we don't know if it's the body, and eye or the mouth...
      if [renderers[0].IsVisibleFrom[Camera.main]]
      {
        Spawn[];
      }
    }
    else
    {
      // AI
      //------------------------------------
      // Move or attack. permute. Repeat.
      aiCooldown -= Time.deltaTime;

      if [aiCooldown 

Chủ Đề