Interfaces

Writing one piece of code that works with several kinds of thing, and picking the right tool for classes and for components.

Updated 2026-09-07

An interface is a promise about what something can do, without saying what it is. Write code against the promise and it works with anything that keeps it.

public interface IShape
{
    int Area();
}

public class Square : IShape
{
    public int side;

    public int Area()
    {
        return side * side;
    }
}

public class Rect : IShape
{
    public int width;
    public int height;

    public int Area()
    {
        return width * height;
    }
}

Anything holding an IShape can ask for its area without knowing which kind it has, and the answer comes from whichever class is actually there:

IShape shape = square ? (IShape)new Square() : new Rect();

int area = shape.Area();

That decision can be made while the world is running. This is the everyday use, and it is where interfaces earn their keep: one piece of code, many kinds of thing.

Where they pay off

Anywhere you would otherwise write a long if over a type field.

  • Inventory items that each do something different when used
  • Quest steps that each decide when they are complete
  • Effects applied to a player, each with its own rule
  • Weapons, where firing means something different per weapon

Written with an interface, adding a new kind of item means adding one class. Nothing that consumes IItem changes.

Components are different: use a base class

Interfaces describe classes you create in code. Components are different, because you drag them onto GameObjects and Unity has to save that reference — and Unity cannot serialize an interface field. Typed as an interface, the field will not appear in the inspector at all.

So when the thing you want to share is a behaviour, use an abstract base class:

public abstract class Door : UdoniteBehaviour
{
    public abstract void Open();
}

public class SlidingDoor : Door
{
    public override void Open() { /* ... */ }
}

public class SwingingDoor : Door
{
    public override void Open() { /* ... */ }
}

Now a switch holds one field and works with either kind:

public class Switch : UdoniteBehaviour
{
    public Door door;      // drag a SlidingDoor or a SwingingDoor onto this

    public override void Interact()
    {
        door.Open();
    }
}

The field shows up in the inspector, accepts either door, and door.Open() runs the right one. A base class can also carry shared state and shared code, which an interface cannot.

This is the same advice you would follow in ordinary Unity, for the same reason.

Choosing between them

You want Use
Several classes you create in code to share a contract an interface
Several behaviours on GameObjects to share a contract an abstract base class
Shared state or shared method bodies an abstract base class

A base class can implement an interface, so a behaviour can do both when it is genuinely useful.

Something went wrong Reload