Toggling Events and False Orders

[SOLVED]

OK this is another question that is out of order, but explaining it will be quite easy… it’s just that I can’t think of a way to fix this one, so here goes:

Part of my systems is that I want to be able to call animals in my game (MalberS again, I know…), and my problem here is that when I’m in the water in my game, or driving a boat or within the range of a boat, I want to disable the ability to call those animals (so that they don’t spawn underwater, which is a very real problem that I have in my game)

Now, the problem is that they run on an event-based system (all three systems (finding water, being on a boat, and finding a boat) are inherited from the ‘RangeFinder.cs’ script), so they toggle for a blink of a moment and then shut down, and if they are not in order for any reason (I’ll give an example below, where leaving the boat radius after entering the water is a serious problem for me, which really triggered my brain to start thinking of a solution for this issue), this can be a serious problem

The problem here is… sometimes they will toggle their way into activating the state, when it’s not meant to be turned on, because of the wrong order because of the nature of how these events happen.

For example, if I was supposed to turn it on after I leave the radius of the boat’s entrance, and turn it back off when I enter the water, but I enter the water before I leave the radius of the boat, it will be turned on, because The turn on trigger (leaving the boat radius) happened AFTER the turn off trigger (entering the water) happened… You can guess how much of a disaster this can be, and how it can easily lead to unintended consequences

What’s the best way to go around this problem? I’m not sure if I solved something like this before or not, but… yeah I’m stuck with that one now :sweat_smile: (Just when I thought that I solved my bugs… Apparently, I didn’t solve the logical-errors)

1 Like

OK I solved this one in an interesting way. This time, I didn’t let my intrusive thoughts win and use a static variable

Instead, I used an Interface (again… OK now they’re actually really tempting when you get the hang of them). Before we start, no it didn’t fully solve my problem, but it absolutely solved what it was supposed to solve, and actually made me realize that my problem still exists :sweat_smile:). Here’s what I did:

  1. Create the interface itself. This one will have two functions, an enabler and a disabler (you can go through my description to understand the logic flow):
// THIS INTERFACE KEEPS TRACK OF Malbers' Input ON THE PLAYER COMPONENT, AND ENSURES
// THAT IT DOES NOT RE-ACTIVATE WHEN IT'S NOT SUPPOSED TO, OR 
// DEACTIVATE WHEN IT'S SUPPOSED TO BE TURNED ON

// IT'S CENTRALIZED IN 'PlayerStateMachine.cs', AND USED IN 'PlayerBoatDrivingState.cs',
// 'WaterFinder.cs' and 'BoatFinder.cs' TO MAKE SURE THAT WE DO NOT ACTIVATE MALBERS INPUT
// WHEN WE ARE NOT SUPPOSED TO, EFFECTIVELY ELIMINATING THE LOGIC BUG OF BEING ABLE TO CALL ANIMALS
// WHEN WE ARE ON A BOAT, IN WATER, OR NEAR A BOAT

public interface IMalbersInputHandler 
{
    void EnableMalbersInput();
    void DisableMalbersInput();
}
  1. In ‘PlayerStateMachine.cs’, where the logic is centralized, I implemented the interface, as follows:
// a. write it at the top:
    public class PlayerStateMachine : StateMachine, ITargetProvider, IAimReticleTargetProvider, IMalbersInputHandler /* <-- like this */

// b. Declare a 'MalbersInput' variable (which I did here and updated it in the hierarchy):
        [field: SerializeField] public MalbersInput MalbersInput {get; private set;} // to avoid animal calling during boat-driving

// c. the logic itself:
        // --------------------------------------------------------------- Malbers Input tracker (IMalbersInputHandler Interface logic implementation) -------------------------------------

        public int disableCounter = 0;

        public void EnableMalbersInput()
        {
            disableCounter = Mathf.Max(0, disableCounter - 1); // max the counter to zero (only then, will Malbers' Input be allowed to turn on again)
            UpdateMalbersInputState();
        }

        public void DisableMalbersInput()
        {
            disableCounter++; // only when the disable counter is over zero, do we disable the Malbers' Input script
            UpdateMalbersInputState();
        }

        private void UpdateMalbersInputState() 
        {
            MalbersInput.enabled = disableCounter == 0; // only activate the Malbers Input state when the disable counter is zero
        }

        // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  1. Apply it in ‘WaterFinder.cs’, ‘BoatFinder.cs’ and ‘PlayerBoatDrivingState.cs’:
// in 'WaterFinder.cs':

    // (TEST) MALBERS TRACKER
    private IMalbersInputHandler inputHandler; // same thing as 'PlayerStateMachine' I guess...

// in 'Awake()':
        // TEST:
        inputHandler = GetComponentInParent<PlayerStateMachine>(); // same thing as 'PlayerStateMachine' I guess...


// when you find some water (i.e: water is enabled):
        // TEST:
        inputHandler.DisableMalbersInput();

// when you don't find water (i.e: water is disabled):
        // TEST:
        inputHandler.EnableMalbersInput();
// 4. In 'BoatFinder.cs' (pretty much the same idea):

    // TEST (MALBERS TRACKER)
    private IMalbersInputHandler inputHandler;

    // TEST FUNCTION:
    void Awake() 
    {
        inputHandler = GetComponentInParent<PlayerStateMachine>();
    }

// When you find the boat (AddTarget()):
        // TEST:
        inputHandler.DisableMalbersInput();

// When you don't find the boat (RemoveTarget()):
        // TEST:
        inputHandler.EnableMalbersInput();
// 5. When you're driving and undriving the boat (excuse my grammar for now... My brain is hard on logic right now :sweat_smile:), in 'PlayerBoatDrivingState.cs' (part of my state machine):

// in 'Enter()':
        // TEST:
        inputHandler.DisableMalbersInput();

// in 'Exit()':
        // TEST:
        inputHandler.EnableMalbersInput();

Essentially, it’s a mathematical game that will keep swarming with values above the number zero until you actually leave the water, or boat, or whatever is affecting the call (in this case, driving the boat, finding a boat or finding water), and eventually reset the number to zero, and that’s when you re-enable the script

and only then will you reach zero (when you left all 3 of them) and re-enable the script

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms