using System.Collections.Generic; using System.ComponentModel; using UnityEngine; using UnityEngine.SceneManagement; using Component = UnityEngine.Component; namespace Unity.VisualScripting { /// /// Component that handles the variables that you can use in the Script Graphs of your project. /// /// /// This component is automatically added to a GameObject when a is /// added, or when (Script) are created using the “Visual Scripting Scene Variables” /// menu in the Hierarchy. /// /// The component manages the object variables for any GameObject /// that you add it to. You can access these variables from the Object Variables section of the Blackboard /// of any associated with the GameObject. /// /// The component also manages the scene variables for any “VisualScripting SceneVariables” /// GameObject that you add it to. You can access these scene variables from the Scene Variables /// section of the Blackboard of any you add to this same scene. /// /// /// Note: It's best not to add a component to a GameObject that also /// includes the (Script). If you do this, the Blackboard displays Scene /// Variables that are also present in Object Variables and this can cause confusion. /// /// For more information on how to interact with Variables, refer to the User Manual. /// /// /// The following example shows how to programmatically change the value of a variable used in a Visual Scripting graph. /// Every time you press the Space key, we double the value of the velocity variable. /// Note: You can try this example in a Script Graph. /// /// /// [AddComponentMenu("Visual Scripting/Variables")] [DisableAnnotation] [IncludeInSettings(false)] [VisualScriptingHelpURL(typeof(Variables))] public class Variables : LudiqBehaviour, IAotStubbable { /// /// Retrieves a collection of the variables set in the Variables component. /// [Serialize, Inspectable] public VariableDeclarations declarations { get; internal set; } = new VariableDeclarations() { Kind = VariableKind.Object }; /// /// Retrieves a collection of graph variables for a given graph. /// /// The reference to a graph. /// If the graph is instantiated, returns the graph variables of that instantiated graph. /// Otherwise, returns the graph variables from the definition of the given graph (i.e.: from the graph asset definition) /// /// If is null. /// public static VariableDeclarations Graph(GraphPointer pointer) { Ensure.That(nameof(pointer)).IsNotNull(pointer); if (pointer.hasData) { return GraphInstance(pointer); } else { return GraphDefinition(pointer); } } /// /// Retrieves a collection of graph variables of an instantiated graph. /// /// The reference to a graph. /// A collection of graph variables of an instantiated graph. /// /// If the graph data cannot be read. Which probably means that the graph is not instantiated. /// public static VariableDeclarations GraphInstance(GraphPointer pointer) { return pointer.GetGraphData().variables; } /// /// Retrieves a collection of graph variables from the definition of a graph. /// /// The reference to a graph. /// A collection of graph variables of a given graph. public static VariableDeclarations GraphDefinition(GraphPointer pointer) { return GraphDefinition((IGraphWithVariables)pointer.graph); } /// /// Retrieves a collection of graph variables from the definition of a graph. /// /// The reference of a graph /// A collection of graph variables of a given graph. public static VariableDeclarations GraphDefinition(IGraphWithVariables graph) { return graph.variables; } /// /// Retrieves a collection of the object variables of a given . /// /// The whose object variables will be returned. /// A collection of the object variables contained in the Variables component of the that was passed as a parameter. /// If the doesn't have a Variables component, it is supplied with one by default and the returned collection is empty. public static VariableDeclarations Object(GameObject go) => go.GetOrAddComponent().declarations; /// /// Retrieves a collection of the object variables of a given . /// /// The whose 's object variables are returned. /// A collection of object variables contained in the Variables component of the 's . /// If the GameObject does not have a Variables component, a Variables component is added to the and the returned collection is empty public static VariableDeclarations Object(Component component) => Object(component.gameObject); /// /// Retrieves a collection of scene variables for a given Scene. /// /// The Scene whose scene variables are returned. /// A collection of scene variables contained in the Variables component associated with the (Script). /// /// If is null. /// public static VariableDeclarations Scene(Scene? scene) => SceneVariables.For(scene); /// /// Retrieves a collection of scene variables for a given Scene. /// /// A whose Scene will be accessed to get its variables. /// A collection of scene variables contained in the Variables component associated with the (Script). /// /// If the `go.scene` is null. /// public static VariableDeclarations Scene(GameObject go) => Scene(go.scene); /// /// Retrieves a collection of scene variables for a given Scene. /// /// A whose 's Scene's scene variables will be returned. /// A collection of scene variables contained in the Variables component associated with the (Script). /// /// If the `component.go` or `component.go.scene` is null. /// public static VariableDeclarations Scene(Component component) => Scene(component.gameObject); /// /// Retrieve a collection of the scene variables of the active scene. /// public static VariableDeclarations ActiveScene => Scene(SceneManager.GetActiveScene()); /// /// Retrieve a collection of the application variables. /// public static VariableDeclarations Application => ApplicationVariables.current; /// /// Retrieve a collection of the saved variables. /// public static VariableDeclarations Saved => SavedVariables.current; /// /// Check if a Variables component exists on the passed as a parameter. /// /// The we want to check for the Variables component. /// True if the has a Variables component. Otherwise, returns false. public static bool ExistOnObject(GameObject go) => go.GetComponent() != null; /// /// Check if a Variables component exists on the 's passed as a parameter. /// /// A for which we want to know if the has a Variables component. /// True if the 's has a Variables component. Otherwise, returns false. public static bool ExistOnObject(Component component) => ExistOnObject(component.gameObject); /// /// Check if there is a SceneVariables component instantiated to find out if the scene contains scene variables. /// /// A Scene we want to check for scene variables. /// True if the Scene is not null and contains scene variables. Otherwise, returns false. public static bool ExistInScene(Scene? scene) => scene != null && SceneVariables.InstantiatedIn(scene.Value); /// /// Check if there is a SceneVariables component instantiated to find out if the active scene contains scene variables. /// /// Returns true if the active scene contains scene variables. Otherwise, returns false. public static bool ExistInActiveScene => ExistInScene(SceneManager.GetActiveScene()); [ContextMenu("Show Data...")] protected override void ShowData() { base.ShowData(); } /// /// Don't use this method. It is for Unity Visual Scripting internal usage only. /// [EditorBrowsable(EditorBrowsableState.Never)] public IEnumerable GetAotStubs(HashSet visited) { // Include the constructors for AOT serialization // https://support.ludiq.io/communities/5/topics/3952-x foreach (var declaration in declarations) { var type = declaration.value?.GetType(); if (type == null) continue; // UVSB-2576: When the type is or inherits from AudioMixer (eg: AudioMixerController inherits from AudioMixer), its constructor shouldn't be added to AotStubs: // - AudioMixer is a singleton that refers to a specific asset and shouldn't be instantiated. // - AudioMixerController has a public constructor but is an Editor type and shouldn't be part of AotStubs. const string audioMixerTypeName = "UnityEngine.Audio.AudioMixer"; const string audioControllerTypeName = "UnityEditor.Audio.AudioMixerController"; if (!string.IsNullOrEmpty(type.FullName) && (type.FullName.Contains(audioMixerTypeName) || type.FullName.Contains(audioControllerTypeName))) continue; var defaultConstructor = type.GetPublicDefaultConstructor(); if (defaultConstructor != null) { yield return defaultConstructor; } } } } }