Search Unity

Getting an enemy to move towards you ?

Discussion in 'Scripting' started by shader, Nov 11, 2009.

  1. shader

    shader

    Joined:
    Apr 4, 2009
    Posts:
    253
    Can anyone offer a relatively simple script to make an enemy move towards a FPS player.


    thanks
     
  2. shader

    shader

    Joined:
    Apr 4, 2009
    Posts:
    253
    found this on the forum, I tested with 2 cubes on a plane and it works but I couldn't figure out how to slow down the movement of the cube to the enemy cube ... it's instantaneous when in range (obviously from the code)
    I added the 'else' statement that displays the distance for debugging purposes

    Code (csharp):
    1.  
    2. var enemy : Transform;
    3.  
    4. function Update()
    5.  
    6. {
    7.     if ( Vector3.Distance( enemy.position, transform.position ) < 500 )
    8.    
    9.    
    10.     {
    11.         print("player is close");
    12.       transform.position = enemy.transform.position;
    13.       transform.rotation = enemy.transform.rotation ;
    14.        
    15.     }
    16.     else
    17.        {
    18.     print("not close yet");
    19.     print(Vector3.Distance( enemy.position, transform.position ));
    20.        }
    21. }
    22.  
    23.  
     
  3. shader

    shader

    Joined:
    Apr 4, 2009
    Posts:
    253
    Got this working but it happens in 1 second, how do I slow it down ???

    Code (csharp):
    1.  
    2. var enemy : Transform;
    3. var start: Transform;
    4. var end: Transform;
    5.  
    6. function Update()
    7.  
    8. {
    9.    
    10.  
    11. if (  Vector3.Distance( enemy.position, (Vector3.Lerp(start.position, end.position,Time.time) )) < 100  )
    12.    
    13.    
    14.     {
    15.        print("player is close");
    16.        transform.position = enemy.transform.position;
    17.        transform.rotation = enemy.transform.rotation ;
    18.        
    19.       transform.position = Vector3.Lerp(start.position, end.position, Time.deltaTime  );
    20.        
    21.     }
    22.     else
    23.     {
    24.     print("not close yet");
    25.     print(Vector3.Distance( enemy.position, transform.position ));
    26.     }
    27. }
    28.  
    [/code]
     
  4. Bren

    Bren

    Joined:
    Aug 28, 2008
    Posts:
    191
    Code (csharp):
    1.  
    2. var enemy : Transform;
    3. var speed: float;
    4.  
    5. function Update()
    6. {
    7. if (  Vector3.Distance( enemy.position, transform.position) < 100  )
    8.     {
    9.        print("player is close");
    10.      
    11.       transform.position = (enemy.position - transform.position ).normalized * speed * Time.deltaTime;
    12.     }
    13.     else
    14.     {
    15.     print("not close yet");
    16.     print(Vector3.Distance( enemy.position, transform.position ));
    17.     }
    18. }
    19.  
     
  5. shader

    shader

    Joined:
    Apr 4, 2009
    Posts:
    253
    Thanks Bren, I'll try it later.

    EDIT:

    It didn't seem to work, the player cube just disappears
     
  6. RHD

    RHD

    Joined:
    Mar 30, 2009
    Posts:
    719
    I guess you've checked out the Lerpz tutorial?

    It's a while since I did it but there are handy enemy scripts there that may provide some useful info.
     
  7. Bren

    Bren

    Joined:
    Aug 28, 2008
    Posts:
    191
    Speed will be in m/s, so it should be a relatively small number, depending on your scale. Start with 1 and see how that goes.

    Try this one, by putting it on an enemy object.

    Make sure the player is tagged Player.

    It ain't pretty, but it's tested and works for me.

    Code (csharp):
    1. var player : GameObject;
    2. var speed : float = 1;
    3.  
    4. function Start ()
    5. {
    6.      player = GameObject.FindGameObjectWithTag("Player");
    7.  
    8.      if (!player)
    9.           Debug.Log ("ERROR could not find Player!");
    10. }
    11.  
    12. function Update()
    13. {
    14.      if (!player)
    15.           return;
    16.  
    17.      var distance = Vector3.Distance( player.transform.position, transform.position);
    18.  
    19.      if ( distance < 100  )
    20.      {
    21.           Debug.Log ("player is close");
    22.          
    23.           var delta = player.transform.position - transform.position;
    24.           delta.Normalize();
    25.          
    26.           var moveSpeed = speed * Time.deltaTime;
    27.      
    28.           transform.position = transform.position + (delta * moveSpeed);
    29.     }
    30.     else
    31.     {
    32.           Debug.Log("not close yet " + distance);
    33.     }
    34. }
     
  8. Mr.Shaw

    Mr.Shaw

    Joined:
    Nov 15, 2009
    Posts:
    4
    okey just give the emeny this script and take the first person player to target
    Code (csharp):
    1. var speed = 3.0;
    2. var rotationSpeed = 5.0;
    3. var shootRange = 15.0;
    4. var attackRange = 30.0;
    5. var shootAngle = 4.0;
    6. var dontComeCloserRange = 5.0;
    7. var delayShootTime = 0.35;
    8. var pickNextWaypointDistance = 2.0;
    9. var target : Transform;
    10.  
    11. private var lastShot = -10.0;
    12.  
    13. // Make sure there is always a character controller
    14. @script RequireComponent (CharacterController)
    15.  
    16. function Start () {
    17.     // Auto setup player as target through tags
    18.     if (target == null  GameObject.FindWithTag("Player"))
    19.         target = GameObject.FindWithTag("Player").transform;
    20.  
    21.     Patrol();
    22. }
    23.  
    24. function Patrol () {
    25.     var curWayPoint = AutoWayPoint.FindClosest(transform.position);
    26.     while (true) {
    27.         var waypointPosition = curWayPoint.transform.position;
    28.         // Are we close to a waypoint? -> pick the next one!
    29.         if (Vector3.Distance(waypointPosition, transform.position) < pickNextWaypointDistance)
    30.             curWayPoint = PickNextWaypoint (curWayPoint);
    31.  
    32.         // Attack the player and wait until
    33.         // - player is killed
    34.         // - player is out of sight    
    35.         if (CanSeeTarget ())
    36.             yield StartCoroutine("AttackPlayer");
    37.        
    38.         // Move towards our target
    39.         MoveTowards(waypointPosition);
    40.        
    41.         yield;
    42.     }
    43. }
    44.  
    45.  
    46. function CanSeeTarget () : boolean {
    47.     if (Vector3.Distance(transform.position, target.position) > attackRange)
    48.         return false;
    49.        
    50.     var hit : RaycastHit;
    51.     if (Physics.Linecast (transform.position, target.position, hit))
    52.         return hit.transform == target;
    53.  
    54.     return false;
    55. }
    56.  
    57. function Shoot () {
    58.     // Start shoot animation
    59.     animation.CrossFade("shoot", 0.3);
    60.  
    61.     // Wait until half the animation has played
    62.     yield WaitForSeconds(delayShootTime);
    63.    
    64.     // Fire gun
    65.     BroadcastMessage("Fire");
    66.    
    67.     // Wait for the rest of the animation to finish
    68.     yield WaitForSeconds(animation["shoot"].length - delayShootTime);
    69. }
    70.  
    71. function AttackPlayer () {
    72.     var lastVisiblePlayerPosition = target.position;
    73.     while (true) {
    74.         if (CanSeeTarget ()) {
    75.             // Target is dead - stop hunting
    76.             if (target == null)
    77.                 return;
    78.  
    79.             // Target is too far away - give up
    80.             var distance = Vector3.Distance(transform.position, target.position);
    81.             if (distance > shootRange * 3)
    82.                 return;
    83.            
    84.             lastVisiblePlayerPosition = target.position;
    85.             if (distance > dontComeCloserRange)
    86.                 MoveTowards (lastVisiblePlayerPosition);
    87.             else
    88.                 RotateTowards(lastVisiblePlayerPosition);
    89.  
    90.             var forward = transform.TransformDirection(Vector3.forward);
    91.             var targetDirection = lastVisiblePlayerPosition - transform.position;
    92.             targetDirection.y = 0;
    93.  
    94.             var angle = Vector3.Angle(targetDirection, forward);
    95.  
    96.             // Start shooting if close and play is in sight
    97.             if (distance < shootRange  angle < shootAngle)
    98.                 yield StartCoroutine("Shoot");
    99.         } else {
    100.             yield StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
    101.             // Player not visible anymore - stop attacking
    102.             if (!CanSeeTarget ())
    103.                 return;
    104.         }
    105.  
    106.         yield;
    107.     }
    108. }
    109.  
    110. function SearchPlayer (position : Vector3) {
    111.     // Run towards the player but after 3 seconds timeout and go back to Patroling
    112.     var timeout = 3.0;
    113.     while (timeout > 0.0) {
    114.         MoveTowards(position);
    115.  
    116.         // We found the player
    117.         if (CanSeeTarget ())
    118.             return;
    119.  
    120.         timeout -= Time.deltaTime;
    121.         yield;
    122.     }
    123. }
    124.  
    125. function RotateTowards (position : Vector3) {
    126.     SendMessage("SetSpeed", 0.0);
    127.    
    128.     var direction = position - transform.position;
    129.     direction.y = 0;
    130.     if (direction.magnitude < 0.1)
    131.         return;
    132.    
    133.     // Rotate towards the target
    134.     transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    135.     transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    136. }
    137.  
    138. function MoveTowards (position : Vector3) {
    139.     var direction = position - transform.position;
    140.     direction.y = 0;
    141.     if (direction.magnitude < 0.5) {
    142.         SendMessage("SetSpeed", 0.0);
    143.         return;
    144.     }
    145.    
    146.     // Rotate towards the target
    147.     transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    148.     transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    149.  
    150.     // Modify speed so we slow down when we are not facing the target
    151.     var forward = transform.TransformDirection(Vector3.forward);
    152.     var speedModifier = Vector3.Dot(forward, direction.normalized);
    153.     speedModifier = Mathf.Clamp01(speedModifier);
    154.  
    155.     // Move the character
    156.     direction = forward * speed * speedModifier;
    157.     GetComponent (CharacterController).SimpleMove(direction);
    158.    
    159.     SendMessage("SetSpeed", speed * speedModifier, SendMessageOptions.DontRequireReceiver);
    160. }
    161.  
    162. function PickNextWaypoint (currentWaypoint : AutoWayPoint) {
    163.     // We want to find the waypoint where the character has to turn the least
    164.  
    165.     // The direction in which we are walking
    166.     var forward = transform.TransformDirection(Vector3.forward);
    167.  
    168.     // The closer two vectors, the larger the dot product will be.
    169.     var best = currentWaypoint;
    170.     var bestDot = -10.0;
    171.     for (var cur : AutoWayPoint in currentWaypoint.connected) {
    172.         var direction = Vector3.Normalize(cur.transform.position - transform.position);
    173.         var dot = Vector3.Dot(direction, forward);
    174.         if (dot > bestDot  cur != currentWaypoint) {
    175.             bestDot = dot;
    176.             best = cur;
    177.         }
    178.     }
    179.    
    180.     return best;
    181. }
    i snap it from FPS tutorial
     
  9. shader

    shader

    Joined:
    Apr 4, 2009
    Posts:
    253
    Thanks Bren, got it going !

    It turns out that I had a massive scale, I actually had to use 50 with your code.

    How do you set your scale ??? What reference do you use when starting a new scene ?


    Mr Shaw, you're script uses waypoints. I havn't looked at them yet but thanks anyway.
     
  10. trinitysj

    trinitysj

    Joined:
    Jan 15, 2010
    Posts:
    54
    I tried to add the below script to my enemy object and get this error

    Assets/Standard Assets/Scripts/enemy.js(171,19): BCE0018: The name 'AutoWayPoint' does not denote a valid type.

    not sure what that is..
    the enemy toon has character controller on it as well as its animations.
    is this a .js or .cs file as well..

    thanks
     
  11. psychentist

    psychentist

    Joined:
    Apr 12, 2009
    Posts:
    75
    to trinitysj:

    in the fps tutorial, the enemy robot things have waypoints that they automatically move to whenever the player is not around. in order to use their a.i. you also have to import the "auto way point" script. just attach it to an empty game object to create a way point, and the robot will work.
     
  12. sovietpenguin

    sovietpenguin

    Joined:
    Jan 9, 2011
    Posts:
    21
    thank you bren! this works and really helps with my game! one thing to keep in mind, my cube doesent rotateto face the player! help?
     
    Last edited: Jan 9, 2011
  13. PaulHarisson

    PaulHarisson

    Joined:
    Jan 31, 2011
    Posts:
    13
    your script works great bren, Wat i need is I have to rotate the enemy to look at my Player.
     
  14. CheyTac

    CheyTac

    Joined:
    Feb 17, 2011
    Posts:
    71
    var Player : Transform;

    function Update()
    {
    transform.LookAt(Player);

    }
     
  15. casey945

    casey945

    Joined:
    Feb 16, 2009
    Posts:
    46
    nice!
     
  16. zulkarneyn

    zulkarneyn

    Joined:
    Mar 26, 2011
    Posts:
    2
    hi Bren , this code is related to distance how can we change it to visibilty.
    i want enemies start following when they see "player" and stop moving when sight is gone till hitting a wall.
    also i expect enemies to move only X or only Z axis.
     
  17. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    You need a function like this:

    Code (csharp):
    1.  
    2. function IsVisible(object : Transform){
    3.     var hits : RaycastHit[];
    4.     var ray : Ray = new Ray (transform.position, transform.position-object.position);
    5.    
    6.     hits = Physics.RaycastAll (ray, Vector3.Distance(transform.position, object.position));
    7.    
    8.     for (var i = 0;i < hits.Length; i++) {
    9.         var hit : RaycastHit = hits[i];
    10.         var obj : Transform = hit.collider.transform;
    11.         // is the object anything but this or the one we are searching for
    12.         if (obj != transform   obj != object) return false;
    13.         // is the object the one we are searching for?
    14.         if (obj == object) return true;
    15.     }
    16.     // this should never happen...
    17.     return true;
    18. }
    19.  
     
  18. kropcke

    kropcke

    Joined:
    Nov 20, 2009
    Posts:
    11
    (Bren, it's 2013 now... you posted this in 2009)

    Thank you.
    Your script is exactly what I've been looking for...

    (1) find the delta between Object and Player
    (2) normalize that delta
    (3) add normalized delta to Objects' new transform.

    You are a godsend - thank you again.

    Sincerely,
    kropcke

    (hope you get this)
     
  19. DuckFuel

    DuckFuel

    Joined:
    Jan 28, 2014
    Posts:
    2
    Scratch that, it's now 2014! Also, my first post. Better late than never.

    I came across this thread whilst looking into a simple way of implementing it and this is the gold. In fact, this is pretty much how I'd thought it would be implemented which is encouraging, because this is my first full project using Unity. Anyway, enough of the babbling; I use C# so I have converted it to C# (Not much to change at all) and added the LookAt player feature simply for convenience :)

    Code (csharp):
    1.     private GameObject player;
    2.     public float speed = 1.0f;
    3.  
    4.     // Use this for initialization
    5.     void Start () {
    6.    
    7.         player = GameObject.FindGameObjectWithTag ("Player");
    8.  
    9.         if (!player) {
    10.             Debug.Log ("ERROR could not find Player!");
    11.         }
    12.     }
    13.    
    14.     // Update is called once per frame
    15.     void Update () {
    16.  
    17.         if (!player) {
    18.             return;
    19.         }
    20.  
    21.         var distance = Vector3.Distance( player.transform.position, transform.position);
    22.  
    23.         if ( distance < 100  )  
    24.         {  
    25.             Debug.Log ("player is close");
    26.             var delta = player.transform.position - transform.position;
    27.             delta.Normalize();
    28.             var moveSpeed = speed * Time.deltaTime;
    29.             transform.position = transform.position + (delta * moveSpeed);
    30.             transform.LookAt(player.transform);
    31.         }
    32.  
    33.         else    
    34.         {
    35.             Debug.Log("not close yet " + distance);
    36.         }
     
    Last edited: Jan 28, 2014