How do I create an NPC that "repels" (runs away from) the player in Unity3d

Viewed 637

I've done about an hour of research on how to make an NPC "repel," meaning run away from, the player in Unity3d. Everywhere I search this up, I find a ton of stuff on how to make an NPC run towards a player, but never repel. I am new to game development, so I have no idea how to do this stuff.

2 Answers

take the Vector3 positions of the player and the NPC and perform this calculation:

Vector3 direction = NPCPosition - playerPosition;
direction.y = 0;
direction = Vector3.Normalize(direction);
NPCTransform.rotation = Quaternion.Euler(direction);

//MOVE NPC forward (the calculations above calculate the direction away from the player)
NPCTransform.Translate(NPCTransform.position + (transform.forward * NPCSpeed));

I hope this helped. :)

If anything is unclear, just ask me. :D

Edit: I added the direction = Vector3.Normalize(direction); line.

in this answer I will try to explain the code I wrote as best as I can.

Vectors are just arrays of floats. Vector2 contains two floats, Vector3 contains 3 floats... In Unity, a Vector3 is used for positions and directions.

The first line:

Vector3 direction = NPCPosition - playerPosition;

We are creating a Vector3 direction. We take the Vector3 NCPPosition - playerPosition. So, why are we doing this? Just imagine two points in one line. let's say, you want to get the distance the second point must travel on the line to reach the first point. Let's say that the first point is 1 Inch away from the starting point of the line. And let's say the second point is 2 Inches away from the starting point of the line. So in which direction must the second point travel to get away from the first point? Well, to the right. And how do we calculate this? We take the position of the point we want to move and we subtract the position of the point we want to travel away from. This will get us a value (1). This means, that we can travel 1 Inch to the right. If the points were on different positions, let's say the point we want to move is on 2 and the point we want to move away from is on 5, the calculation above will return -3.This means, we could move -3 Inches to the right (3 Inches to the left) to move away from the point. Now let's do this for all the axes (x, y and z) this will get a Vector 3 with a direction we want to move (away from the player).

In the second line,

direction.y = 0;

We set the y axis to be zero. Why? In Unity the y axis represents up and down. And since we don't want the NPC to just fly away (if he is higher than the player) and lag into the ground (when he is lower than the player), we set this axis to be zero.

I forgot this line in my previus answer:

direction = Vector3.Normalize(direction);

In this line we make the direction actually just a direction (sorry for poor explanation for this one). And that's because we take the diference in the global space between th objects and we want the NPC to just move away with a constant speed. If we didn't write this line, the NPC's speed would change when the distance to the player changes.

In the next line,

NPCTransform.rotation = Quaternion.Euler(direction);

We rotate the NPC away from the player. And why is that Quaternion.Euler() there? Well, we can't set the rotation to a Vector, we must first make a Quaternion out of it. A quaternion in Unity is used for rotation.

In the last line we actually move the NPC.

NPCTransform.Translate(transform.forward * NPCSpeed);

There are many ways to move an object in Unity. If you want the NPC to have gravity (in case he falls down from somewhere, to not just float in the air :D), you should add a Rigidbody to the NPC and check "use gravity" In that case the last line would look like this instead of NPCTransform.Translate(transform.forward * NPCSpeed);:

NPCRigidbody.AddForce(direction * NPCSpeed);

When using a tranform to move the NPC, we would use the line above:

NPCTransform.Translate(...);

The translate method moves the transform (the object (in our case the NPC)) the position we gave. So, what are we passing in that method? We passed in this:

transform.forward * NPCSpeed

Because this method moves the object a position, we add transform.forward * NPCSpeed. In this we just take the direction and multiply it with the speed we want the NPC to move. (speed is a number, usually float).

So the code would look like this if you would use a transform to move the NPC:

Vector3 direction = NPCPosition - playerPosition;
direction.y = 0;
direction = Vector3.Normalize(direction);
NPCTransform.rotation = Quaternion.Euler(direction);
NPCTransform.Translate(transform.forward * NPCSpeed);

And like this if you would use a Rigidbody to move the NPC:

Vector3 direction = NPCPosition - playerPosition;
direction.y = 0;
direction = Vector3.Normalize(direction);
NPCTransform.rotation = Quaternion.Euler(direction);
NPCRigidbody.AddForce(direction * NPCSpeed);

I hope that the explanation is good enough. :)

Related