Unhelpful error messages, when using RequireComponent with interfaces

You can use interfaces with the RequireComponent or RequiredInterface attribute. But when a GameObject has no Monobehaviour attached - which implements this interface - Unity error message only says: NullReferenceException: Object reference not set to an instance of an object.

Here’s an example:

EnemyBrain implementing IMoveInput interface:

using Character.Input;
using UnityEngine;

namespace Character.Enemy
{
    public class EnemyBrain : MonoBehaviour, IMoveInput
    {
        [SerializeField] private Transform enemyTarget;
      
        public Vector2 MoveVector { get; private set; }

        private void Update()
        {
            ReadMoveVectorToTarget();
        }

        private void ReadMoveVectorToTarget()
        {
            var dir = enemyTarget.transform.position - transform.position;
            MoveVector = dir.normalized;
        }
    }
}

ChaserEnemy which require an IMoveInput on the Gameobject:

using Character.Input;
using Character.Movement;
using UnityEngine;

namespace Character.Enemy
{
    [RequireComponent(typeof(Rigidbody2DController))]
    [RequireComponent(typeof(IMoveInput))]
    public class ChaserEnemy : EnemyBase
    {
        [SerializeField] private float speed;

        private Rigidbody2DController _rigidbodyController;
        private IMoveInput _moveInput;

        private void Awake()
        {
            _rigidbodyController = GetComponent<Rigidbody2DController>();
            _moveInput = GetComponent<IMoveInput>();
        }

        private void FixedUpdate()
        {
            ChaseTarget();
        }

        private void ChaseTarget()
        {
            _rigidbodyController.Move(_moveInput.MoveVector * (speed * Time.fixedDeltaTime));
        }
    }
}

Full error message:

NullReferenceException: Object reference not set to an instance of an object
Character.Enemy.ChaserEnemy.ChaseTarget () (at Assets/Scripts/Character/Enemy/ChaserEnemy.cs:29)
Character.Enemy.ChaserEnemy.FixedUpdate () (at Assets/Scripts/Character/Enemy/ChaserEnemy.cs:24)

I mean the error tells you exactly where and what the problem is. You’re trying to access something that’s not actually there.

What do you expect? If it’s not there and you have nothing to guard access to this member that is null, you’ll get this error.

Yes, it says the line, but I have multiple objects there, which can be also null.

It wouldn’t be a problem, if the editor - when you attach a Monobehaviour, which requires a component that implements the interface - would allow to choose between components, which are all implementing the said interface, and attach it to the Gameobject.

Also, the error message doesn’t say which reference is null. If I didn’t just modify this file and run the game, and know what changes I exactly made, I wouldn’t know what to look for.

From Unity - Scripting API: RequireComponent
The RequireComponent attribute automatically adds required components as dependencies.

Which isn’t exactly true, if you use it with interfaces.

Well that do you expect? RequireComponent adds and enforces the supplied component type when the decorated component is added. But when you supply it an interface… how does it magically know which component that implements the interface to add? You could have any number of definitions that implement this interface.

Honestly it should throw an error when you add the component, as using an interface makes no sense.

You have all of two reference types that could be null in that line. It should take you less than 10 seconds to figure out which one isn’t present.

So moral of story, RequireComponent doesn’t do anything with interfaces. Nice as it would be, it’s not a supported feature. If one used their eyes when adding the decorated component, they might notice one of two required components weren’t added.

So is this thread just a complaint, an actual request for help, or a feature request?

Feature request is more likely :slight_smile: