Normal C# Class as Decorator for GameObject/Monobehaviour

Hello!

For Example, I have class:

public class Bullet : MonoBehaviour
{
    private void Awake()
    {
        //1. Construct Object
    }

    private void OnCollisionEnter2D(Collision2D other)
    {
        //2. Process collision
    }

    public void Move()
    {
        // 3. Move Object
       // transform.Translate();
    }
   
    // 4. Another methods
}

I don’t like this design, because i dont want implement business logic in Monobehaviour. I want to write a game using only normal classes. The main motivation is that I want to test my game and not depend on objects that I do not control.

I am planning to implement such objects as follows:

public class BulletBehaviour : MonoBehaviour
{
    public event Action<GameObject> OnHit;
    private void OnCollisionEnter2D(Collision2D other)
    {
        OnHit?.Invoke(other.gameObject);
    }
}

And

public class Bullet
{
    private readonly GameObject gameObject;
   
    public Bullet(GameObject prefab)
    {
        gameObject = GameObject.Instantiate(prefab);
        gameObject.GetComponent<BulletBehaviour>().OnHit += OnHit;
        //1. Construct Object
    }

    private void OnHit(GameObject obj)
    {
        //2. Process collision
    }
   
    public void Move()
    {
        // 3. Move Object
        //gameObject.transform.Translate();
    }
   
    // 4. Another methods
}

I would like to ask experienced developers - how do you solve such problems? Is my decision correct? Maybe I don’t need to complicate this?

Then you should probably write your own engine, because if you don’t, you’ll always be depending on objects you do not control. Your concept here doesn’t remove dependence on objects you don’t control. You’re still relying on Unity’s event loop because your methods can’t be called without the MonoBehaviour kicking them off. Your “logic class” still will only compile in the context of Unity because you need your references to GameObject. You’re still exactly as dependent as you’d have been before, but now, you’ve doubled the number of classes and added a fair amount of work to achieve that exact same dependency.

It’s possible to achieve some degree of independence from Unity-specific classes, but it’s only useful to do this for some of the classes. I don’t have a solid “here’s when it’s worthwhile to do that” rule, it’s just sort of instinct developed across 14 years of using unity. Some potential indicators:

  • if you can implement a complete piece of logic without touching the UnityEngine namespace (except for primitive types like Vector3), it may be worth putting into a non-Unity class.
  • if it needs to be able to safely run on a thread, it may be worth putting into a non-Unity class
  • if it needs to be serialized, it almost certainly should go in a non-Unity class
  • If it touches rendering or the UI at all, it almost certainly should be based directly on Unity classes.
    None of these are 100% but they’re helpful starting points at least.

Regarding testing, Unity has a suite of testing tools specifically for this.

2 Likes

You’re attempting to start at too low of a level. Unity is already providing the component based architecture and many classes/functions to support your development. You simply need to start at a higher level (not that much higher lets be honest) and begin working.

MonoBehaviour is the base of every component.

If you want a raw class-only architecture then the best thing you’re going to find is ECS/DOTS or build a game with ScriptableObjects that handle all of your functions and data. SO’s are basically asset files and classes at the same time so theres a lot of flexibility in how you design with them.

1 Like

Thanks for the explanation!

My experience in Unity (and in game development in general) is one month, and I am trying to find rules for dividing my classes into categories: regular classes, monobenaviours, monobenaviours singletons, etc.

Waaaaaay to early to try that. Instead, do lots of small tutorials, try lots of things yourself, really soak in the breadth of the way things are done in Unity. Some people like to do everything in code. Some people put all that code in one giant class! Some people do almost everything in the editor with a minimum of code. Some people make everything a tiny little monobehavior. Some people hook together crazy amounts of non-monobehavior scripts with only a few monobehavior scripts.

Your challenge should be to get versant enough in Unity to pull up any example project from the net, examine it, run it, tweak and twiddle it, and see if you can make a meaningful change to the code: stuff like, change how the camera operates, change how the controls operate, put a new UI into the game, etc.

THAT is where you need to focus, otherwise you won’t be useful in any Unity context except your own way of doubling all the classes in pursuit of some unattainable non-Unity state of being within Unity.

2 Likes