Forum rules - please read before posting.

On exit AC Trigger causes NullReferenceException on scene change

I have a simple AC scene with a GameObject with a Trigger AC component attached.

The properties of the Trigger AC component are the following:

Trigger AC component

Then I have another GameObject with a Hotspot, that, when clicked, it switches to the 'MainMenu' scene of the game like so:

MainMenu hotspot

I click on the area inside the Trigger AC collider to move the character inside of it. Then as soon as the character reaches inside this area, I click on the Hotspot that triggers the scene transition.

Most of the times (not always) I get two identical NullReferenceException errors right after I click on the Hotspot (although the scene does switch to the main menu):

NullReferenceException: Object reference not set to an instance of an object
AC.StateHandler.get_gameState () (at Assets/AdventureCreator/Scripts/Game engine/StateHandler.cs:536)
AC.AC_Trigger.IsObjectCorrect (UnityEngine.GameObject obToCheck) (at Assets/AdventureCreator/Scripts/Logic/AC_Trigger.cs:338)
AC.AC_Trigger.OnTriggerExit2D (UnityEngine.Collider2D other) (at Assets/AdventureCreator/Scripts/Logic/AC_Trigger.cs:150)

Note: The MainMenu scene contains a DefaultPlayerStart2D that spawns the playable character.

Main Setup

Unity version: 2022.3.5f1
AC version: 1.81.6

Settings manager

Interface

Movement method: Point And Click
Input method: Mouse and Keyboard

Camera

Camera perspective: 2D

Comments

  • Open up AC's StateHandler script and replace line 536:

    if (KickStarter.playerInteraction.InPreInteractionCutscene) return GameState.Cutscene;
    

    with:

    if (KickStarter.playerInteraction && KickStarter.playerInteraction.InPreInteractionCutscene) return GameState.Cutscene;
    

    Does that resolve it?

  • Unfortunately not, if a nullability check is added for playerInteraction then a NullReferenceException is produced because of the checks that follow right after that:

    if (KickStarter.actionListManager.IsGameplayBlocked ())

    and

    if (KickStarter.playerInput.IsInConversation (true))

    and even if I add nullability checks there for actionListManager and playerInput, then I get a NullReferenceException in AC_Trigger line 296:

    KickStarter.playerInteraction.DeselectHotspot (false);

    I am wondering whether it makes sense for the gameState getter to return the GameState.Normal value if a manager instance is not available, instead of GameState.Paused.

    I don't know how this change will affect other AC subsystems, but if the gameState getter had something like:

    if (KickStarter.playerInteraction == null) return GameState.Paused;

    then the AC_Trigger IsObjectCorrect() method would return false and wouldn't call its Interact() method.

    Here's my modified version of the gameState getter that doesn't produce any errors:

            /** The current state of the game (Normal, Cutscene, Paused, DialogOptions) */
            public GameState gameState
            {
                get
                {
                    if (inScriptedPause) return GameState.Paused;
    
                    if (KickStarter.playerMenus.ArePauseMenusOn ())
                    {
                        if (KickStarter.actionListManager.IsGameplayBlockedAndUnfrozen ())
                        {
                            return GameState.Cutscene;
                        }
                        return GameState.Paused;
                    }
    
                    if (inScriptedCutscene) return GameState.Cutscene;
                    if (KickStarter.mainCamera && KickStarter.mainCamera.IsShowingForcedOverlay ()) return GameState.Cutscene;
                    if (KickStarter.playerInteraction == null) return GameState.Paused;
                    if (KickStarter.playerInteraction.InPreInteractionCutscene) return GameState.Cutscene;
    
                    if (KickStarter.actionListManager == null) return GameState.Paused;
                    if (KickStarter.actionListManager.IsGameplayBlocked ())
                    {
                        return GameState.Cutscene;
                    }
    
                    if (KickStarter.playerInput == null) return GameState.Paused;
                    if (KickStarter.playerInput.IsInConversation (true))
                    {
                        return GameState.DialogOptions;
                    }
                    return GameState.Normal;
                }
            }
    
  • edited September 2024

    Another way this can be approached without altering the gameState getter is having the AC_Trigger class listen for the OnBeforeChangeScene and maybe disable itself so it doesn't listen for the produced trigger events (e.g. OnTriggerExit2D), given that based on my tests the OnBeforeChangeScene event is produced before the OnTriggerExit2D one.

    Update:

    Turns out disabling the AC_Trigger component (enabled = false) or even de-activating the whole gameobject (gameObject.SetActive(false);) doesn't prevent the OnTrigger* events from being produced, so extra checks need to be added there to ensure that the component / GameObject are disabled before proceeding into calling the Interact() method. Strange.

  • I would like to recreate the original issue before delving further into a potential fix, but I cannot so far.

    Can you PM me your Managers + scene file to test directly?

  • I will attempt to replicate the issue on the demo project and I will PM you the files.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.