Forum rules - please read before posting.

Problem accessing global variables in custom action script

Hi all - thanks for stopping by. Apologies in advance if this turns out to be something stupid that I've done/not done - it's my first AC project.

Summary: It appears that local and global variables are not being correctly accessed by a custom action script I'm writing e.g. a global integer variable that increases by 1 every second always shows as 0 when output to the debug log by the custom script.

Windows 10 (auto-updates so fairly up-to-date)
Unity version 2020.3.22f1 Personal
AC version 1.74.5

I have a global integer variable (GlobalTimer) that starts at 0 when the game starts for the first time and is increased by 1 every second through an ActionList running constantly in the background across all scenes. It works just fine as far as I can tell. I intend to save the GlobalTimer variable in save games but haven't implemented this yet FYI. This GlobalTimer ActionList is independent from the ActionList I mention below.

In the scenario I'm outlining here, I want to use the GlobalTimer variable to set the clock times in scenes where clocks are shown. The game story starts at 08:00 and runs in real-time, so I can calculate how much to rotate each clock hand using GlobalTimer. I've attempted to do this natively in AC but couldn't quite figure it out so saw it as a good opportunity to give custom actions a go.

The trouble I am having is simply that the value of GlobalTimer doesn't seem to be getting pulled through by my custom action script.

Here's a pic of (hopefully) most of the relevant parts of the Unity editor - https://imgur.com/fwIkzzP

You can see in the console that the top line shows FR as an empty string and GT/H/M/S are all zero. GT should be showing the value of the GlobalTimer variable which would have been at 13 when the log was made. H, M and S are the results of the calculations done using the GlobalTimer variable and are always ending up as zero so the clock hand's rotation doesn't change. Note: if a value of rotation is hard-coded in to the custom script, then rotation occurs and the hard-coded value appears in the log. FR is a pop-up switch which should have been showing some text i.e. this is also not working.

My custom action script that output that debug log line (well, actually a cut down version of the script with only one clock hand) is as follows:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

if UNITY_EDITOR

using UnityEditor;

endif

namespace AC
{

[System.Serializable]
public class ActionSetBreakOutClock : Action
{

    public override ActionCategory Category { get { return ActionCategory.Custom; } }
    public override string Title { get { return "Set Break Out Clock"; } }
    public override string Description { get { return "Sets the hands of the clock to the correct rotation based on Global Timer global variable."; } }

    //GVar myVar = LocalVariables.GetVariable(0);
    GVar gTimer = GlobalVariables.GetVariable ("GlobalTimer");
    GVar FR = GlobalVariables.GetVariable ("FrancoisStatus");

    public GameObject PBhourHand;

    float PBhourDegrees = -1.0f;
    float PBminuteDegrees = -1.0f;
    float PBsecondDegrees = -1.0f;

    public int constantIDhour;

    override public void AssignValues(List<ActionParameter> parameters)
    {
        PBhourHand = AssignFile(constantIDhour, PBhourHand);

    }

    override public float Run()
    {
        if (!isRunning)
        {
            isRunning = true;

            PBhourDegrees = (float)gTimer.IntegerValue * (float)-0.008333334;
            PBminuteDegrees = (float)gTimer.IntegerValue * -0.1f;
            PBsecondDegrees = (float)gTimer.IntegerValue * -6.0f;

            Debug.Log(" FR:" + FR.TextValue + " GT:" + gTimer.IntegerValue + " H:" + PBhourDegrees + " M:" + PBminuteDegrees + " S:" + PBsecondDegrees);

            PBhourHand.transform.Rotate(0.0f, 0.0f, PBhourDegrees, Space.Self);

        }
        isRunning = false;
        return 0f;
    }

if UNITY_EDITOR

    override public void ShowGUI(List<ActionParameter> parameters)
    {
        PBhourHand = (GameObject)EditorGUILayout.ObjectField("PB hour hand:", PBhourHand, typeof(GameObject), true);

        constantIDhour = FieldToID(PBhourHand, constantIDhour);
        PBhourHand = IDToField(PBhourHand, constantIDhour, true);

        AfterRunningOption();
    }

    public override string SetLabel()
    {
        return string.Empty;
    }

endif

}

}

I think the only thing not visible in the linked editor pic is that there is an ActionList Starter component on the parent of the PBBreakOutClockHour gameobject. The AL starter component runs the AL asset seen in the AL Editor. If I understand correctly, this runs each time the scene is started (meaning after being switched to?) so that's how I am trying to trigger the setting of the clock hands.

