[ENG] How to make a friendly NPC move automatically in Unity – guide for a top down 2D game

csharpunity

Hello everyone,

today I want to present you an how to. This will be about, as the title says, on how to move a friendly NPC randomly around the map. This script has furthermore code for non-moving characters. Sounds pretty dump? Well, this non-moving script is for the case, that the non-movement NPC can be pushed – and plays the appropriate animation.

So, personally I suggest you following options:

  1. you read the whole guide and learn things and…
    1. … you copy the code afterwards
    2. … you write the code yourself
  2. you skip the whole guide and just copy the code, read it and set up your object in the way it works. Or maybe change the code.

All of the options above are valid depending on your skills. Please don’t forget to give me some credits on your published game – thanks!

1. Preparing the Animator

Before you can start to use the script, you may want to set up the animator. I won’t write a tutorial on this, since it is pretty forward and I think easy to understand. Personally I like quick tutorials and I just found one which suits best:

HINT: if you want only check the script out without animation, please comment the lines out which contains the variable anim. The character won’t be animated, but still moved. Nevertheless I encourage you to use the animation, it’s even more nice and you learn how to create an animation, if you haven’t yet.

IMPORTANT NOTE: Please keep in mind that I used following variables on the animator:

bool for animation state, changed by code: TRUE if the character is moving, FALSE if the character stands

float for animation state, changed by code: gets the speed on the x-axis (left or right / vertically) of the character. can be refined for more smooth animation. In my example I am using only values -1, 0 and 1, 0 is for not walking on the x-axis, -1/1 is walking on the x-axis. -1 is left, 1 is right.

float for animation state, changed by code: gets the speed on the y-axis (up or down / horizontally) of the character. can be refined for more smooth animation. In my example I am using only values -1, 0 and 1, 0 is for not walking on the y-axis, -1/1 is walking on the y-axis. -1 is up, 1 is down.

float for animation state, changed by code: this saves the last movement for the player, in order to determine the correct idle-position, for the x-axis.

float for animation state, changed by code: this saves the last movement for the player, in order to determine the correct idle-position, for the y-axis. After you set up the animation-states with its blend trees and applied the sprites on the appropriate animation state you are ready to proceed.

Nevertheless, here are some screenshofs of my set up:

Figure 1: States and Variables in the Animator

animator_vars_states
States and Variables in the Animator

Figure 2: A blend tree for the 8 direction movement.

blendtree_example
Example of a Blendtree in the state.

2. NPC Character Setup

The second must have is the component Rigidbody2D. As I don’t want the character to be rotated, I set the checkbox on “Freeze Rotation” activated.

Figure 3: Inspector screenshot for a NPC

npc_inspector_example
Example of a NPC set-up

Optionally, but not needed in the example is any Collider2D-Component. I am using BoxCollider2D, which suites for my use case the best. You may will need it for later, as an example you can use the collider to check if the enemy has been hit by a player. Somehow the Rigidbody2D built-in collider isn’t working in the appropriate way – for this reason I added my own, because in my game you are able to push the NPCs around.

3. Adding some logic – explanation

So, with the steps one and two you added the basic needs for this setup. At this point it’s pretty obvious that the character won’t move automatically. As I am a big fan of dynamic and re-usable code, i planned to make the code as flexible as needed. Before we have a look at the code, let us just proceed to the thoughs behind the random movement.

Note: Please keep in mind that I won’t describe everything  on the code, just the general idea behind a NPC walking script are reflected here. If you have questions on this, feel free to ask this in the comments!

3.1 Basic definitions

The requirements for this are defined as following:

  • – the NPC should move randomly:
    • within a specified area,
    • has a limit on the distance it can walk
    • changing the direction at a specified range of time,

