Skip to content

Instantly share code, notes, and snippets.

@miguelSantirso
Created February 4, 2016 18:47
Show Gist options
  • Save miguelSantirso/cf6568e45ed37a974ae4 to your computer and use it in GitHub Desktop.
Save miguelSantirso/cf6568e45ed37a974ae4 to your computer and use it in GitHub Desktop.
[Unity] Extremely simple tweaker
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
public class Tweaker : MonoBehaviour
{
[Serializable]
public class TweakableChangedEvent : UnityEvent<string> {}
private static Tweaker instance;
public static Tweaker Instance { get { return instance; } }
#region Tweakables
// INSERT YOUR TWEAKABLES HERE:
[SerializeField]
[Range(0f, 1f)]
public float Example = 0.5f;
#endregion
#region inspector properties
[SerializeField]
private TweakableChangedEvent valueChanged = new TweakableChangedEvent();
#endregion
private Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>();
public TweakableChangedEvent ValueChanged { get { return valueChanged; } }
public List<FieldInfo> GetAllTweakables()
{
return new List<FieldInfo>(fields.Values);
}
public object GetObject(string key)
{
if (!fields.ContainsKey(key))
{
Debug.LogWarningFormat("No tweakable for key \"{0}\"", key);
return default(object);
}
return fields[key].GetValue(this);
}
public void SetObject(string key, object value)
{
var currValue = GetObject(key);
if (value != currValue)
{
var field = fields[key];
var casted = Convert.ChangeType(value, field.FieldType);
fields[key].SetValue(this, casted);
valueChanged.Invoke(key);
}
}
void Awake()
{
if (instance != null)
{
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(this);
IndexFields();
}
private void IndexFields()
{
var tweakerType = typeof(Tweaker);
var allFields = tweakerType.GetFields();
foreach (var field in allFields)
{
if (field.IsNotSerialized) continue;
var key = field.Name;
fields[key] = field;
}
}
}
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class TweakerUI : MonoBehaviour
{
#region inspector properties
[SerializeField]
private Tweaker tweaker;
[SerializeField]
private GameObject[] tweakerUIPrefabs;
#endregion
private Dictionary<string, TweakerUIComponent> components = new Dictionary<string, TweakerUIComponent>();
public void OnValueChanged(string key)
{
if (components.ContainsKey(key))
components[key].SetValue(tweaker.GetObject(key));
else
UdpateUI();
}
TweakerUIComponent InstantiateComponentFor(FieldInfo tweakable)
{
var supportedTypes = new List<System.Type>(){typeof(bool), typeof(int), typeof(float), typeof(string)};
var typeIndex = supportedTypes.FindIndex( type => type == tweakable.FieldType );
if (typeIndex < 0)
Debug.LogErrorFormat("Tweakable type not supported: \"{0}\"", tweakable.FieldType);
var gameObj = (GameObject)Instantiate(tweakerUIPrefabs[typeIndex]);
gameObj.transform.SetParent(transform, false);
var component = gameObj.GetComponent<TweakerUIComponent>();
component.Configure(tweakable);
component.SetValue(tweaker.GetObject(tweakable.Name));
var keyCopy = tweakable.Name;
component.ValueChanged.AddListener((object value) => {
OnComponentChanged(keyCopy, value);
});
return component;
}
void OnComponentChanged(string key, object value)
{
tweaker.SetObject(key, value);
}
void UdpateUI()
{
foreach (var component in components.Values)
{
Destroy(component.gameObject);
}
components.Clear();
var allTweakables = tweaker.GetAllTweakables();
foreach (var tweakable in allTweakables)
{
var component = InstantiateComponentFor(tweakable);
components[tweakable.Name] = component;
}
}
void Start()
{
UdpateUI();
}
}
using UnityEngine;
using UnityEngine.Events;
using System.Reflection;
public abstract class TweakerUIComponent : MonoBehaviour
{
public class ValueChangedEvent : UnityEvent<object> { }
#region inspector properties
[SerializeField]
private ValueChangedEvent valueChanged = new ValueChangedEvent();
#endregion
public ValueChangedEvent ValueChanged { get { return valueChanged; } }
public abstract void Configure(FieldInfo field);
public abstract void SetValue(object value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment