• No results found

Action Points – performing an action in a specified spot

In document Unity 5.x Animation Cookbook (Page 170-174)

Action Points are a common concept used for characters in games that have to perform a certain action in a certain spot. You will find a lot of them in RPG games where NPCs populate towns and perform different actions creating an illusion of a living community.

We are going to address a simple case of an Action Point in this recipe.

Getting ready

We are going to use a character with three animations: Walk, Idle, and Action. We are also going to use the SetSpeedFromAgent.cs script from the Using Blend Trees to blend walk and run animations recipe in Chapter 5, Character Movement. You can also open the provided example Unity project and go to the Chapter 05 Character actions and

expressions\Recipe 05 Action points performing an action in a specified spot directory. You will find an Example.scene scene there. Play the game to see the effect—the Humanoid character will approach an Action Point and perform a pick up animation.

How to do it…

To create a simple Action Point, follow these steps:

Import the character to Unity.

1.

Put it on the scene and add a NavMesh Agent component to it.

2.

Bake the NavMesh in the scene.

3.

Create an Animator Controller and assign it to the character's Animator 4. component.

Create a float Speed parameter and a Trigger Action parameter in the 5. controller.

Drag and drop the Idle, Walk, and Action animations to the controller. Make 6. sure that the Idle animation is the default state.

Create four transitions (see the following image):

7. Idle | Walk with one condition: Speed parameter greater than 0.5. Has Exit Time should be set to false and TransitionDuration set to around 0.1 seconds.

Walk | Idle with one condition: Speed parameter less than 0.5. Has Exit Time should be set to false and Transition Duration set to around 0.1 seconds.

Any State | Action with one condition: Action triggers parameter. Has Exit Time should be set to false and Transition Duration set to around 0.1 seconds.

Action | Idle with no conditions: Has Exit Time should be set to true and Transition Duration set to around 0.1 seconds.

Animator Controller with Action state used by the Action Point

Create a new script and call it ActionPoint.cs.

8.

In that script, we have an IEnumerator PerformAction() coroutine that 9. handles the Action Point usage (it is started in the Start() function). In this

coroutine, we first check if our character is close enough to the Action Point. If not, we set the NavMesh Agent's destination to the Action Point's position, wait one frame, and check again:

while ((agentTransform.position

transform.position).sqrMagnitude > actionDistance * actionDistance)

{

agent.SetDestination(transform.position);

agent.Resume();

yield return null;

}

The agentTransform variable holds the reference to the character's transform.

10. The actionDistance is the distance from the Action Point in which our character should start performing the action.

When our character is closer to the Action Point than the actionDistance, we 11. stop the NavMesh Agent and check if we want to match the character's position and/or rotation to our Action Point before the character starts playing the action animation. If not, we start playing the animation right away:

agent.Stop();

if (!matchBeforeAction) {

anim.SetTrigger(actionTrigger);

}

Next we check if we want to match character's position and/or rotation

12. with Action Point's position/rotation. If so, we use linear interpolation to match the position and/or rotation. If the position and/or rotation of the character are close enough to the Action Point's position/rotation, we set the character's position/rotation to be exactly the same as Action Point's position/rotation:

while (matchRotation == true || matchRotation == true)

agentTransform.rotation =

Lastly, we check if we want to play the animation after the character's position 13. and/or rotation was matched with the Action Point. If so, we play the animation

now (as the character position and/or rotation was adjusted):

if (matchBeforeAction)

Create a new empty game object, call it Action Point, and place it in the scene, 15. where the character should perform the action.

Attach the script to the Action Point game object. Drag and drop the character to 16. the Agent field of the script's component.

You may need to adjust the Action Distance value of the script. You can also set 17. the Match Position, Match Rotation, and Match Before Action options to

achieve different results.

Play the game to see the effect.

18.

How it works…

The ActionPoint.cs script's role is to tell the character where to go and what animation to play. The PerformAction() coroutine also adjusts the character's position and rotation to match the position and rotation of the Action Point. We use the simple Lerp() function here for both the position and the rotation. In most cases, it's enough.

There's more…

You may also use the MatchTarget() function to interpolate the character's position and rotation and match it with the Action Point. We were using this technique in the Adding animation to off-mesh links recipe in Chapter 4, Character Movement. In such cases, it would be best to have a special approach animation in which the character approaches the Action Point.

You may also want to use the randomized actions concept for creating Action Points with random actions. The concept is described in the Using Blend Trees to create randomized actions recipe. Instead of creating random actions, you can also prepare a public enum Action variable containing all your actions as enumerations and a pu variable to store the Action in the Actionblic Action actionPointAction variable to store the Action in the Action Point. Then you need to set the RandomAction parameter (as described in the mentioned recipe) to the (float) actionPointAction value. This will allow you to use Blend Trees for performing specified actions (instead of random ones).

Also, in many cases, you will need to divide your actions into three steps:

Pre-Action: This animation can be used to approach the Action Point or as a

“state transition” animation. For instance, when we want our character to sit on a chair it is good to have a Pre-Action animation of the character sitting (transition from Idle to Sitting states).

Looped-Action: A looped animation suitable for this Action Point. In our sitting example, that would be a looped sitting animation. It can also be a series of animations (our character can, for instance, sit and eat or sit and drink).

Post-Action: This is an animation that transitions from the Looped-Action animation to the Idle animation. In our example, it would be a character getting up from the chair.

Synchronizing an animation with objects in

In document Unity 5.x Animation Cookbook (Page 170-174)