Forum rules - please read before posting.

Using a Component Variable inside a custom Script

edited October 2019 in Technical Q&A

Hey folks!

I want to use a simple bool - I set up inside the AC-Component-Variables-Script - inside a custom script. (for savegame reasons)

I have attached the following two AC-Scripts to the GameObject FlowerTower:

-Variables (I setup a bool, ID 0, initial value: false, Link to: Custom Script)
- Remember Variables

I access the bool var during a script this way:

using AC;
.....
 public GVar myVariable; // I can nicely see all the possible values inside the Inspector 
.....

void Start()
    {
        myVariable = FlowerTower.GetComponent<Variables>().GetVariable(0);

        if (myVariable.val == 1) 
            FlowerTower.SetActive(false);  // but it's not working even though val is set to 1
    }

When I start the game the AC variable Inspector shows me that the bool var is set to false correctly. Later when I do my Action during gameplay with "myVariable.SetValue(1);" its correctly shifting to 1 (from 0) but for some reason "if (myVariable.val == 1) " is not recognizing that change after I chance scenes and come back. But I can see the correct Variable-setting inside the AC Component Variables Inspector as well as in "public GVar myVariable;". When I switch scenes val is still set to 1 (correctly).

If I try "if (myVariable.val == 0) " before I do my action during gameplay it works perfectly.

Am I missing something important in my script?

Thanks for your help!

