- Home /
Is there a Wild Card Variable in Unity c#?
I would like to create a blackboard like Unreal Engine. Blackboard is used to access variables inside the state machine for behavioural scripts. User can add variables of any data type they want. So inherited AI controllers can have different values depending on the need of the bahaviour scripts.
I was wondering if there are WildCard Properties/Variables here on Unity. So I can create a custom editor where the users can just add the data types they want such as int,string,Gameobject, Vector3, etc.
One of my ideas in approching this without wild card property is creating a class "BlackboardKey" and can be inherited to put variable depending on the data type. for example "BlackboardKeyVector". Blackboard key will have a function that returns a generic type of the value it contains.
Any thoughts on this?
.][1]
Answer by RowelCaps · Feb 25, 2021 at 06:49 AM
First of all, I wanna thank everyone who posted their answers, It did help me a lot coming up with a approach for this problem. So here is the answer that I come up with, I hope it helps other people in the future. I'm not sure if this is the best approach, so just tell me if there are better ways in handling this.
So first things first there are a few obstacles that we need to face in serializing generic types:
the variable "object" is the generic variable of c# and cannot be serialized in the unity editor
Declaring Data types one by one will quickly over populate your class for the blackboard keys.
We can't easily store generic classes under the same list
I used SimpleJSON for my saving system so I figured out that I may as well use this in serializing generic types. (SImpleJSON is a free plugin you can download from the net)
Here is my BlackboardKey class:
//===================
// I posted only the important parts since my code is quite lenghty
public class Blackboard: MonoBehaviour
{
public List<BlackboardKey> KeyArray = new List<BlackboardKey>();
}
[System.Serializable]
public class BlackboardKey
{
//===============================================================
//Identification for Blackboard Components
public string Name;
public EBlackboardKeyQuantity KeyQuantity;
public EBlackBoardKeyType BlackboardKeyType;
//===============================================================
//Used for serializing Values to the generic value type
public string SerializedValue;
public BlackboardObjectSerializer ObjectSerializer;
//==============================================================
//Value of this blackboard key
private object Value;
}
The EBlackboardKeyQuantity is an Identification if the Blackboard key is a type of Array or a Single Variable.
The EBlackboardKeyType helps to identify if the DataType is a Type of (int, string, float, Vector, gameobject, etc).
The SerializedValue is the most important part, This is where we will put are JSON value so we can serialize our "object value;" later on (During awake or something)
The ObjectSerializer has a values of "Object" this is the base class for all Objects inside unity. Used to serialize GameObject, Monobehaviour, and other things.
Now I have a class for my CustomEditor which is responsible for setting the SerializedValue. So here is how I serialize values in the editor
//This is quite lenghty too but I will post the Important part
public class BlackboardEditor : Editor
{
public void SerializeSingleKey(Rect fieldRect,int Index, SerializedProperty Type, string SerializedValue)
{
EBlackBoardKeyType type = (EBlackBoardKeyType)Type.intValue;
JSONObject objSaved = string.IsNullOrEmpty(SerializedValue) ? new JSONObject() : (JSONObject)JSON.Parse(SerializedValue);
JSONObject obj = new JSONObject();
switch (type)
{
case EBlackBoardKeyType.Int:
int intValue = string.IsNullOrEmpty(SerializedValue) ? 0 : objSaved["Value"].AsInt;
int Result = EditorGUI.IntField(fieldRect, intValue);
obj.Add("Value", Result);
Board.KeyArray[Index].SerializedValue = obj.ToString();
break;
// Put other variable types here
}
}
for the custom editor I used a Reorderable list you can check this blog out.
So here is the final result:
I had fun making this since it is the first time I created a custom editor for anything lol. Spent couple of hours trying to study and making it. the UX for my blackboard is still kinda rough but it works and I'm happy with it. :D
Answer by VOTRUBEC · Feb 24, 2021 at 09:23 AM
Unity makes extensive use of SerilizedObjects and SerializedProperties. If you take a look at their implementation of a SerializedProperty, you can see that it holds variable data for each type of data that the property can serialise. There's also a 'propertyType' field which returns an enum which is defined as (cut and past from ILSpy) :
public enum SerializedPropertyType
{
Generic = -1,
/// <summary>
/// <para>Integer property.</para>
/// </summary>
Integer,
/// <summary>
/// <para>Boolean property.</para>
/// </summary>
Boolean,
/// <summary>
/// <para>Float property.</para>
/// </summary>
Float,
/// <summary>
/// <para>String property.</para>
/// </summary>
String,
/// <summary>
/// <para>Color property.</para>
/// </summary>
Color,
/// <summary>
/// <para>Reference to another object.</para>
/// </summary>
ObjectReference,
/// <summary>
/// <para>LayerMask property.</para>
/// </summary>
LayerMask,
/// <summary>
/// <para>Enumeration property.</para>
/// </summary>
Enum,
/// <summary>
/// <para>2D vector property.</para>
/// </summary>
Vector2,
/// <summary>
/// <para>3D vector property.</para>
/// </summary>
Vector3,
/// <summary>
/// <para>4D vector property.</para>
/// </summary>
Vector4,
/// <summary>
/// <para>Rectangle property.</para>
/// </summary>
Rect,
/// <summary>
/// <para>Array size property.</para>
/// </summary>
ArraySize,
/// <summary>
/// <para>Character property.</para>
/// </summary>
Character,
/// <summary>
/// <para>AnimationCurve property.</para>
/// </summary>
AnimationCurve,
/// <summary>
/// <para>Bounds property.</para>
/// </summary>
Bounds,
/// <summary>
/// <para>Gradient property.</para>
/// </summary>
Gradient,
/// <summary>
/// <para>Quaternion property.</para>
/// </summary>
Quaternion,
/// <summary>
/// <para>A reference to another Object in the Scene. This is done via an ExposedReference type and resolves to a reference to an Object that exists in the context of the SerializedObject containing the SerializedProperty.</para>
/// </summary>
ExposedReference,
/// <summary>
/// <para>Fixed buffer size property.</para>
/// </summary>
FixedBufferSize,
/// <summary>
/// <para>2D integer vector property.</para>
/// </summary>
Vector2Int,
/// <summary>
/// <para>3D integer vector property.</para>
/// </summary>
Vector3Int,
/// <summary>
/// <para>Rectangle with Integer values property.</para>
/// </summary>
RectInt,
/// <summary>
/// <para>Bounds with Integer values property.</para>
/// </summary>
BoundsInt,
/// <summary>
/// <para>Managed reference property.</para>
/// </summary>
ManagedReference
}
So each serialisable data value is stored in a separate field, of that type. There's no generics in use. I would suggest using a SerializedProperty, but unfortunately some of the fields are marked as internal, and it's pretty specific to the SerializedObject.
But once you redo your own, then you can create a new PropertyDrawer that will allow you to look at the stored data type and then display the appropriate field type (e.g. IntegerField, ObjectField etc.)
So, a simple, cut down version might look like:
public MyProperty : ScriptableObject
{
public SerializedPropertyType propertyType;
public int intValue;
public float floatValue;
public string stringValue;
public Vector2 vector2Value;
public Vector3 vector3Value;
// etc., etc.
}
Obviously, you only need to put in as many types as you will actually want.
As for the PropwertyDrawer, that'll depend of whether or not you want to use IMGUI or UIToolkit. UIToolkit is easier to implement, but doesn't fully implement the full IMGUI Editor properties yet. It's close, but things like array lists are still of the old style.
Answer by xxmariofer · Feb 23, 2021 at 03:04 PM
Hello, Not in Unity itself but pure c# coding you can achieve something similar, they are called Generic classes here is a link to a tutotirla https://www.tutorialsteacher.com/csharp/csharp-generics
The use would be something like this
first create the generic class
class DataStore<T>
{
private T[] _data = new T[10];
public void AddOrUpdate(int index, T item)
{
if(index >= 0 && index < 10)
_data[index] = item;
}
public T GetData(int index)
{
if(index >= 0 && index < 10)
return _data[index];
else
return default(T);
}
}
now you can use different vairables type like
DataStore<string> cities = new DataStore<string>();
cities.AddOrUpdate(0, "Mumbai");
cities.AddOrUpdate(1, "Chicago");
cities.AddOrUpdate(2, "London");
DataStore<int> empIds = new DataStore<int>();
empIds.AddOrUpdate(0, 50);
empIds.AddOrUpdate(1, 65);
empIds.AddOrUpdate(2, 89);
His question comes down to serialization if you know this subject matter at all. Generics don't only won't help with serialization but bring whole another world of pain to the issue.
First of all, you are SO rude, "assu$$anonymous$$g you know this subject matter at all"? to someone who is investing his time to help others????
Second, before judging someones "program$$anonymous$$g skills" would you $$anonymous$$d taking a soft look into the documentation? it probably takes less time than writing your comment. LINK generic classes work with serialization perfectly and here is a follow up of the previous code
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(DataStore<>))]
public class Test : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, position.height), property.FindPropertyRelative("_data"), new GUIContent(fieldInfo.FieldType.GetGenericArguments()[0].FullName));
}
}
It works perfectly, I have used it myself, but obviosly i dont know it "all" about Unity, so if you politely explain why would be a "whole another world of pain" Im here to learn
@xxmariofer please accept my apologies, I didn't meant to be mean here. I'm sorry I offended you.
(question is tagged #unity5)
Answer by pauldarius98 · Feb 24, 2021 at 06:48 PM
Unfortunately there is no Wildcard in C# but the solution that you presented is the way to go (I would say). BehaviourTree asset is a node-base AI tool that is very similar to the Blackboard from unreal and you should really check out their approach https://opsive.com/support/documentation/behavior-designer/variables/creating-shared-variables/. I hope this will help you
Answer by FallingRocketGames · Feb 24, 2021 at 01:17 AM
Are you looking for this?
https://assetstore.unity.com/packages/tools/integration/roslyn-c-runtime-compiler-142753?fbclid=IwAR3d2UG5ppCdGSee_yH-hn5uQoesARZ0tukyaT8hlnrWG4MlC1r56FvhJzU
Your answer
![](https://koobas.hobune.stream/wayback/20220613025601im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Is it possible to access OnValidate() when using a custom inspector? 1 Answer
WebGL Input - KeypadEnter registering as Return 0 Answers
Coroutine works in editor, but not in build Windows application 0 Answers
Unity 5 C#, having a script show up in a path in the Editor 1 Answer