I’m trying to make a script that I can attach to my GUI text and then only have to edit Inspector values to make it work, instead of making a new script every time. The following code is more like pseudocode, the idea being I give it the object, script and variable and it will change the text to what ever value it finds. What will make the following work?
var objectToGetScriptFrom : GameObject;
var scriptName : String = "Script Name";
var variableName : String = "Variable Name";
function Start () {
}
function Update ()
{
var text = objectToGetScriptFrom.GetComponent(scriptName).variableName;
UILabel.text = text.ToString();
}
Thanks
Create a new C# script called ComponentBinder.cs, then delete the default contents and replace with this instead:
using System;
using System.Reflection;
using UnityEngine;
public class ComponentBinder : MonoBehaviour
{
public enum BindValueMode {BindValueToString, BindObjectValue};
[Serializable]
public class BindingEnd
{
[SerializeField]
public GameObject gameObject;
[SerializeField]
public string componentName;
[SerializeField]
public string member;
protected MonoBehaviour component;
public MonoBehaviour Component
{
get
{
if(component == null && gameObject != null)
{
component = gameObject.GetComponent(componentName) as MonoBehaviour;
}
return component;
}
}
protected MemberInfo memberInfo;
public MemberInfo MemberInfo
{
get
{
if(memberInfo == null && Component != null)
{
memberInfo = Component.GetType().GetField(member);
if(memberInfo == null)
{
memberInfo = Component.GetType().GetProperty(member);
}
}
return memberInfo;
}
}
public object Value
{
get
{
try
{
if(MemberInfo != null)
{
if(MemberInfo is FieldInfo)
{
return (MemberInfo as FieldInfo).GetValue(component);
} else
{
return (MemberInfo as PropertyInfo).GetValue(component, null);
}
}
}
catch{}
return null;
}
set
{
try
{
if(MemberInfo != null)
{
if(MemberInfo is FieldInfo)
{
(MemberInfo as FieldInfo).SetValue(component, value);
} else
{
(MemberInfo as PropertyInfo).SetValue(component, value, null);
}
}
}
catch{}
}
}
public override int GetHashCode()
{
return gameObject.GetHashCode () ^ componentName.GetHashCode() ^ member.GetHashCode();
}
public void Rebind()
{
component = null;
memberInfo = null;
}
}
public BindingEnd source;
public BindingEnd target;
public BindValueMode BindMode;
protected int previousSourceHash;
protected int previousTargetHash;
// Update is called once per frame
void Update ()
{
if(source.GetHashCode() != previousSourceHash)
{
source.Rebind();
previousSourceHash = source.GetHashCode();
}
if(target.GetHashCode() != previousTargetHash)
{
target.Rebind();
previousTargetHash = target.GetHashCode();
}
if(source.MemberInfo != null && target.MemberInfo != null)
{
if(BindMode == BindValueMode.BindValueToString)
{
target.Value = source.Value.ToString ();
}
else
{
target.Value = source.Value;
}
}
}
}
Attach this script to some game object, although it doesn’t necessarily need to be the UI labels if you prefer keeping all bindings in one centralized place.
This scripts shows this inspector:
What this script does is letting you select a source of values and a target for those values. For example, you can select a game object, script name and field/property for Source, and another game object, script name and field/property for Target.
If all the names are right every frame the value in the source Game Object/Script/Member will be copied to the target Game Object/Script/Member. You can select if what is copied is the source value.ToString() or the plain value. In this last case make sure both source and target Members are of compatible types. If you choose the first mode, then make sure the target member is of string type.
I have written it so that you can change the objects, script names and member names on the fly, in the inspector, while the game is running, just in case you want to test stuff quickly.
If you write wrong member or script names, no errors will be thrown. Make sure you type the member names as they appear in the code, not as they appear in the inspector.
In javascript I’m not sure if it’s possible, but in C# it’s possible.
C# Reflection
Related answer:
C# Reflection - Get All Public Variables from Custom Script