Search Unity

OOP with Unity Design Problems

Discussion in 'Scripting' started by Anthony-Blanchette-Potvin, Jul 10, 2019.

  1. Anthony-Blanchette-Potvin

    Anthony-Blanchette-Potvin

    Joined:
    Mar 1, 2016
    Posts:
    5
    Hello everyone,

    I'm trying out something new tonight : Object Oriented Programming in Unity ! I'm an OOP adept and I'm glad that it is possible in Unity.

    I'm using the MVC (Model - View - Controller) architectural pattern. Basically, I have a superclass called Character which contains various fields and methods like Walk(), Run() and Attack() and another class called CharacterController that controls data in the Character class based on player inputs. These classes do not inherits from MonoBehavior since it would be against my purpose of using OOP.

    My main question is concerning the movement (run, walk, etc.) of the character. Right now, I'm doing all the movement logic in the CharacterController class. But, I think I would prefer to handle it in the Character superclass so that I can override the Walk method in any other class that inherits from Character. The thing is that I'm so used to various methods provided by Unity like Time.deltaTime or Update to create a smooth, real-time, frame independant movement.

    So, how would you handle any movement logic within the Character superclass (does not inherits from MonoBehaviour) ?

    If you guys need any code or images, I will provide it on demand !
     
  2. I wouldn't. It is L'art pour l'art to fight against the framework Unity provides. It does not deliver any advantages other than the orgasm when you have a perfect MVC architecture.
    Substantial elements like object moving, character animation, etc, it is imperative to use the stuff Unity provides for the sake of any performance (OOP is bad enough on its own). But this is just my opinion.
     
    bart_the_13th likes this.
  3. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    [GeneralWarning]
    Unity is a game engine, a development platform, not a framework you can simply choose to use or not to use. Similar to writing extensions for Adobe products or any other existing software, you're limited in your access and methodology to those supported by the software. Trying to go for a pure OOP approach will only hurt you- not just because OOP is deeply flawed itself (so swapping one implementation for another is just extra work with little payoff), but because swimming against a current is hard, if not impossible.

    Unity has no Main() entry point, nor is there some core services lookup where you can just swap out their systems with your own. What you're trying to do probably isn't possible even in theory, but even if it were, in trying to rid yourself of what you see as the mistakes in fundamental methodology, you also rid yourself of every benefit of actually using Unity to begin with. If that's what you want, you should go check out Godot instead, as that's so raw as to not even really possess a "methodology" you can go against.

    I won't really argue with you on this (I've had enough of that lately), just consider it a warning you can heed or choose to ignore. *shrugs*
    [/GeneralWarning]

    Getting to the specific issues though, operations having to do with in-scene interactions are not really negotiable. If you go check out the Unity source code, you'll only see about half of it (the half that's in C#). The source for the unmanaged side isn't available, and that side is where the physics interactions lie, among other things. Colliders, Triggers, gravity, and many other elements simply aren't able to be directly manipulated in a way that would support moving outside of the MonoBehaviour paradigm.

    So you should change your mindset IMO- if you want to remove yourself as much as possible from the encouraged workflow of GameObjects and MonoBehaviours, use those only for things that have explicit in-scene interactions. Create your own external services or MVC pattern or whatever you like, but when you need something to be done in the scene, use proxy objects to manage it. In other words, generate the scene object either manually using "new GameObject" and "AddComponent" and the like, or instantiate from prefabs, then whenever the owner service needs scene information / interactions, it can run them through its proxy. This is entirely possible.

    One of the first things we did in our latest project is to create a service that handles update event calls- Update is called once per frame on GameObjects/Components in the scene and can't really be wired into externally. A service class that isn't a part of the scene has no way to receive these update calls, so we create a proxy object in the scene, set it to DontDestroyOnLoad, then add a MonoBehaviour that we've made to invoke delegates every time Update, LateUpdate, and FixedUpdate are called on it. The service sets these delegates, and receives the invokes, then fires events that all other services can subscribe to.

    At the cost of a single in-scene GameObject and MonoBehaviour, all services (managed through a service locator) can now be notified whenever one of the various Update calls are made. We have similar services/proxies that serve as in-game Object pools, UI management roots, etc... There are a lot of things that simply must exist in some form in the scene, but the proxy approach helps abstract that out so that knowledge of the scene and its interactions isn't necessary by consumers of various services.

    That's just one example, but it should give a good idea of how you can possible manage some of what you want.
     
    Last edited: Jul 10, 2019
    silvematt, ashapcott, Boz0r and 2 others like this.
  4. Anthony-Blanchette-Potvin

    Anthony-Blanchette-Potvin

    Joined:
    Mar 1, 2016
    Posts:
    5
    Hello Lysander,

    I didn't read myself before posting my thread. That's is pretty much what I'm doing / want to achieve.

    I said that even my CharacterController didn't inherit from MonoBehavior, but that's not true. Only the Data Models (Character, Item, Quest, etc.) don't inherits from MonoBehavior. The Controllers are scripts that inherit from MonoBehavior and the views are GameObjects instantiated and controlled by the Controllers.

    I just want the Model part of the architecture to be usable in other C# project other than Unity, like Godot.

    And, I would like to know in what sense OOP is that flawed ? I don't want to argue, I just wanna know :)

    Thank you !
     
  5. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    You doing OOP in Unity wrong way. Imagine a javascript-like language with prototypes instead of classes. Learn how inheritance and other OOP concepts implemented in this kind of languages. Now pretend your prefabs being prototypes (i.e. classes) and game objects are their instances. Now you can use OOP patterns in terms of Unity to model your game in correct way, not fighting unity component approach.
    P.S. After you got this, learn about scriptable objects and ECS.
     
  6. Anthony-Blanchette-Potvin

    Anthony-Blanchette-Potvin

    Joined:
    Mar 1, 2016
    Posts:
    5
    Wow, thank you ! Basically, do not try to make your own idea of how Unity should work. If it throws at you scripts and components, you probably should take advantage of the entity component system (ECS) instead of going in the obscure way which in that case is OOP in Unity.

    Had my lesson. Thank you guys !
     
  7. I like the ECS things and all and I think much better than the OOP counterpart but it is not about this.

    MonoBehaviour descendant classes can be attached to game objects in the editor. These are called components.
    And there is this notion in OOP and OOD: composition over inheritance, which basically means concentrate on small building blocks which can be put together like puzzle to achieve certain things. These are tightly coupled, components in this context means composition.
     
  8. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Weellll, most people will never need or use ECS. It's only hyped since it's the newest thing. But it's only purpose is to enable faster graphics-heavy action games. If you want to make a "slow" OOP framework, which OOP-loving people can easily use to make story-based games, or crafting games, or 95% of the games which don't need speed, ECS won't matter to you.

    One of the first things anyone with a coding background learns in Unity is that half the stuff is just to ease in game designers from other engines. They don't necessarily want you to do things the way their demos show. For example, many of my scenes have 1 main entry point, with non-monobehaviour classes doing most of the work. They mostly look like normal computer programs.
     
    DonLoquacious likes this.
  9. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Why do you contrapose those two concepts? ECS is just another OOP pattern.
     
  10. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Because its actually DOD?
     
  11. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    No, conceptually. ECS is just another OOP pattern just like MVC and many others.
     
  12. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I guess you're right. It depends on the implementation.
     
  13. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    I think the confusion is coming from that ECS is OOP, but with DOD considerations brought in. DOD and OOP aren't necessarily exclusive from one another. Though you could lean one way or another, you can also take from both at the same time.
     
    xVergilx and palex-nx like this.
  14. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    There are specific OOP design patterns, involving tricks with virtual functions and subclasses. The only way you can say ECS "is" a Design Pattern is by saying which one it is, or by admitting you have your own personal definition.

    The only concrete thing I got from the plans for how ECS would eventually work is that you'd be able to decide on the memory layout of components. You could have the Rigidbodies and colliders for all gameObjects grouped together. Less jumping around in memory, for faster memory access seems to be the entire point. Seems about as far from OOP as you can get.
     
    xVergilx likes this.
  15. I guess I'm more used to the functional-like DOD systems. So it came automatically :D Well, technically, we have classes here in Unity ECS, so whatever.
     
  16. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Well no one has necessarily called it a 'design pattern'.

    Though if it were... saying which on it is is well calling it one. "The only way you can say Factory 'is' a design pattern is by saying which one it is..." It's a circular argument.

    Anyways, ECS is an architectural pattern. As opposed to a specific pattern, it is instead a school of thought used when deciding patterns to use. ECS favors a composition over inheritance via a component based design (which is already familiar in game design), but with memory layout taking a larger role in the decision process.

    Not sure how it's the farthest thing from OOP. I mean yes, memory concerns aren't usually a big concern in OOP... but that doesn't make it the farthest thing from OOP. It just means we're layering on that concept to existing design choices (specifically composition pattern via components).
     
    Suddoha likes this.
  17. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Thats just an illusion. Unity implemented ECS in this manner and memory layout is not a goal of ECS pattern at all. You can implement MVP, for instance, in this manner too.There's a lot of ECS implementations around build without this optimization in mind, check them out if interested. ECS is one of standard solutions for modelling complex dynamic systems, like MVP is for document-oriented systems.
     
    Suddoha likes this.
  18. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Ah, I see the confusion. ECS has 2 different meanings here. "Entity Component System" is an old generic term, roughly describing the way Unity makes a Light or Rigidbody by adding a Component to a GameObject. You don't hear it much to describe Unity, the same way you don't hear "OK, so you know how calculus works? Well Animation curves are just... ".

    But "Unity ECS" is a very specific system, currently in development. I've been seeing "ECS" here on Forums only to talk about this new thing.

    The first mention of ECS was Palex: "learn about scriptableObjects and ECS". That's gotta be about the new Unity ECS. But then it got switched back to the first definition later on. It seems unintentional -- ECS is not a descriptive name for the new system. If you haven't read it, it seems like it's converting Unity into ECS, when it's not, since Unity is already that way.
     
  19. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    I'm talking about ECS as ECS and not just specifically Unity ECS.

    The use of components is not the only part of ECS. It's the separation of entity, the component (as a data container), and the system (the logic that acts on that data).

    The system acts on the component, rather than component acting on itself.

    In the case of Rigidbody/Collider, yeah, that's technically the structure there since the physics system is what acts on the components for Rigidbody/Collider/etc. But that's mostly incidental.

    ECS as an architecture is more in line with what Unity's ECS is working out to be. Where you have code/systems separate from the entities/components, and it iterates over them acting on each one individually. And usually with their data organized linearly to allow for efficient piping of that data to the cpu.
     
    Lurking-Ninja likes this.
  20. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    If I'm reading that right, then this is the original thing I disagreed with -- that we need to care about the new ECS system. The Unity ECS blog(?) post tells us that Unity won't look any different after the Unity-ECS project is done. Behind the scenes, data will be stored nicer. Forums threads keep getting hijacked by "everything will change when ECS gets here, you'd better learn it now", which are just wrong. Nothing will change. But maybe these people are merely confused, since to play with the partly done ECS you need to do a bunch of extra stuff.

    For generic ECS, I guess my question would be: where would that be in a guide to using Unity? I'd say never. For example, people sometimes ask if a MonoBehaviour with no Update costs extra time. It doesn't since the system pre-makes a list of scripts with Update(). You could instead explain it by saying Unity uses ECS, which according the the Wikipedia page iterates through a ... , but that seems less helpful.
     
  21. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Yeah, we don't need to care about the new ECS system if you don't like it.

    I personally haven't really used it all that much because I don't need it for what I do. My partner and I make small little adventure games, the new ECS stuff would be overkill for what we do.

    Agreed, I've seen this.

    I think it's a conflation of "things will change because new features will be added that I can take advantage of; which are awesome!!!" vs "things will change, and you'll be forced to use the new features being added!".

    Unity isn't forcing it... as far as I know. Someone may correct me if I'm wrong.

    And if they are... welp, that's what LTS is for!