- Home /
Is it possible to pick reference variables from one component, in another (different) component via the inspector?
I've been searching on this, and as with most questions I post, there's probably an easy answer here that I'm just not finding or formatting my search to find.
Here's the setup:
- Component Script A includes:
public float myFloat
public int myInt
- Component Script B has:
public {variable}
The idea being that, in the inspector I can attach Component Script B to an object, and through the inspector pick the GameObject that has Component Script A, and choose "myFloat" as the variable to reference inside of Component Script B.
Is this even possible?
Here's what I'm trying to do:
I'd like to make a simple script that can be attached to UI text objects to auto-update their displayed text values to match that of the referenced variable value (like the above example) - but I don't want to have to write a lot of small scripts to find and make these references at run time (which I already know how to do).
So - with that intention, perhaps there's a different way to accomplish this?
Per the usual, everyone here is awesome and I appreciate any input/help/guidance that could be provided - thanks!
Answer by Extrys · Oct 16, 2019 at 12:50 PM
There is another solution you can use! @Glurth method is ok, but you are coupling your classes in that way.
The way to accomplish that without boilerplate code is... Scriptable Objects!
ScriptableObjects are like monobehaviours, without being GameObjects haha!
You can create an instance of a class inside the assets folder,
and use that instance in your classes as a draggable value in the inspector,
then you will be using the same instance of the shared variable.
Both classes are using the SAME instance that contains the variable.
In fact you can create events for variable changes!
You just need to create a ScriptableObject called "SharedFloat" (for example) it should have a float variable types to share!
using System;
using UnityEngine;
[CreateAssetMenu]
public class SharedFloat : ScriptableObject
{
//You need to asign an initial and current values, because
//scriptable objects doesnt reset their state on application quit
[SerializeField] float initialValue, currentValue;
//The public property to access to operate with the current value
public float Value
{
get => currentValue;
set
{
//if new value is different to the old one then set that value to the currentValue
//and execute all functions subscribed to the OnValueChanged event
if (value != currentValue)
{
currentValue = value;
OnValueChanged();
}
}
}
//the event that is called on when current value is changed
public event Action OnValueChanged;
//here is where the current value copy initial value on start
private void OnEnable() => currentValue = initialValue;
}
Then in the Player and HealthUI Scripts you can do this!
//The Script attached to the player
public class PlayerTest : MonoBehaviour
{
public SharedFloat Health;
//when player gets damage
public void GetDamage(float damage) => Health.Value -= damage;
}
//The Script attached to the UI
public class HPBarTest : MonoBehaviour
{
public SharedFloat Health;
//Subscribe to OnValueChanged at the begining
private void Awake() => Health.OnValueChanged += UpdateHPUI;
void UpdateHPUI()
{
//Do everything what you want here
}
}
Boom! You have now Reactive Shared Variables!
Answer by Glurth · Aug 24, 2016 at 01:58 PM
Uncompiled example (may contain errors, example only):
public class ScriptA:Monobehavior
{
public float Anum;
}
public Class ScriptB:Monobehavior
{
public ScriptA Aref; //this public varaiable, allows you to drag an object with a ScriptA component, onto this field, in the inspetcor.
public float copyOfANum;
void Start()
{
if(Aref!=null)
copyOfANum= Aref.Anum; //after confirming the user HAS indeed provided a reference to a ScriptA component, we can look "into" it, with the "." (dot), to get the number we want.
}
}
But would there be a way to do this without making (in your example) "Aref" ScriptA type-specific?
not with the existsing inspector, no. There is no way to select particular field, of a component, to be dragged.
That being said you COULD define an INTERFACE that provides a way to access Anum, say AnumInterface, and implement this interface in all your components that contain the float (like ScriptA) . Then you can provide a reference to that AnumInterface to script B. "Interfaces" is a fairly advanced c# concept, similar to, but not exactly like, inheritance. Rather than go into detail about that here, I'll suggest you just google search that stuff. Feel free to past back with questions.
Edit: I have not actually implemented interfaces with he unity inspector yet, myself. So note: these comments are just supposition.
@glurth Thanks for the guidance - I'll do some digging and respond if additional questions come up. Thanks!
Your answer
Follow this Question
Related Questions
inspector isnt showing scripts 2 Answers
Variable set twice on the same Update call - Second time doesn't update? 2 Answers
How to expose member variables to the inspector in C#? 1 Answer
Inspector Drop Down for Variables 0 Answers
Is there a way to extend the amount of values for inspector? 0 Answers