After checking through the manual, forums and wiki, I've been through several versions of the custom script code and what I have listed here is as good as I have got it so far. I've tried using ID numbers instead of names to identify the global variables. I tried doing the calculations in AssignValues instead of Run. Tried including the AC namespace when initializing the variable.

So I'm a bit stumped. Any advice would be greatly appreciated.

Not sure if it is relevant (way over my head) but you can also see in the editor pic that there is an error that doesn't appear until I press the Unity editor play button to stop running the game in the editor. The error doesn't occur if I cut all of this code out so it is related to this issue but not sure it helps solve it. The error in full is as follows:

InvalidOperationException: EnsureRunningOnMainThread can only be called from the main thread
UnityEngine.Object.EnsureRunningOnMainThread () (at <07c89f7520694139991332d3cf930d48>:0)
UnityEngine.Object.GetInstanceID () (at <07c89f7520694139991332d3cf930d48>:0)
UnityEngine.Object.IsNativeObjectAlive (UnityEngine.Object o) (at <07c89f7520694139991332d3cf930d48>:0)
UnityEngine.Object.CompareBaseObjects (UnityEngine.Object lhs, UnityEngine.Object rhs) (at <07c89f7520694139991332d3cf930d48>:0)
UnityEngine.Object.op_Implicit (UnityEngine.Object exists) (at <07c89f7520694139991332d3cf930d48>:0)
AC.KickStarter.get_runtimeVariables () (at Assets/AdventureCreator/Scripts/Game engine/KickStarter.cs:520)
AC.GlobalVariables.GetVariable (System.String _name, System.Boolean synchronise) (at Assets/AdventureCreator/Scripts/Static/GlobalVariables.cs:119)
AC.ActionSetBreakOutClock..ctor () (at Assets/MondagoAdventure/CustomActions/ActionSetBreakOutClock.cs:20)

Cheers.

Comments

  • edited January 2022

    Welcome to the community, @Alf.

    The error in the Console is indeed pointing to the issue: you're attempting to assign your GVar variables in their declaration, rather than a function.

    When defining a variable, your code needs to be able its initial value at all times. The GlobalVariables script, and the variables it contains, are only accessable at runtime. This is more of a general C# behaviour, rather than one specific to AC, though.

    Since the gTimer and FR variables are only used by the Run function, however, you can get around this just by moving them entirely into that function. Here's a modified script that should resolve it:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    #if UNITY_EDITOR
    
    using UnityEditor;
    #endif
    
    namespace AC
    {
    
        [System.Serializable]
        public class ActionSetBreakOutClock : Action
        {
    
            public override ActionCategory Category { get { return ActionCategory.Custom; } }
            public override string Title { get { return "Set Break Out Clock"; } }
            public override string Description { get { return "Sets the hands of the clock to the correct rotation based on Global Timer global variable."; } }
    
            public GameObject PBhourHand;
    
            float PBhourDegrees = -1.0f;
            float PBminuteDegrees = -1.0f;
            float PBsecondDegrees = -1.0f;
    
            public int constantIDhour;
    
            override public void AssignValues(List<ActionParameter> parameters)
            {
                PBhourHand = AssignFile (constantIDhour, PBhourHand);
            }
    
            override public float Run()
            {
                GVar gTimer = GlobalVariables.GetVariable ("GlobalTimer");
                GVar FR = GlobalVariables.GetVariable ("FrancoisStatus");
    
                PBhourDegrees = (float) gTimer.IntegerValue * (float) -0.008333334;
                PBminuteDegrees = (float) gTimer.IntegerValue * -0.1f;
                PBsecondDegrees = (float) gTimer.IntegerValue * -6.0f;
    
                Debug.Log(" FR:" + FR.TextValue + " GT:" + gTimer.IntegerValue + " H:" + PBhourDegrees + " M:" + PBminuteDegrees + " S:" + PBsecondDegrees);
    
                PBhourHand.transform.Rotate(0.0f, 0.0f, PBhourDegrees, Space.Self);
                return 0f;
            }
    
            #if UNITY_EDITOR
    
            override public void ShowGUI(List<ActionParameter> parameters)
            {
                PBhourHand = (GameObject)EditorGUILayout.ObjectField("PB hour hand:", PBhourHand, typeof(GameObject), true);
    
                constantIDhour = FieldToID(PBhourHand, constantIDhour);
                PBhourHand = IDToField(PBhourHand, constantIDhour, true);
            }
    
            #endif
    
        }
    
    }
    
  • Thanks very much indeed, @ChrisIceBox - you nailed it.

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.