The ability to be able to use an Object Oriented approach in GDevelop and able to add events directly to objects every now and then comes up on the forum. Up until recently, I didn’t give too much thought of this but in the past few months I’ve been studying Object Oriented Programming and been using engines that apply an Object Oriented approach and I am at the point when I would prefer to use OOP for organizing game logic.
What is the benefit?
It is something that not everyone agrees on, I’ve seen developers state OOP is a big pile of mess but I am not one of them.
In my opinion, OOP makes “code” and game logic more organized and more simple to maintain especially when our project grows huge. Currently, in GDevelop we need to consider the logic flow as a whole, every single line as being executed from top to bottom one after another. Begin something at the top and end it at the bottom is a natural way of thinking to most people and this is why it is so easy to get started with GDevelop. But when it comes to huge and complex projects I see people often mess things up by changing a value somewhere along the way and wondering why is this not working.
OOP has the benefit we don’t need to think about the project as a whole, we need to think only about what we want to do with “THIS” object and when.
So instead of saying
If OBJECT1 is colliding with the WALL: delete OBJECT1
if OBJECT2 is colliding with the WALL: delete OBJECT2
With OOP we can simplify it and say
If THIS object is colliding with the WALL: delete THIS object.
We could just add this event to objects and it would apply to all objects the event is attached to.
“THIS” should be a new expression that returns the instance of the object the event is attached to. In other engines, it is also often called “SELF” that we can use in events in place of the object name to reference the instance the event is attached to.
GDevelop could go even further and introduce “Inheritance”, the ability to create objects inherit from another object and borrow all the events and variables from the parent. Which means we need to attach the event only to 1 object and all child objects inherit from this 1 object, will apply the same event and have the same variables with the same values which also means, if we want to update the event or variables later, we need to update it only for 1 object instead of 20. Of course, we can do similar with functions and external events, but the point is, in case of “inheritance” we don’t even need to bother attaching events and calling functions and external events. All the events and variables would be borrowed automatically from the parent. Also if we decide though we want slightly different values for the child, we can add the same variable also to the child which is then going to override, replace the value from the parent and the same goes for the events. If we decide to add an event to a child it will override the event from the parent. Ideally, we should even be able to choose if we want to override or extend in which case the child would apply the event of the parent and also its own events too.
But not only that. Currently, if we want to check condition between instances of the same object in GDevelop for example.
If the X position of OBJECT is < OBJECT.X(): delete OBJECT
GDevelop got no idea which instance we are comparing to which and which instance we want to delete.
With object event, we could solve this easily like so:
If the X position of THIS object is < OBJECT.X(): delete THIS object
Since “THIS” return the instance the event is attached to, it would be more obvious to GDevelop which instance we are comparing to which instance (THIS to All other), and which one supposed to be deleted (THIS the one has the event).
Finally, object events would be triggered, checked and executed only if an instance of the object is present in the scene which means we don’t need to worry about that we are wasting resources on events that points to an object that doesn’t even exist in our scene. Of course we can simply check the number of objects in a scene before triggering any events, but it is just nice OOP take care of this by nature and we don’t need to worry about any of this stuff.
We could do a lot with Object events and Inheritance without the need to ever keep in mind the logic flow as a whole. With Object events, we would need to think about only what we want to happen to THIS object and when. Which makes it a lot more organized and more simple to maintain our game logic in my opinion.
How could it work in GDevelop?
First of all, worth mentioning that it would NOT change how games are made in GDevelop now, it would be only an option to those who come from an OOP environment and prefer to do it this way. It would be optional.
It could be implemented as a Behavior that we can add to objects and then in the behavior property we could open an event editor to add events to the object like normal, but in this case, the event would be exclusive to the object. It would be also important to introduce the expression “THIS” to be able to use it in places to enter an object name.
Inheritances could be a property in object properties that we can choose if an object inherits from object. If we don’t enable it, it is a normal object, if we enable it, the events and variables of the selected object would be copied and used at runtime. If we add the same variable to the inheritance as the parent, it value override the one coming from the parent. And if we choose to add event to the child, ideally we should be able to choose if we want to override or we want to extend the event coming from the parent.
So, in essence, we could use the current event sheet to implement GLOBAL logic that applies to the entire game and we could use “Object events” to add events to objects that apply only to the object itself, its instances, and its inheritances. It would not change anything from a user point of view, GD would continue to work as usual but the option to use an Object Oriented approach would be there to those who need it.