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

Need help in statemachine

Discussion in 'Scripting' started by Hanross, Sep 21, 2018.

  1. Hanross

    Hanross

    Joined:
    Aug 11, 2018
    Posts:
    11
    I used simple basic statemachine

    there are 3 classes

    and here are codes

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace StateStuff {
    6.  
    7.  
    8.     public class StateMachine<T> {
    9.         public State<T> CurrentState { get ; private set ;}  
    10.         public T owner;
    11.         public StateMachine(T _o)
    12.         {
    13.             owner = _o;
    14.             CurrentState = null;
    15.  
    16.         }
    17.  
    18.         public void Changestate (State<T> _newstate)
    19.         {
    20.            
    21.             if (CurrentState != null)
    22.                 CurrentState.ExitState (owner);
    23.            
    24.             CurrentState = _newstate;
    25.             CurrentState.EnterState (owner);
    26.  
    27.  
    28.         }
    29.            
    30.  
    31.         public void Update()
    32.         {
    33.             if (CurrentState != null)
    34.                 CurrentState.UpdateState (owner);
    35.         }
    36.     }
    37.  
    38.     public abstract class State<T> {
    39.  
    40.        
    41.         public GameObject NPC;
    42.    
    43.  
    44.         public void Inputs (T _owner)
    45.         {
    46.             // some needful resources
    47.         }
    48.  
    49.         public abstract void EnterState (T _owner);
    50.         public abstract void ExitState (T _owner);
    51.         public abstract void UpdateState (T _owner);
    52.     }
    53. }
    3 state classes inherit state<T>
    public class FirstState : State<AI> {}
    public class SecondState : State<AI> {}
    public class ThirdState : State<AI> {}

    they use value provided from state<T>

    now one monobehaviour class which will be attached to enemy
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using StateStuff;
    5.  
    6. public class AI : MonoBehaviour {
    7.  
    8.     public StateMachine<AI> stateMachine { get; set; }
    9.     GameObject enemy;
    10.  
    11.     // Use this for initialization
    12.     private void Start () {
    13.         enemy = this.gameObject;
    14.         stateMachine = new StateMachine<AI> (this);
    15.         stateMachine.Changestate (FirstState.Instance);
    16.     }
    17.    
    18.     // Update is called once per frame
    19.     private void Update () {
    20.         stateMachine.Update ();
    21.     }
    22.  
    23.  
    24.  
    25. }
    now my question is I want to set NPC = enemy but I don't have any idea how to pass it
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    If it's attached to the enemy, you can just set

    enemy = this.gameObject; 

    in Start. Monobehaviour has its own built-in reference to the GameObject.

    If you want to set it using the inspector,
    add the
     [SerializeField] 
    directive above the declaration.

    Edit: Oops, I misunderstood your question. You want to set the NPC field of each state? It's just a public member, so can set it with a normal assignment statement.

    I'm not sure about your implementation, though. You have a reference to FirstState.instance in your code. is first state a singleton?
     
    Last edited: Sep 21, 2018
  3. Hanross

    Hanross

    Joined:
    Aug 11, 2018
    Posts:
    11
    thank you for your reply

    Code (CSharp):
    1. using UnityEngine;
    2. using StateStuff;
    3.  
    4. public class FirstState : State<AI> {
    5.  
    6.     private static FirstState _Instance;
    7.  
    8.  
    9.  
    10.     private FirstState()
    11.     {
    12.         if (_Instance != null)
    13.             return;
    14.  
    15.         _Instance = this;
    16.     }
    17.  
    18.     public static FirstState Instance
    19.     {
    20.         get{
    21.             if (_Instance == null)
    22.                 new FirstState ();
    23.  
    24.             return _Instance;
    25.         }
    26.     }
    27.  
    28.  
    29.        
    30.  
    31.     public override void EnterState (AI _owner)
    32.     {
    33.         Inputs (_owner);
    34.         enemy.hbar = false;
    35.     }
    36.     public override void ExitState (AI _owner)
    37.     {
    38.     }
    39.     public override void UpdateState (AI _owner)
    40.     {
    41.         if (enemy.dead)
    42.             _owner.stateMachine.Changestate (DeadState.Instance);
    43.        
    44.        
    45.         if (_owner.switchState)
    46.         _owner.stateMachine.Changestate (SecondState.Instance);
    47.  
    48.     }
    49. }
    this is the code of FIrstState.cs

    Basically I attach AI.cs to enemy gameobject and using this statemachine enemy change it's state like patrol,alert,attack,pain and dead and all the paramaters set in state<T> so they will used by every state
    but I want to let this statemachine know that it need to perform operations with the object which has attached that AI.cs script for that I need access "enemy of AI.cs into state<T> but I have no idea how to do it
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    Maybe I still don't understand, but can't you just add

    FirstState.instance.NPC=enemy;


    in your AI script?
     
    Hanross likes this.
  5. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    It seems to me that having static states and the NPC field are mutually exclusive. Suppose you have 100 NPCs, each having their own state machine. How would the NPC field even work with all NPCs sharing the same static states?

    From what I can tell, you don't even need the NPC field. Just extract it from _owner.gameObject, although you'd need to add a constraint that T must be of type MonoBehaviour.

    Or, get rid of the static state instances, and have each NPC have their own pool of states. They can easily assign themselves as the state owner if they're the ones responsible for creating the states.
     
  6. Hanross

    Hanross

    Joined:
    Aug 11, 2018
    Posts:
    11
    nope
     
  7. Hanross

    Hanross

    Joined:
    Aug 11, 2018
    Posts:
    11
    well till better solution I just need max 7-8 NPCs so i made few changes in code and it's working fine
    change in State<T>
    public abstract void EnterState (T _owner,GameObject npc);

    in statemachine<T>
    Code (CSharp):
    1. public StateMachine(T _o,GameObject _enemy)
    2.         {
    3.             owner = _o;
    4.             enemy = _enemy;
    5.             CurrentState = null;
    6.  
    7.         }
    8.  
    in Firststate
    Code (CSharp):
    1. public override void EnterState (AI _owner,GameObject _npc)
    2.     {
    3.         Inputs (_owner,_npc);
    4.         enemy.hbar = false;
    5.         Debug.Log (_npc.name);
    6.     }
    well for now I can continue with it
     
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    So does it give you an error message? Does it not do what you want? I guess I still don't know what you're trying to do.

    Also, I've been going under the assumption that you made the FirstState class a singleton on purpose. If you actually wanted to have more than one NPC with that state, then do like BlackPete says
     
  9. Hanross

    Hanross

    Joined:
    Aug 11, 2018
    Posts:
    11
    ok my mistake its not give me error so i can use it thanks mate