C# Static class and methods showing strange behavior along side Unity

51 views Asked by At

I have the following code in place inside of a static class, this is a static method which I call from another Monobehavior object

To give more context on the code, I have an array of 'actions' that need to be 'Act()' one after another, in some scenarios i must wait before an action completes, and sometimes not wait and Act the next action immediately

Below code is an extract from my PlayNextAction Method()

The strange behaviour:

For an action that is "wait for completion" as true, logs from both if and else sections are printing, after executing the if condition correctly it prints (1) in the end and then it proceeds to skip and print (2), it does not execute any other lines. Dequeue is getting called just once, also this does not happen every time, it happens when the "Act" method for some action may have a coroutine in the mix before finish action are called.

Please let me know if i can add more information to this! I am dumbfounded and need help

            if (actionQueue.Count > 0)
            {
                isActionPlaying = true;
                Debug.Log("Dequeue")
                _currentAction = actionQueue.Dequeue();
                if (_currentAction.waitForCompletion)
                {
                    _currentAction.onActionCompleteEvent.AddListener(HandleActionCompleted);
                    Logs.Print("Playing Action " + _currentAction.Name + " waiting for completion!. For the Query: " + _currentAction.Query);
                    _currentAction.Act();
                    (1)Logs.Print("Act called on current action " + _currentAction.Name);
                }
                else
                {
                    Logs.Print("Playing Action " + _currentAction.Name + " NOT waiting for completion!");
                    _currentAction.Act();
                    HandleActionCompleted();
                    (2)Logs.Print("Act called on current action " + _currentAction.Name + " NOT waiting for completion!. For the Query: " + _currentAction.Query);
                }
            }


The entire class:

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Events;
using VRseBuilder.Core.Utility;

namespace VRseBuilder.Core.NoCode.Utility
{
    public static class ActionManager
    {
        private static Queue<PlayableAction> actionQueue = new Queue<PlayableAction>();
        private static bool isActionPlaying = false;

        private static PlayableAction _currentAction = null;
        public static UnityEvent onPlayableActionSequenceCompleted = new UnityEvent();


        // Method to add actions to the queue and start the sequence if not already started
        public static void PlayActionsInSequence(PlayableAction[] actions)
        {
            foreach (var action in actions)
            {
                actionQueue.Enqueue(action);
                Logs.Print("Adding to the current queue is:" + action.Name);
            }
            Logs.Print("The current length of action queue after clearing is :" + actionQueue.Count);
            if (!isActionPlaying)
            {
                PlayNextAction();
            }
        }

        // Plays the next action in the queue
        private static void PlayNextAction()
        {
            if (actionQueue.Count > 0)
            {
                isActionPlaying = true;
                _currentAction = actionQueue.Dequeue();
                if (_currentAction.waitForCompletion)
                {
                    _currentAction.onActionCompleteEvent.AddListener(HandleActionCompleted);
                    Logs.Print("Playing Action " + _currentAction.Name + " waiting for completion!. For the Query: " + _currentAction.Query);
                    _currentAction.Act();
                    Logs.Print("Act called on current action " + _currentAction.Name);
                }
                else
                {
                    Logs.Print("Playing Action " + _currentAction.Name + " NOT waiting for completion!");
                    _currentAction.Act();
                    HandleActionCompleted();
                    Logs.Print("Act called on current action " + _currentAction.Name + " NOT waiting for completion!. For the Query: " + _currentAction.Query);
                }
            }
            else
            {
                isActionPlaying = false;
            }
        }

        // Handles the completion of an action
        private static void HandleActionCompleted()
        {
            Logs.Print("Entered Handle Action Completed the count for actionQueue is" + actionQueue.Count);
            _currentAction.onActionCompleteEvent.RemoveListener(HandleActionCompleted);
            isActionPlaying = false;
            if (actionQueue.Count <= 0)
            {
                Logs.Print("All the actions in the queue played!");
                onPlayableActionSequenceCompleted?.Invoke();
                return;
            }
            if (actionQueue.Peek() != null)
            {
                PlayNextAction();// Unsubscribe to prevent memory leaks
            } // Play the next action in the sequence
        }
        // Adds an array of PlayableActions to the queue and starts the sequence if not already playing
        public static void AddActionsAndPlay(PlayableAction[] actions)
        {
            foreach (var action in actions)
            {
                actionQueue.Enqueue(action);
            }

            if (!isActionPlaying)
            {
                PlayNextAction();
            }
        }
        // CLears and then adds an array of PlayableActions to the queue and starts the sequence if not already playing
        public static void ClearPreviousAndPlayActionSet(PlayableAction[] actions)
        {
            if (_currentAction != null && isActionPlaying)
            {
                _currentAction.SkipAction();
                _currentAction.onActionCompleteEvent.RemoveListener(HandleActionCompleted);
            }
            //_currentAction.SkipAction();
            actionQueue.Clear();
            isActionPlaying = false;
            PlayActionsInSequence(actions);
        }


        // Adds a single PlayableAction to the queue
        public static void AddAction(PlayableAction action)
        {
            actionQueue.Enqueue(action);

            if (!isActionPlaying)
            {
                PlayNextAction();
            }
        }
        // Skips the current action without automatically proceeding to the next action in the queue
        public static void SkipCurrentAction(bool proceedToNext = true)
        {
            Debug.Log("Skipping Current Action");
            if (isActionPlaying)
            {
                // Assuming currentAction represents the currently playing action
                _currentAction?.SkipAction();
                _currentAction.onActionCompleteEvent.RemoveListener(HandleActionCompleted); // Unsubscribe

                isActionPlaying = false; // Stop the playback sequence

                if (proceedToNext)
                {
                    PlayNextAction(); // Proceed to next action only if specified
                }
            }
        }
        public static void PlayActionImmediately(PlayableAction action)
        {
            // Clear the queue of any pending actions
            actionQueue.Clear();

            // Unsubscribe from the current action's completion event and stop it if it's playing
            if (isActionPlaying)
            {
                // Assuming there's a way to get the currently playing action
                // This could be tracked by updating a currentAction variable in the PlayNextAction method
                // For simplicity in this example, we'll just skip the current action
                SkipCurrentAction(); // Note: Adjust SkipCurrentAction to not automatically play the next action in the queue
            }

            // Reset the playing flag as we're manually handling the next action
            isActionPlaying = false;

            // Add the new action to the queue and play it
            AddAction(action);
        }
    }

}

1

There are 1 answers

0
Epiczzor On BEST ANSWER

There was a cyclic dependency that was messing with the code flow, deeper debugging helped reveal that!