- Home /
Exposing interface implementation
So i have many objects of different types implementing the interface IMatrixNode. I now have a object Matrix. I tried declaring a variable like so:
Public IMatrixNode[] column;
It is my understanding now that you can't expose interfaces in such a way. If i declare it as a GameObject array however it will also be able to recieve objects that do not implement the interface. Is there a way to limit a variable so it will only be able to recieve GameObjects that implement IMatrixNode in the editor?
Answer by Jamora · Feb 07, 2014 at 03:05 PM
You have two options (that I know of) to have the Editor accept only your interface types in the general case:
1) Do as IUnified, and have a generic MonoBehaviour class for which you create a property drawer
2) Have a collection that is visible in the Editor (e.g. Monobehaviour, GameObject...). Then provide an implementation for the OnValidate method for the class that has your interface-collection. An example implementation could be one where you check that each element in the collection implements your interface. If one doesn't, it is removed.
If it's just for that one class, then a possibilty is to create a custom editor.
Thnk you OnValidate worked great. Here is an example of what i did if anyone else is interested: void OnValidate() { if (light_node != null) { I$$anonymous$$atrixNode test = (I$$anonymous$$atrixNode)light_node.GetComponent (typeof(I$$anonymous$$atrixNode)); if (test == null) { light_node = null; } } }
Answer by nesis · Feb 07, 2014 at 02:03 PM
I'm thinking I did what you're attempting with this (Unity 4.3):
MyInterface.cs:
using UnityEngine;
using System.Collections;
public interface MyInterface {
string GetSomeClassId();
void DoSomeMaths(float a, float b);
bool IsSomething();
}
bar.cs:
using UnityEngine;
using System.Collections;
public class bar : MyInterface {
public string GetSomeClassId() {
return "bar is cool";
}
public void DoSomeMaths(float a, float b) {
Debug.Log (a+" * "+b+" = "+(a*b));
}
public bool IsSomething() {
return true;
}
}
foo.cs:
using UnityEngine;
using System.Collections;
public class foo : MyInterface {
public string GetSomeClassId() {
return "foo is cooler";
}
public void DoSomeMaths(float a, float b) {
Debug.Log (a+" + "+b+" = "+(a+b));
}
public bool IsSomething() {
return false;
}
}
TestOutput.cs:
using UnityEngine;
using System.Collections;
public class TestOutput : MonoBehaviour {
public MyInterface[] tests = {new bar(), new foo(), new bar()};
public void Start () {
foreach (MyInterface t in tests) {
t.DoSomeMaths(2,8);
Debug.Log("GetSomeClassId(): "+t.GetSomeClassId());
Debug.Log("IsSomething(): "+t.IsSomething());
Debug.Log("===");
}
}
}
Thanks for the reply but this is not what I meant. In your example I need to hard code every object that is implementing the interface. I want to be able to add an object from the editor like any other public array however I want to limit that array so it will only be able to recieve objects that implemented the interface as input.
If exposing an interface to the Inspector is what you're wanting, you'll have to do a bit of work, as suggested in this similar question. Essentially, you'll need to make a custom editor script for it, or use an existing workaround others have made (one of which is posted in that link).
Answer by vexe · Jan 04, 2015 at 12:19 AM
A 3rd solution to add to @Jamora's list, is to implement a custom serialization system that properly handles edge cases that Unity doesn't do a good job at.
I did just that in VFW, a custom serialization and drawing system that provides polymorphic serialization and proper exposure to interfaces/abstract types. An added benefit to having a better serialization system is that you could handle pretty much everything else that Unity can't (properties, dictionaries, delegates etc)