Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[Help!] Getting movement direction of an enemy?

Discussion in 'Scripting' started by derrtyones, Jul 28, 2016.

  1. derrtyones

    derrtyones

    Joined:
    Aug 27, 2012
    Posts:
    14
    Hi everyone!

    Info
    I'm not a great coder and ran into something I just can't seem to figure out. I am working on a top-down 2D game. I have an enemy which will move to random waypoints around the levels. He does this by going to Vector2 X and Y coordinates. The enemy itself does not rotate when going around corners. So far so good.

    I was looking for a simple FOV (Field of View) script for the enemy and I came across this article:
    http://www.pencilsquaregames.com/2014/09/light-easy-and-fast-field-of-view-2d/

    So I attached this script and everything except one thing works perfectly. In the inspector you can change the direction the cone of the FOV needs to face by setting the X and Y values (default X=0, Y=90). This works great in the scene, however when I actually play the game, the cone keeps facing upwards, even when the enemy is moving downwards or to the left. This is obvious because these numbers aren't changing depending on the movement of the enemy.



    What I need
    I need a simple code to track the movement. I want the cone to face the direction the enemy is moving towards. I just can't figure out how to accomplish this.

    What I tried
    I thought I could simply get the direction the enemy is facing by checking whether the X and Y values are changing depending on the starting position. Like:

    Code (csharp):
    1. if(transform.position.x < defaultPositionX){
    2.    direction.x = -90; //moving left, so face cone to the left
    3.    direction.y = 0; // moving left, so making sure cone doesn't face up
    4. }
    Obviously this won't work because the starting position is only set once and the script will always depend on those numbers. Secondly, the enemy can move diagonally. So I am really stuck here.

    Let me know if you need any more information, I hope I explained it properly.
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    what's making the enemy move? you could just store the direction in a public variable on the enemy script and reference that
     
  3. derrtyones

    derrtyones

    Joined:
    Aug 27, 2012
    Posts:
    14
    The enemy moves by the random coordinates (X and Y values) given in the inspector of the pathfinding script. The problem is I don't know how to get the direction the enemy is going in.
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    I'm not familiar with what information is available when doing AI navigation, but if you can get his next waypoint, you can do this:

    direction = (nextwayPoint.position - currentPosition).normalized;

    otherwise you can do this:

    Code (CSharp):
    1. private Vector3 previousPosition;
    2. private Vector3 currentMovementDirection;
    3. private void Update() {
    4.     if(previousPosition != transform.position) {
    5.         currentMovementDirection = (previousPosition - transform.position).normalized;
    6.         previousPosition = transform.position;
    7.     }
    8. }
     
    hms0589 likes this.
  5. derrtyones

    derrtyones

    Joined:
    Aug 27, 2012
    Posts:
    14
    Thanks for your time to reply. Still unsure what to do.

    I created an Empty Object as a child of the Enemy. I attached the FOV script on the empty child. I noticed that when changing the valus of the Transform in the inspector, nothing happens. The only way to rotate this object is by changing the X and Y values of the direction in the inspector. This also doesn't work in runtime.

    If I can't get this FOV thing to work I might need to consider an alternative. All I want is a FOV on the Enemy that rotates with the movement.
     
  6. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    :confused: then some script somewhere is saying "go in that direction" and moves the enemy in that direction, "or go to that point" and moves it towards that point and can store "where I am - where I'm going" (which is the direction)... seems very odd to try and work out what direction it's going in when there is a source for that data.

    If you were trying to track something being moved by the physics engine based on whatever forces and interactions are in the scene you'd need something like Jeff posted.
     
    LiterallyJeff likes this.
  7. derrtyones

    derrtyones

    Joined:
    Aug 27, 2012
    Posts:
    14
  8. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    ah ok, so it's the PolyNavAgent from that asset that is making things move... if you don't fancy editing the internals of that script to add in the variable to reference, Jeff's approach would be one of the easiest; although I'd go with that being a standalone component (lets call it "MovementData") you can put on anything and have "currentMovementDirection" as a public variable :) then it would be just a case of

    Code (csharp):
    1.  
    2. Vector3 enemyDirection = enemy.GetComponent<MovementData>().currentMovementDirection;
    3.  
    you might also want to consider using Mathf.dot() to check what direction it's moving towards https://docs.unity3d.com/ScriptReference/Vector3.Dot.html , it might make checking "is it moving a little left or a lot left" easier.
     
  9. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Keep in mind that normalizing and vector.Magnitude are CPU costly operations (because they rely on square root), so try to avoid them when you can. If it's something where direction only changes on mouseclick, the direction vector should be updated only then. Not on every frame.
     
  10. derrtyones

    derrtyones

    Joined:
    Aug 27, 2012
    Posts:
    14
    Thanks for all the help guys, much appreciated. This seems to get really complicated. I will have a look tomorrow, otherwise I will have to come up with a more simple way getting a FOV kinda system to work for the enemy.

    I thought of using a Raycast and checking whether the enemy can see the player. That won't work with a FOV but at least I will get a step closer. I will have to look into how to get that done.

    If anyone else got any ideas or suggestions, just post! :)
    Thanks!
     
  11. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    Thanks for the tip. Perhaps this then...
    Code (CSharp):
    1. private Vector3 previousPosition;
    2. private Vector3 velocity;
    3.  
    4. public Vector3 CurrentMovementDirection {
    5.     get {
    6.         return velocity.normalized;
    7.     }
    8. }
    9.  
    10. private void Update() {
    11.     if(previousPosition != transform.position) {
    12.         velocity = previousPosition - transform.position;
    13.         previousPosition = transform.position;
    14.     } else {
    15.         velocity = 0;
    16.     }
    17. }
    It's worth noting that the script @derrtyones is using makes use of normalize on Update, so it's doubly bad to do it before assigning the direction.

    Here it is in context. Just make sure this code is running in a script on the same object as the CrewSensors script. This couples this script with the CrewSensors script, which isn't great, but gets the job done simply.
    Code (CSharp):
    1. private Vector3 previousPosition;
    2. private Vector3 velocity;
    3.  
    4. public Vector3 CurrentMovementDirection {
    5.     get {
    6.         return velocity.normalized;
    7.     }
    8. }
    9.  
    10. private CrewSensors sensors;
    11.  
    12. private void Start(){
    13.     sensors = GetComponent<CrewSensors>();
    14. }
    15.  
    16. private void Update() {
    17.     if(previousPosition != transform.position) {
    18.         velocity = previousPosition - transform.position;
    19.         previousPosition = transform.position;
    20.         sensors.direction = velocity;
    21.     }
    22. }
    Also remember to comment out the Debug.Log statements from the Crew Sensors script. Printing to the console slows down the game quite a bit.
     
    Last edited: Jul 29, 2016
    hms0589 and derrtyones like this.
  12. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    that kind of approach works for FOV when combined with checking against the Vector3.angle between the "forward" direction and the raycast... which means you're back to needing the "forward" direction again :(