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

Resolved Noob trying to understand some basic Class constructor / base concepts from this youtube video

Discussion in 'Scripting' started by Smams68, Oct 3, 2023.

  1. Smams68

    Smams68

    Joined:
    May 28, 2023
    Posts:
    11
    Hello, apologies for anyone crazy enough to try and help me. I'm going through this video and recreating a FSM system, and one thing I just can't wrap my head around.

    @08:05

    At this time, the dude sets up a constructor for whenever he initiates a new class
    Code (CSharp):
    1.     public State(Batttlesystem system)
    2.  
    3.     {
    4.        _system = system;
    5.     }
    All well and good. But when he goes to create a class he uses intellisense to auto fill this in for each class and doesn't discuss it at all @ 09:25
    Each class requires something like
    Code (CSharp):
    1.     public BeginState(Batttlesystem system) : base(system)
    2.  
    3.     {
    4.     }
    With nothing in the brackets. What is going on here? What is that :base thing and why does it care about (system)? According to C# doco it's trying to
    "Specify which base-class constructor should be called when creating instances of the derived class"
    That sounds like word salad to my brain. I can't read it.

    It would at least kind of make sense to me if the code was
    Code (CSharp):
    1.     public BeginState(Batttlesystem system) : base(system)
    2.  
    3.     {
    4. _system = system;
    5.     }
    I just don't understand it at all, if we have already declared the constructor in the base, why does each class get pissy if we don't write this in again each time?
    Is there a simpler, less abstract why to write or understand this? Please respond to me as if you were responding to a drunken, sleep deprived 7 year old.
    I know it works, but not sure why, and not sure why it's a problem if I don't add it. I really hate this guy's videos, but they are so useful.
     
    Last edited: Oct 3, 2023
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,593
    In C#, you can't inherit Constructors. So in order to satisfy the compiler, we create a new Constructor for the BeginState class. But since we just want to call the same code that State calls, we just call the base constructor. Normally, the base keyword allows us to call methods that are overridden, so you would expect to be able to do something like this.

    Code (CSharp):
    1. public BeginState(Battlesystem system)
    2. {
    3.     base(system); // <== bad, can't do, compiler will complain
    4. }
    But you cannot call a constructor method like a normal method, as constructors are for creating new objects. To remedy that, C# has that thing above which allows us to call the base constructor's code.

    That means this:
    Code (CSharp):
    1. public BeginState(Battlesystem system) : base(system) // <== calls State(system)
    2. {
    3.  
    4. }
    is the same as
    Code (CSharp):
    1. public BeginState(Battlesystem system)
    2. {
    3.     _system = system; // the code pulled from the base class
    4. }
    If you called
    Code (CSharp):
    1. public BeginState(Batttlesystem system) : base(system)
    2. {
    3.     _system = system;
    4. }
    It would essentially be this
    Code (CSharp):
    1. public BeginState(Battlesystem system)
    2. {
    3.     _system = system; // this is from the base class
    4.     _system = system; // this is from your actual line of code, is a repeat
    5. }
     
    Smams68 and Chubzdoomer like this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,711
    Yes there is. This needless silly abstraction of an ULTRA simple programming problem drives me nuts. I actually keep a specific warning paste handy for this.

    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.
     
    Smams68 likes this.
  4. Smams68

    Smams68

    Joined:
    May 28, 2023
    Posts:
    11
    Thank you so much, this was the simple hidden thing I was trying to understand and could not find documentation on. Would have been looking in the wrong place.
     
  5. Smams68

    Smams68

    Joined:
    May 28, 2023
    Posts:
    11
    Thanks KD, there is a fair bit for me to chew on there, I'll take some time to process.
    I managed to get a turn based battle system working using enums a la Brackeys using Update() and conditionals. It worked, but was very clunky and not scalable which led me down FSM rabbit holes.

    I was trialling a more complex battle system with about 15 states (or turns) per round. Using these class based States, I figure I can just pop this in the main CombatSystem script Update() method:

    Code (CSharp):
    1. Update()
    2. { currentClass.Update() }
    In order to call whatever State specific Update functions every frame.

    It seems cleaner so far. I'm almost 50% confident the refactor will in no way backfire or introduce more problems...