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

Question WEapons State Machine using Abstract/Concrete classes, not able to use generic Fire() method

Discussion in 'Scripting' started by SamAdamsUK, Jun 20, 2023.

  1. SamAdamsUK

    SamAdamsUK

    Joined:
    Mar 21, 2023
    Posts:
    8
    Hi All,

    Really hope you can help.

    I'm using a WeaponsStateManager script that inherits from Monobehaviour, and this sets a number of different weapons classes and sets each as the current state depending on weapen used:

    public SniperRifleState srState = new SniperRifleState();
    public RocketLauncherState rlState = new RocketLauncherState();

    I have a WeaponsBaseState script, which is abstract, and has:
    public virtual void Fire() { }

    I then have on each script, e.g. SniperRifleState, an override such as:
    public override void Fire()
    {
    Debug.Log("Fire!!");
    }

    My issue is: On my InputManagerScript,
    public WeaponsBaseState weapons;
    weapons.Fire();

    .. I get a null error whether setting the weapons reference to the abstract, or the concrete class - I am trying to achieve being able to call a generic Fire(), on the same script/reference, regardless of which weapon is currently active.

    Any help very welcome! I am a newbie!

    Thankyou
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Then it doesn't matter, it doesn't require forum posting. Go fix it. Here's how.

    How to fix a NullReferenceException error

    https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

    Three steps to success:
    - Identify what is null <-- any other action taken before this step is WASTED TIME
    - Identify why it is null
    - Fix that


    Beyond that, keep this in mind:

    FSM finite state machines:

    I suggest never using the term "state machine." Instead, just think:

    - I have to keep track of some THING(s)
    - That THING might change due to reasons
    - Depending on that THING, my code might act differently

    That's it. That's all it is. Really!! The classic example is a door:

    - track if it is open or closed
    - if it is open, you could close it
    - if it is closed, you could open it
    - if it is open you could walk through it
    - if it is closed you could bump into it

    Wanna make it more complex? Put a latch on one side of the door.

    This is my position on finite state machines (FSMs) and coding with them:

    https://forum.unity.com/threads/state-machine-help.1080983/#post-6970016

    I'm kind of more of a "get it working first" guy.

    Ask yourself, "WHY would I use FSM solution XYZ when I just need a variable and a switch statement?"

    All generic FSM solutions I have seen do not actually improve the problem space.

    Your mileage may vary.

    "I strongly suggest to make it as simple as possible. No classes, no interfaces, no needless OOP." - Zajoman on the Unity3D forums.


    If you absolutely MUST go CIS-100 on it, instead of inheritance, consider composition:

    Using Interfaces in Unity3D:

    https://forum.unity.com/threads/how...rereceiver-error-message.920801/#post-6028457

    https://forum.unity.com/threads/manager-classes.965609/#post-6286820

    Check Youtube for other tutorials about interfaces and working in Unity3D. It's a pretty powerful combination.


    Unity's component architecture

    https://forum.unity.com/threads/custom-gameobject.967582/#post-6299125
     
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,899
    Most likely your weapons field is becoming null because serialization of an abstract class requires using the [SerializeReference] attribute.

    Also, the field should be named weapon because it's a single weapon, not a collection of weapons. And the base class should be called either WeaponBase or WeaponStateBase because it's best practice to suffix an abstract class with "Base". Personally, I'd go with WeaponBase because "State" doesn't add anything to the name. In fact, a State probably wouldn't have a Fire() method, it would just be a state.