I'm using IMGUI in Unity to make a custom variable debugger which allows me to send it varables of different primitive types and it will draw them on screen without much fuss. (by fuss I mean writing an OnGUI each time I want to check what a variable is doing, or hooking something up with the canvas system.) I know that obviously I can just look at these things in the inspector but with this system I can a) quickly add and remove things, and b) do it at runtime without having to do a development build.
I have a function working that takes in different types of data and does things with it based on its type. The issue is that it only seems to work if I pass the variable by value, and not by ref.
So for example if I send it an int or a float by value it works just fine but when I send it by ref I get this error:
error: CS1503: Argument 1: cannot convert from 'ref int' to 'ref object'
This occurs when AddDebugEntry
is called (whole code is at the bottom of this question):
public void AddDebugEntry(ref object value, string name, DebugDrawStyle style = DebugDrawStyle.Label, float min = 0, float max = 0)
{
DebugEntry newEntry = new DebugEntry(ref value, name, style, min, max);
DebugEntries.Add(newEntry);
}
I beleive this may be something to do with Boxing: Is int (Int32) considered an object in .NET or a primitive (not int?)?
But I'm not sure how to get around it :(
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using UnityEngine;
public class DebugEntry
{
public object m_Value;
public string m_name;
public DebugDrawStyle m_Style;
public float m_min;
public float m_max;
public DebugEntry(ref object mValue, string mName, DebugDrawStyle mStyle, float mMin, float mMax)
{
m_Value = mValue;
m_name = mName;
m_Style = mStyle;
m_min = mMin;
m_max = mMax;
}
}
public enum DebugDrawStyle { Label, Slider }
public class DebugTool : MonoBehaviour
{
#region -- Variable Declaration ------------------------------------------------------------------------------------
public Project currentProject;
public Vector2 DebugPosition;
public Vector2 DebugSize;
private int index = 0;
[SerializeField]
private List<DebugEntry> DebugEntries = new List<DebugEntry>();
#endregion -- End Variable Declaration -----------------------------------------------------------------------------
#region -- Initialisation ------------------------------------------------------------------------------------------
// Start is called before the first frame update
void Start()
{
currentProject.DebuggingTool = this;
}
#endregion -- End Initialisation -----------------------------------------------------------------------------------
#region -- Adding / Removing Entries -------------------------------------------------------------------------------
public void AddDebugEntry(ref object value, string name, DebugDrawStyle style = DebugDrawStyle.Label, float min = 0, float max = 0)
{
DebugEntry newEntry = new DebugEntry(ref value, name, style, min, max);
DebugEntries.Add(newEntry);
}
public void RemoveDebugEntry(string name)
{
for (int i = 0; i < DebugEntries.Count; i++)
{
if (DebugEntries[i].m_name.GetHashCode() == name.GetHashCode())
{
DebugEntries.Remove(DebugEntries[i]);
}
}
}
#endregion -- End Adding / Removing Entries ------------------------------------------------------------------------
#region -- GUI Updates ---------------------------------------------------------------------------------------------
private void OnGUI()
{
index = 0;
foreach (var entry in DebugEntries)
{
index++;
switch (Type.GetTypeCode(entry.m_Value.GetType()))
{
case TypeCode.Int16:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Int32:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Int64:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Decimal:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Double:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Single:
switch (entry.m_Style)
{
case DebugDrawStyle.Label:
DrawLabel(entry);
break;
case DebugDrawStyle.Slider:
DrawSlider(entry);
break;
default:
throw new ArgumentOutOfRangeException();
}
break;
case TypeCode.Boolean:
DrawLabel(entry);
break;
case TypeCode.String:
DrawLabel(entry);
break;
default:
Debug.Log("Type not found");
throw new ArgumentOutOfRangeException();
}
}
}
#endregion -- End GUI Updates --------------------------------------------------------------------------------------
#region -- GUI Draw Functions --------------------------------------------------------------------------------------
void DrawLabel(DebugEntry entry)
{
GUI.Label(new Rect(DebugPosition.x, DebugPosition.y + (DebugSize.y * index), DebugSize.x, DebugSize.y), entry.m_name.ToString());
index++;
GUI.Label(new Rect(DebugPosition.x, DebugPosition.y + (DebugSize.y * index), DebugSize.x, DebugSize.y), entry.m_Value.ToString());
}
void DrawSlider(DebugEntry entry)
{
GUI.Label(new Rect(DebugPosition.x, DebugPosition.y + (DebugSize.y * index), DebugSize.x, DebugSize.y), entry.m_name.ToString());
index++;
GUI.HorizontalSlider(new Rect(DebugPosition.x, DebugPosition.y + (DebugSize.y * index), DebugSize.x, DebugSize.y),
(float) entry.m_Value, entry.m_min, entry.m_max);
}
#endregion -- End GUI Draw Functions -------------------------------------------------------------------------------
}