- Home /
Is the inclusion of abstract classes and interfaces really needed in Unity Game development?
Well I'm doing this game for an assignment we've been given. I haven't faced many coding issues other than the occasional "bullet not firing" kind of problem.
While everything's going ok, it feels strange because from the way I've been using this game engine I really haven't found the need to structure the code in such a way which includes abstract classes or interfaces for example. I could if I wanted to, but to be honest it seems like I don't really need to because of the way the Unity's scripting mechanism works.
My question is; am I the only one with this school of thought? Would it be better in terms of game development practice if I implement this structure into my code? Does the engine like working with abstract classes more than regular "attach and go" code?
Answer by Statement · Dec 22, 2013 at 04:54 PM
It's possible to use abstract classes and interfaces in Unity, yes.
Should you use them? I don't know. Do you need to use them?
Some useful tips:
Public interface type fields can't be set via the inspector.
Public abstract class type fields can be set via the inspector.
You can't use polymorphism on System.Serializable tagged classes or you will experience type slicing.
You can get components implementing an interface via GetComponent(typeof(MyInterface)) but you can't use the generic version.
As a rough guide:
Normal classes extending from MonoBehaviour are easy and works for most problems you need to solve
Normal sub-classes works as you'd expect. If your goal is code reuse favor composition over inheritance.
Abstract classes are not much harder to use (remember you need a concrete implementation)
Interfaces are working against you if exposed in public fields, shown in the inspector
From my experience, abstract classes can better be used as interfaces (just leave all methods abstract). I say better, because at least you can serialize the references properly. However you can only inherit from a single abstract class (or chain them). Interfaces have the benefit that you can implement multiple interfaces. You can't do the same for abstract classes.
You will also carry the baggage of MonoBehaviour. This can be both a relief and an annoyance.
public abstract class Explosive : MonoBehaviour
{
public abstract void Explode();
}
I really haven't found the need to structure the code in such a way which includes abstract classes or interfaces for example.
This is a good thing, generally. You should favor composition over inheritance. Unity makes it very easy to do this and you should favor composition when you have no need for inheritence. However it gets awkward when you want to decouple from Unity, like if you want to run Unit Tests separately.
If you feel lost on the topic of composition over inheritence, I suggest you pick up a book on design patterns as they will discuss it until your ears bleed. One that I found good was Head First: Design Patterns but there are more canonical books on the subject like Design Patterns: Elements of Reusable Object-Oriented Software by the gang of four. I found Head Firsts book to be very easy to follow and I've had a lot of use of the skills it taught me.
If you don't know what Unit Testing is, I can recommend a book called The Art of Unit Testing which I found good.
I agree. If using an abstract class or an interface solves more problems than it introduces in the project, then they should be used. The goal should be to have the simplest working code possible.
I tend to only use abstract classes when I need to uniformly work with a family of classes. I would much more prefer to use an interface, but Unity is limiting me and I resort to an abstract class. A concrete example of where I'd use it is Triggers (making a custom general trigger system - not to be confused with Physics Triggers). I have a uniform API to raise a trigger based on an event, and I want to polymorphically chain triggers together. In this case it makes sense to use a base class so I can substitute the implementation easily. If I were making something else which I don't require a uniform API for, I just make it a normal class that extends from $$anonymous$$onoBehaviour.
I'd really want to work with Interfaces but Unity makes it hard and I prefer to stay productive and not fight against the system.
Wow, thank you for this answer. I know how interfaces and abstract classes work and have an idea of how unit testing is implemented, but I really do need a brush-up on design patterns and I will definitely give a good look at the suggestions you've given me.
The way the game is being designed, it doesn't require me to use inheritance in the code really, so I'll just stick to this structure since I'm finding it relatively easy and simple to work with.
Thank you!
@jamesb1, I don't know what your level of experience with program$$anonymous$$g and patterns are, but if you haven't read a book on design patterns yet I think you'll get a feeling like it's Christmas on top of Christmas. It will open your eyes open to so many possibilities and I can't recommend the act of getting and reading a design patterns book cover to cover enough. When I first read a book on design patterns my head just exploded with so many solutions to problems I thought was hard to solve.
Prerequisites should just be things you already know, such as interfaces, abstract classes, polymorphism and such.
Straight after (and during) reading the book, you may go into a phase where you try to approach every problem with a pattern and over engineer things a bit. People generally frown on this kind of behaviour (at least in production code) but I had a blast trying out different kinds of approaches to a single problem and learned a lot from it. Just keep in the back of your $$anonymous$$d that you don't need to use these patterns everywhere. The single most important piece to take home from the book I recommended was to favor composition over inheritence and that alone will help you solve a lot of problems in ways you may not intuitively have thought of yourself prior to that. You will naturally see that you don't need to build long and intricate inheritance trees and you'll see when it's harmful to do so (not for performance, but for the code design - to avoid getting into awkward positions where you need to rewrite parts or whole of a system).
To put it bluntly. First you must unlearn the wish to create deep inheritance trees. Then you learn the patterns. Then you'll need to unlearn to use patterns everywhere. The last step was actually the hardest for me to let go of, since it is so tempting to use any of the patterns you've learned. So if you are anything like me, also be prepared to figure out a way to:
Avoid forcing design patterns on everyone (see, I have a hard time even now!) and for every single problem.
Try actively to restrain yourself from overusing patterns to avoid over engineering.
Over engineering is bad because you'll end up spending more time writing code to facilitate the patterns without bringing any real value to the solution. It might also make your code overly complex (especially for novices) to understand.
I'd wait with the Unit Testing book, unless you want to learn Unit Testing. You'll at least benefit a lot by learning code design before introducing Unit Testing. Also, you may find yourself a bit short of content after finishing the Unit Testing book, since things are a bit different in Unity and you probably want to include other kinds of tests, like end-to-end tests, acceptance tests, a "walking skeleton", and so on. It is a great starting point but I think you'll start to appreciate testing better once you've read a couple of books about it. At least, that's me and my advice.
Answer by mahdiii · Jul 27, 2016 at 01:05 PM
I say, as far as possible,split your codes to bunch of components. For example suppose you need the reload function. You know that all of weapons need to reload so you write an abstract class "weaponsystem" and an abstract method reload,then you write several classes(SMG,AK47,M16,G3) that implement the reload function.it is cool but suppose that G3 and AK47 have the same reload function but M16 and SMG have the same one. what to do. You need to copy and paste reload codes for G3 and AK47 (and M16 and SMG). It is not bad? surely it is bad and causes problems. now suppose you write an interface IReloadable and implement it in Reload1 and Reload2 class. So you can use Reload1 for SMG and M16 class and Reload2 for AK47 and G3 easily. Component based procedures give you a power you can easily extend your codes and programs. Use abstract class or common class for inheritence only when you are sure you need them.