[REQUEST] Object event, OOP in GDevelop

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.

Thanks.

2 Likes

I love these suggestions! I haven’t done much OOP, but I know enough to see the benefits this would have to game development in GDevelop. And if there are those who are opposed to OOP over procedural programming, at least it being optional should be a good compromise.

Great suggestion!

Object Groups can do some of these things. I haven’t really went through their limitations, but with some clever algorithms, they might even be able to do most of the stuff you want to do.

Object Groups are set in the Editor, and then Objects are added to the Object Group.
For example: Bullet-group includes Bullet, Laser, Missile

If any Bullet-group member is colliding with the wall: delete THIS Bullet-group member

How does it know which one is THIS? Conditions select which objects to affect. It only knows “selected” or “not selected”, nothing else. I have only looked into the very basics of GDevelop, so I haven’t figured out how to store “selected object” into a variable. It might not be possible to do it directly, but I should be able to store something like its position or its ID number, and choose that to re-select it.

Once I figure that out, it’d let me do “custom selections”.

That would be able to solve your problem of:

If the X position of OBJECT is < OBJECT.X(): delete OBJECT

Basically, it would become

For each OBJECT(1) do:
        Select OBJECT (1)
        For each OBJECT(2) do:
             Check that OBJECT(1) is not OBJECT(2)
             Check if OBJECT(1).X() < OBJECT(2).X()  :  delete OBJECT(1)

Note that this pseudocode DOESN’T work, yet. I haven’t looked in-depth into how GDevelop programming and loops work. I’m not sure if nested for each loops work, I don’t know if objects can be destroyed inside the loop without breaking it, etc.

It might also be possible to just do a comparison using two groups, where each groups has just those objects.

If Group-1-object.X() < Group-2-object.X() : delete Group-1-object.X()

GDevelop might not be able to do everything the same way you would do them in traditional programming, but I think that’s perfectly fine. It is a bit more complex than it seems at first.


That said, I agree with you on the main premise - I think GDevelop would be greatly improved if object oriented approach was easier to do. In my case, the problem is with separates player-controls and player-characters.

How do I make a Player 1 “class / object” a specific player-character, such as “Ship-1” or “Ship-2”? How do I check the variables of that ship, like its speed and rotation and weapon cooldowns? I think it might be possible, but I’m not sure how to do it.

Yes, groups can do some of the tricks as long you want the very same events to apply on multiple objects but very messy.

Imagine that you have many different type of bullets, lasers and missiles. In general you want only the bullets to delete, the lasers to fade out and missiles to explode. Now you can create 3 groups called “Bullets” “Lasers” “Missiles” it means you need to have 3 events to check collision.

Is Bullets colliding with wall delete
Is Lasers colliding with wall fade out
Is Missiles colliding with wall play explode animation

Now imagine that though, you have a special laser, bullet that supposed to last a little longer.

You can create a 4th group called “SpecialProjectile” and say

Is SpecialProjectile is colliding with the wall then wait X second and then… You want to delete the bullet and fade out the laser, so you might want to create 2 events for each bullet instead. But what if you have multiple of those special projectiles, it means you need 2 more groups. “DelayedBullet” “DelayedLaser” which means you end up having 5 events to check collision with the wall.

And then you also want to cause damage to the wall but different projectiles cause different level of damage and also need to take in to account the type of wall which also means additional groups and events only to handle collision and damage between projectiles and walls.

Can be done of course, but it is a mess in my opinion and after a while in a huge game also hard to follow and manage.

OOP and Inheritance would make it more organized more simple to manage because it helps to focus only on what do you want THIS object to do and what do you want to happen to THIS object and when and as I mentioned Inheritance helps with borrowing properties and events from the parent and be able to expand on top of it and change it for them self to fit.

It is my opinion. I understand not everyone agree and even less people care and I never going to see this feature in GD but never mind, I figured I have nothing to lose by making this request.

GDevelop can be improved so that it can do the things you want, but those can be done without making GDevelop object-oriented the same way many programming languages are.

For example, at the moment, there don’t seem to be automatic “sore ID of this object / check ID of this object” conditions or actions. They can be done by adding a new object variable where you save a string.
Similarly, I couldn’t find a way to automatically check the type of an object using conditions, even though object name is used in the action “Create an object from its name”. But if you add an object a new variable, and save its name as the variable’s value, you can use that to check for individual object types.

If Bullet-group collides with a wall
      if Bullet-group's variable object-name is "Bullet": destroy Bullet-group
      if Bullet-group's variable object name is "Laser": set variable fade out of Bullet-group to true
      if Bullet-group's variable object name is "Missile": set Bullet-group to use animation "Explode" and move things aorund

Adding one or two new conditions is relatively easy. Adding a whole new object-oriented programming approach is relatively difficult. I’d love for GDevelop to be able to do these things. I only have doubts on whether your approach is the best one, and whether your approach is likely to get actually implemented.

Yeah there is many other ways to go about this obviously but I find none of them as elegant as OOP can be if it done right. But I realize it is subjective.