- Home /
Passing Strings in as code text?
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
Answer by Azrapse · Oct 10, 2013 at 08:56 PM
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.
I'd strongly advise caching it if it's happening frequently (like in an update loop).
I guess he wants that for debugging. I cannot really see something like this being used seriously for a production version.
Perhaps - doesn't sound that way to me :)
If it was cached then fieldInfo.GetValue isn't too expensive, it's the GetField and the GetComponent that would kill it every frame.
Hey guys, Im new to Unity and scripting in general so I wasn't aware GetComponent was expensive. I would have been using this every frame on multiple NGUI labels. What is a least expensive alternative?
Reflection is always slow. However, as Whydoidoit says, if you store the FieldInfo object the first time, you can save a lot of time. I will rewrite my answer to give you a solution with better performance. Stay tuned.
Answer by DarkPixel · Oct 10, 2013 at 03:50 PM
In javascript I'm not sure if it's possible, but in C# it's possible.
Related answer: C# Reflection - Get All Public Variables from Custom Script
Your answer
Follow this Question
Related Questions
Shot Counter Question 2 Answers
What's the difference between GetComponent and GetComponent(StringName)? 1 Answer
how to randomly pick a string from an array 3 Answers
Unity Shutdown 1 Answer
PlayerPrefs for saving strings 1 Answer