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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Idle in Finite State Machine

Discussion in 'Scripting' started by markblank05, Apr 17, 2015.

  1. markblank05

    markblank05

    Joined:
    Apr 2, 2015
    Posts:
    29
    Hi, I'm trying to make a simple finite state machine for my ai and I'm having a problem to make idle state. What I want for my idle state is if my state machine is in idle, it will wait for random range from 3-5 seconds then go to another state, but the wait can be interrupt when the something trigger. I have no Idea how to make script that wait for certain number of seconds. So here is what I have so far for my state machine.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AI : MonoBehaviour
    5. {
    6.     public enum State
    7.     {
    8.         Idle,
    9.         Wander,
    10.         Moving,
    11.         Follow,
    12.         Attack
    13.     }
    14.  
    15.     SphereCollider sphere;
    16.     NavMeshAgent agent;
    17.  
    18.     float walkRadius;
    19.     State _state;
    20.  
    21.     void Awake()
    22.     {
    23.         sphere = GetComponent<SphereCollider> ();
    24.         agent = GetComponent<NavMeshAgent> ();
    25.  
    26.         walkRadius = sphere.radius;
    27.  
    28.         _state = State.Idle;
    29.         StartCoroutine ("FSM");
    30.     }
    31.    
    32.  
    33.     IEnumerator FSM()
    34.     {
    35.         while(true)
    36.         {
    37.             switch(_state)
    38.             {
    39.             case State.Idle:
    40.                 Idle();
    41.                 break;
    42.  
    43.             case State.Wander:
    44.                 Wander();
    45.                 break;
    46.  
    47.             case State.Moving:
    48.                 Moving();
    49.                 break;
    50.  
    51.             case State.Follow:
    52.                 break;
    53.  
    54.             case State.Attack:
    55.                 break;
    56.             }
    57.             yield return null;
    58.         }
    59.     }
    60.  
    61.     void Idle()
    62.     {
    63.         Debug.Log ("Idle");
    64.         _state = State.Wander;
    65.     }
    66.  
    67.     void Wander()
    68.     {
    69.         Vector3 randomDirection = Random.insideUnitSphere * walkRadius;
    70.         randomDirection += transform.position;
    71.  
    72.         NavMeshHit hit;
    73.         NavMesh.SamplePosition(randomDirection, out hit, walkRadius, 1);
    74.         agent.SetDestination(hit.position);
    75.  
    76.         _state = State.Moving;
    77.         Debug.Log ("Moving");
    78.     }
    79.  
    80.     void Moving()
    81.     {
    82.         if (agent.remainingDistance <= agent.stoppingDistance)
    83.         {
    84.             Debug.Log("Done moving, going to idle");
    85.             _state = State.Idle;
    86.         }
    87.     }
    88.  
    89.  
    90. }
    91.  
     
  2. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
  3. markblank05

    markblank05

    Joined:
    Apr 2, 2015
    Posts:
    29
    thanks, I came up with this and add a randomness to my ai but it seems the wait never works.

    Code (CSharp):
    1. void Idle()
    2.     {
    3.         Debug.Log ("Idle");
    4.         StartCoroutine ("Waiting");
    5.     }
    6.  
    7.     IEnumerator Waiting()
    8.     {
    9.         float wanderOrIdle = Random.Range (0, 100);
    10.    
    11.         if (wanderOrIdle >= 50)
    12.         {
    13.             yield return new WaitForSeconds (3);
    14.             _state = State.Wander;
    15.         }
    16.         else
    17.         {
    18.             _state = State.Wander;
    19.         }
    20.  
    21.         StopCoroutine ("Waiting");
    22.     }
    i make a 50-50 change to either wait or wander, but it always go on wonder even if the random is greater than 50
     
  4. markblank05

    markblank05

    Joined:
    Apr 2, 2015
    Posts:
    29
    never mind, i solve it. the problem is the state idle is never change, so every frame called, it start a new coroutine and never wait
     
  5. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
  7. markblank05

    markblank05

    Joined:
    Apr 2, 2015
    Posts:
    29
  8. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683