Search Unity

Working on a AI Steering Behavior script

Discussion in 'Scripting' started by Attila7894, Mar 14, 2012.

  1. Attila7894

    Attila7894

    Joined:
    Mar 11, 2011
    Posts:
    31
    Hi there ;)

    I originally posted this topic in the Assets section but I think it was the wrong one, so here it is.

    I started working on a script for defining AI Steering Behaviors and I thought it would be cool to share it, either for helping others and improving it.

    It's quite basic, I only worked on it a couple of hours, and it's written in Javascript. At the moment it uses transforms instead of rigidbodies, may be useful to create a script for both.

    The target object has a Move script attached to it. which I also used to calculate instant velocity:

    Code (csharp):
    1.  
    2.  
    3. #pragma strict
    4.  
    5. public var moveSpeed : int = 10;
    6.  
    7. var instantVelocity : Vector3;
    8.  
    9. function Start () {
    10.     instantVelocity = Vector3.zero;
    11. }
    12.  
    13. function Update () {
    14.     var pos : Vector3 = transform.position;
    15.    
    16.     var horMovement = Input.GetAxis("Horizontal");
    17.     var forwardMovement = Input.GetAxis("Vertical");
    18.  
    19.     if (horMovement) {
    20.         transform.Translate(transform.right * horMovement * Time.deltaTime * moveSpeed);
    21.     }
    22.  
    23.     if (forwardMovement) {
    24.         transform.Translate(transform.forward * forwardMovement * Time.deltaTime * moveSpeed);
    25.     }
    26.    
    27.     instantVelocity = transform.position - pos;
    28. }
    29.  
    30.  
    Then, the current AI script. Currently it has Seek, Flee, Arrive, Pursuit and Evade behaviors. The methods work, but I think some of them still need tweaking.

    I think the next step is to get rid of the switch case.

    Code (csharp):
    1.  
    2.  
    3. /*
    4.  
    5. AI Steering Behavior Script by Attilio Carotenuto - 2012 - All Rights Reserved
    6. http://www.attiliocarotenuto.com
    7.  
    8. */
    9.  
    10. #pragma strict
    11.  
    12. public var target : Transform;
    13.  
    14. public var moveSpeed : float = 6.0;
    15. public var rotationSpeed : float = 1.0;
    16.  
    17. private var minDistance : int = 5;
    18. private var safeDistance : int = 60;
    19.  
    20. enum AIState {Idle, Seek, Flee, Arrive, Pursuit, Evade}
    21. public var currentState : AIState;
    22.  
    23. function Update () {
    24.     switch(currentState){
    25.         case AIState.Idle:
    26.             break;
    27.         case AIState.Seek:
    28.             Seek();
    29.             break;
    30.         case AIState.Flee:
    31.             Flee();
    32.             break;
    33.         case AIState.Arrive:
    34.             Arrive();
    35.             break;
    36.         case AIState.Pursuit:
    37.             Pursuit();
    38.             break;
    39.         case AIState.Evade:
    40.             Evade();
    41.             break;
    42.     }
    43. }
    44.  
    45. function Seek () : void{
    46.     var direction : Vector3 = target.position - transform.position;
    47.    direction.y = 0;
    48.  
    49.    transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    50.  
    51.    if(direction.magnitude > minDistance){
    52.  
    53.       var moveVector : Vector3 = direction.normalized * moveSpeed * Time.deltaTime;
    54.  
    55.       transform.position += moveVector;
    56.  
    57.    }
    58. }
    59.  
    60. function Flee () : void{
    61.     var direction : Vector3 = transform.position - target.position;
    62.    direction.y = 0;
    63.    
    64.    if(direction.magnitude < safeDistance){
    65.       transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    66.       var moveVector : Vector3 = direction.normalized * moveSpeed * Time.deltaTime;
    67.       transform.position += moveVector;
    68.    }
    69. }
    70.  
    71. function Arrive () : void{
    72.     var direction : Vector3 = target.position - transform.position;
    73.     direction.y = 0;
    74.    
    75.     var distance : float = direction.magnitude;
    76.    
    77.     var decelerationFactor : float = distance / 5;
    78.    
    79.     var speed : float = moveSpeed * decelerationFactor;
    80.    
    81.     transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    82.  
    83.     var moveVector : Vector3 = direction.normalized * Time.deltaTime * speed;
    84.     transform.position += moveVector;
    85. }
    86.  
    87. function Pursuit () : void{
    88.     var iterationAhead : int = 30;
    89.    
    90.     var targetSpeed = target.gameObject.GetComponent(Move).instantVelocity;
    91.    
    92.     var targetFuturePosition : Vector3 = target.transform.position + (targetSpeed * iterationAhead);
    93.    
    94.     var direction : Vector3 = targetFuturePosition - transform.position;
    95.     direction.y = 0;
    96.  
    97.    transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    98.  
    99.    if(direction.magnitude > minDistance){
    100.  
    101.       var moveVector : Vector3 = direction.normalized * moveSpeed * Time.deltaTime;
    102.  
    103.       transform.position += moveVector;
    104.  
    105.    }
    106. }
    107.  
    108. function Evade () : void{
    109.     var iterationAhead : int = 30;
    110.    
    111.     var targetSpeed = target.gameObject.GetComponent(Move).instantVelocity;
    112.    
    113.     var targetFuturePosition : Vector3 = target.position + (targetSpeed * iterationAhead);
    114.    
    115.     var direction : Vector3 = transform.position - targetFuturePosition;
    116.     direction.y = 0;
    117.  
    118.    transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    119.  
    120.    if(direction.magnitude < safeDistance){
    121.  
    122.       var moveVector : Vector3 = direction.normalized * moveSpeed * Time.deltaTime;
    123.  
    124.       transform.position += moveVector;
    125.  
    126.    }
    127. }
    128.  
    129.  
    The script already works, just attach it to a game object, set a target game object and attach the Move script to it.

    Looking forward for comments ;)
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Its a good start, though I don't see how it figures which state it needs to be in. (I only did a search for the word "Arrive" and found that it only exists in the Arrive function, Enum and the Update for the most parts. This means that he seeks, and keeps seeking, but never Arrive's at the destination.

    This could be good when coupled with A* pathfinding and a couple of other nifty things.
     
  3. Attila7894

    Attila7894

    Joined:
    Mar 11, 2011
    Posts:
    31
    Yeah, for now it's just to show the different behaviours, you can choose it from the inspector.

    The idea was to just keep the steering behaviours in this script, and then another AIManager script would control the AI state.
     
  4. mthicke2

    mthicke2

    Joined:
    Aug 23, 2012
    Posts:
    15
    Thanks really useful!