Search Unity

Chase speed

Discussion in 'Scripting' started by rennster200, Jun 23, 2019.

  1. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Hello, I made some kind of script where my zombie chases me and makes it with animations(even tho its not really working- also set the parameters correctly)...but my main problem is that when I enter 60 degrees within zombies sight he just like comes super fast which I want him to do slowly and closer(if I get a little away he follows me)
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class chases : MonoBehaviour {
    5.  
    6.     public Transform player;
    7.     public Transform head;
    8.     static Animator anim;
    9.     bool pursuing = false;
    10.     public float speed = 0.1f;
    11.  
    12.  
    13.     // Use this for initialization
    14.     void Start ()
    15.     {
    16.         anim = GetComponent<Animator>();
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update ()
    21.     {
    22.         Vector3 direction = player.position - this.transform.position;
    23.         direction.y = 0 * speed;
    24.        
    25.         float angle = Vector3.Angle(direction, head.up);
    26.  
    27.         if(Vector3.Distance(player.position, this.transform.position) < 10 && (angle < 60 || pursuing)) //ako je u distanci od 10 i pod kutem od 60
    28.         {
    29.            
    30.             pursuing = true;
    31.             this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
    32.                                         Quaternion.LookRotation(direction), 0.1f);
    33.  
    34.             anim.SetBool("isIdle",false);
    35.             if(direction.magnitude > 5)
    36.             {
    37.                 this.transform.Translate(0,0,0.05f);
    38.                 anim.SetBool("isWalking",true);
    39.                 anim.SetBool("isAttacking",false);
    40.             }
    41.             else
    42.             {
    43.                 anim.SetBool("isAttacking",true);
    44.                 anim.SetBool("isWalking",false);
    45.             }
    46.  
    47.         }
    48.         else
    49.         {
    50.             anim.SetBool("isIdle", true);
    51.             anim.SetBool("isWalking", false);
    52.             anim.SetBool("isAttacking", false);
    53.             pursuing = false;
    54.         }
    55.  
    56.     }
    57. }
    58.  
     
  2. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    Hello, first of all i would recommend you to structure your code like this:

    Code (CSharp):
    1. enum ZombiState
    2. {
    3.       Idle,
    4.       Walking,
    5.       Chasing,
    6.       /* etc...  */
    7.  
    8. }
    9.  
    10. ZombiState state = ZombiState.Idle;
    11.  
    12. ...
    13.  
    14. void Update()
    15. {
    16.          switch()
    17.          {
    18.             case ZombiState.Idle:
    19.                 ...
    20.                 if( CheckSight() )
    21.                      state = ZombiState.Chasing;
    22.  
    23.                break;
    24.  
    25.                ZombiState.Walking:
    26.  
    27.                if( CheckSight() )
    28.                      state = ZombiState.Chasing;
    29.                  ...
    30.  
    31.                 break;
    32.  
    33.                  ZombiState.Chasing:
    34.                    
    35.                 if( !CheckSight() )
    36.                      state = ZombiState.Idle;  // or walking
    37.                  ....
    38.  
    39.               break;
    40.  
    41.          }
    42.  
    43. }
    44.  
    45. bool CheckSight( ZombiState state ) //different conditions based on the state
    46. {
    47.          float a = ...;
    48.          float d = ....;
    49.          return  ....  angle  < a .&&... distance  < d ... ;        
    50. }

    For the speed try to change this instruction:

    Code (CSharp):
    1. this.transform.Translate(0,0,0.05f);
    with something more appropiate, like this:

    Code (CSharp):
    1. float speed = 5f;
    2.  
    3. ...
    4.  
    5. this.transform.Translate(Vector3.forward * speed  * Time.deltaTime);
    that's for the constant speed case, always include Time.deltaTime, this will make the change in position (your current 0.05f) independent from the frame rate.

    For the gradual speed change you can use this (https://docs.unity3d.com/ScriptReference/Mathf.MoveTowards.html):

    Code (CSharp):
    1. float chaseSpeed= 5f;
    2. float currentSpeed = 0f;
    3. float acceleration = 1f; //1 sec to reach targetSpeed , 2f = 0.5 sec .. 0.5f = 2 sec ...and so on
    4. ...
    5.  
    6.  
    7. float targetSpeed = pursuing? chaseSpeed : 0f;
    8.  
    9. currentSpeed= Mathf.MoveTowards( currentSpeed , targetSpeed , acceleration * Time.deltaTime );
    10.  
    11. this.transform.Translate( Vector3.forward * currentSpeed * Time.deltaTime);
    There are some other methods, like Lerp, SmoothDamp, also using a custom AnimationCurve (my favorite), but the principle is the same, you have the current and the target magnitude, in between you perform the operation you want (in this case the "currentSpeed= Mathf.MoveTowards( ..." ) and assign the returned value to the currentValue, it works like a feedback. For the animationCurve you use a "cursor" (i like the name) and change it using deltatime (cursor += Time.deltaTime), then you evaluate the curve passing the cursor, the returned value is the speed (currentSpeed in this case).
     
  3. rennster200

    rennster200

    Joined:
    Jun 21, 2019
    Posts:
    65
    Thanks for response and for code line but I am not really an expert...I made half of the code watching some tutorials...It works now(the speed) but the animations dont change....
     
  4. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    The animation variables should be assigned when the state changes (only once). For example:

    Code (CSharp):
    1. void Update()
    2. {
    3. ...
    4.                  ZombiState.Chasing:
    5.                  
    6.                  if( !CheckSight() )
    7.                  {
    8.                      anim.SetBool("isIdle",true);    //<----- Same for the Idle and Walking, but with the proper flags
    9.                      state = ZombiState.Idle;  // or walking
    10.                  }
    11.                  ....
    12.               break;
    13. ...
    14.  
    In this case the states i mentioned are linked to the animation you see, Idle, Walk, Chasing, etc. If you are using bools you should set them to false after you used them (maybe not necessarily but for the sake of own sanity). Instead of bools you can use triggers, they are "one frame true bools" , you don't need to set them false after you used them, you set the trigger (instead of SetBool you use SetTrigger), change the bools for triggers in the animator controller and you're good to go.
     
    Last edited: Jun 25, 2019