Comments

  • Welcome to the community, @miccel123.

    I'm not quite sure of the context, here. What is it you're ultimately trying to achieve here? Component variables can be read/set through Actions - you don't need to resort to a custom script for that purpose alone.

    So this issue occurs when re-entering the scene? It's likely that this is due to the order in which scripts are called. The variable values aren't persistent - they have to be loaded in by AC upon changing scene.

    You've set the variable's Link to value to Custom Script, but method that involves hooking into the OnDownloadVariable / OnUploadVariable custom events, rather than creating a script reference to the variable directly.

    See the Manual's "Linking with custom scripts" chapter, as well as the provided VariableLinkingExample script. That demonstrates the linking of a global integer variable, but the equivalent for a component bool is similar:
    using UnityEngine;

    namespace AC
    {
    
        public class ComponentVarLink : MonoBehaviour
        {
    
            public bool myCustomBool = false;
            public int variableIDToSyncWith = 0;
    
            private void OnEnable ()
            {
                EventManager.OnDownloadVariable += OnDownload;
                EventManager.OnUploadVariable += OnUpload;
            }
    
            private void OnDisable ()
            {
                EventManager.OnDownloadVariable -= OnDownload;
                EventManager.OnUploadVariable -= OnUpload;
            }
    
            private void OnDownload (GVar variable, Variables variables)
            {
                if (variable.id == variableIDToSyncWith && variables == GetComponent<Variables>())
                {
                    variable.BooleanValue = myCustomBool;
                }
            }
    
            private void OnUpload (GVar variable, Variables variables)
            {
                if (variable.id == variableIDToSyncWith && variables == GetComponent<Variables>())
                {
                    myCustomBool = variable.BooleanValue;
                }
            }
    
        }
    
    }
    
  • edited November 2019

    Thanks for your reply!

    I setup the script correctly (I use an int and named the varibale ALIVE (0) instead of my previous bool) and whenever I shoot an enemie (Adventure Game with survival elements) the variable inside the Component (variables script) is correctly set to int ALIVE 1) After switching scenes the int is still correctly set to 1 but my enemie still spawns even though I use

       KillZombie = Zombie.GetComponent<VariableLinkingExample>();
            myVariable = Zombie.GetComponent<Variables>().GetVariable(0);
    
    if (myVariable.val == 1 || KillZombie.myCustomInteger == 1)
                    Zombie.SetActive(false);
    

    The funny thing is: If I set the initial value of int ALIVE manually to 1 before I start the game the enemie isn't spawning and everything works perfectly.

  • There's no need to check for both. If you access the Variables component directly (i.e. set "myVariable"), then you can ignore myCustomInteger.

    When is this code being run? To ensure it's run once AC's own loading code has completed (and so it's had a chance to update the Variable values correctly), you can do so from the OnAfterChangeScene custom event:

    using UnityEngine;
    using AC;
    
    public class OnSceneChangeExample : MonoBehaviour
    {
    
        private void OnEnable ()
        {
            EventManager.OnAfterChangeScene += OnAfterChangeScene;
        }
    
    
        private void OnDisable ()
        {
            EventManager.OnAfterChangeScene -= OnAfterChangeScene;
        }
    
        private void OnAfterChangeScene (LoadingGame loadingGame)
        {
            if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
            {
                // De-activate the zombie
            }
        }
    
    }
    
  • edited November 2019

    Thank you!

    I have updated the code but still no luck here.

    It's showing the exact same behavior: The zombie is still spawning even though int ALIVE is correctly set to 1 during gameplay and still remains 1 after scene change. (When I chance int ALIVE inside Variables.cs inspector manually before starting the game from 0 to 1 the zombie prefab isn't spawning which is correct)

    I also tried this here to ensure that the overall functionality is given:

    void Update ()
    {
         if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
            {
                Zombie.SetActive(false);
            }
    }
    

    In that scenario the Zombie disappears in the very moment "GetVariable(0).IntegerValue is set to 1. After switching scenes int ALIVE is still correctly set to 1 but Update() is not recognizing the new value so doesn't my Start().

    void Start()
    {
        if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
        {
              Zombie.SetActive(false);
        }
    }
    

    full Code:

        using System.Collections;
        using System.Collections.Generic;
        using UnityEngine;
        using com.ootii.Actors.AnimationControllers;
        using com.ootii.Actors;
        using BehaviorDesigner.Runtime;
        using RootMotion.Dynamics;
        using RootMotion;
        using AC;
    
        public class HealthSystem : MonoBehaviour
        {
            protected MotionController mMotionController = null;
    
            public int health;
            public PuppetMaster Puppet;
            public GameObject PuppetColliders;
            bool deathcheck;
            public GameObject Zombie;
    
            VariableLinkingExample KillZombie;
            public GVar myVariable;
    
            void Start()
            {
                myVariable = Zombie.GetComponent<Variables>().GetVariable(0);
                mMotionController = this.GetComponent<MotionController>();
    
                 if (myVariable.val == 1)
                     Zombie.SetActive(false);
    
                health = Random.Range(3, 6);
                deathcheck = true;
            }
    
            private void OnEnable()
            {
                EventManager.OnAfterChangeScene += OnAfterChangeScene;
            }
    
    
            private void OnDisable()
            {
                EventManager.OnAfterChangeScene -= OnAfterChangeScene;
            }
    
            private void OnAfterChangeScene(LoadingGame loadingGame) // NEW
            {
                if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
                {
                    Zombie.SetActive(false);
                }
            }
    
     void Update () // TERRIBLE CODE!! Just for test purposes
    {
         if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
            {
                Zombie.SetActive(false); // not working after scene change
            }
    }
    
            public void DecreaseHealth()
            {
                health--;
    
                if (health <= 0 && deathcheck)
                {
                    deathcheck = false;
                    MotionControllerMotion lMotion = mMotionController.GetMotion(0, "Crawling");
                    mMotionController.ActivateMotion(lMotion);
                    KillZombie.myCustomInteger = 1; // one way to change from 0 to 1
                    myVariable.SetValue(1); //2nd way to change its value
                    //this.GetComponent<ActorController>().enabled = false;
                    //this.GetComponent<MotionController>().enabled = false;
                    this.GetComponent<UnityEngine.AI.NavMeshAgent>().enabled = false;
                    this.GetComponent<BehaviorTree>().enabled = false;
                    //this.GetComponent<CharacterController>().enabled = false;
                    //Destroy(this.GetComponent<CharacterController>());
                    Puppet.Kill();
    
                    ZombieHealth[] colliders = Puppet.GetComponentsInChildren<ZombieHealth>();
                    foreach (ZombieHealth kills in colliders)
                        kills.enabled = false;
                }
            }
        }
    
  • My code snippet was assuming that the Variables component is attached to the same GameObject as the script. If it's instead attached to Zombie (as you have in your Start function), replace:

        if (GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
    

    with:

        if (Zombie.GetComponent<Variables>().GetVariable(0).IntegerValue == 1)
    
  • edited November 2019

    Dear Chris!

    Such a stupid mistake I made.

    Thank you very much for your help!

    It works perfectly now.

    :) :) :) :) :)

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.