These are the basic requirements which are set up in this script. Of course you could add some more logic or ideas behind it. Defined this requirements we can just head up to the code implementation.  The question is now, how we can represent the above defined points in code? First of all, we know that a movement is something about coordinates. Those are for our use case only X and Y, Z is not needed. Furthermore the coordinates are represented as a float in unity. Knowing this we introduce this variables:

  • Specified Area variables: (for the min max area!)
      • Alternatively you could introduce two Vector2 variables, where the x property is defined as max, and y property is defined as min, like this:
  • limit in walk distance:
      • Alternatively you could introduce here a Vector2 variable, too.

This are the definition of the ranges. They are public, because we want may change the values for a specific NPC – with the public members we are able to change them in the inspector.

In order to use the calculated random values we introduce some more floats:

This two floats will store the current calculated random value within the defined ranges.

The last requirement is that the direction of the character should be change randomly within a specified range of time. Also here, unity provides classes/functionality to analyses the time. What we will is Time.time, which gets the time in seconds since the start of game frame wise (see also Unity – Scripting API). We introduce:

We are using the float tChange for the next change after the current frame. With the Vector2 timeChange we defined a time-range. With this value we will get a random time and set tChange to this value.

3.2 Let the logic do the magic

After defining the variables, we can add some magic. I won’t explain the animation logic here, since I feel like it should be understandable for programmers. If not, try to think of the idea behind – I’m pretty sure you will get it – if not, rethink!!! Okay, back to the topic. In order to check if the time has passed, we need a simple if-clause:

If the time has passed, we want to get some new random values, which is done like this:

After the random-calculation we need to set some variables. We introduce a local member direction, which is used for setting the animation variables, as well for the moving of the character it self.

What’s with the direction? It’s default is 0,0. We are checking the values for randomX and randomY.  If they are greater than animThreshold, which can be seen as the smaller value for playing an animation, then set the corresponding axis to 1, if smaller, then set it to -1. This will determine the correct direction (no code listing).

Last but not least, we want to force the position within it’s borders:

You may notice the Vector originalPosition. This is a private Vector, which contains the original position of the NPC. It will be set at the Start. We want to do this, because we want the NPC within the range.

After we did all this calculation, we can set the animation variables:

Basically, that’s it.

4. Summary and Comments

I know, this description is not 100% detailed and complete. I may add comments and description, depending on the user-reaction. For the first draft, I wanted to make sure to focus on the main task, which is what do I need for making a NPC walking randomly. The code contains a little bit more which should be self-explanatory.

5. The code in action

You may want to see what the code does before using it, here are the two behaviors which are implemented in the script. The NPC is obviously the black guy – the Girl is the player.

walking_animation
Walking NPC
standing
Standing NPC

NOTE: currently the GIFs are not shown at full lenght. I’m looking into it an update it as soon as possible.

6. The Code

Here is what you probably are looking for:

6. Some riddle

The codes works as I intended. As a riddle for you, try to find the little flaw – who is able to see it? Please add to comments 🙂

Thank you and have fun!
——-



5 Kommentare

  1. I copied the code, but I’m getting an error that reads “NPCMoveScript.cs(109,1): error CS1022: Type or namespace definition, or end-of-file expected.” I tried deleting the last parentheses because that didn’t seem to correspond to another one, but it just created more errors, such as “The name ‘moveVec’ does not exist in the current context”. I’m trying this on a mac, so could this be why I’m getting such errors? I’d appreciate advice, thanks.

    Also, is the answer to your riddle that you typed “Using UnityEngine;” twice?

    • hi there – sorry for the extreme late reply. jepp, that was one of two riddles. but i’ve to admin that i’ve forgotten the 2nd one.

      did you copy the full code? I still got a working copy on this code, i may can send it to you if it’s not to late.

  2. Hi
    Thanks for the script. Is there a way to have the object detect a collidable object and stop? Currently the NPC just walks over tiles that are marked as collision objects. I’d like it to stop and change direction again.

    • the formatting on this is strange; the collision problem is maybe the 2nd flaw, i am not 100% sure about it. do the npcs have a collision box?
      I’ve got a new version if this if you are still interested.

Antworten

Deine E-Mail-Adresse wird nicht veröffentlicht.


*


Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.