After analyzing various approaches, I concluded that by far the best way to write the logic for your player and enemies is via behaviors in a custom extension, rather than in the scene or external events. As such I ported the logic for my player from events to my own behavior, which of course inherits the Platformer Object as a required behavior and works on top of it. I got the basics working as intended but am running into a big limitation: How do I address other objects and groups from my behavior?
Say I want an enemy to look for the player and attack them: I don’t seem to have any way to address the player, only item I can reference is Object which refers to self. The player is of course a global object, but even global items are seemingly inaccessible to the extension system. It seems I could define a public action in the behavior which I’d then call from the scene events, parsing the object I want to check as a parameter… only problem is enemy thinking is meant to execute each frame locally (doStepPreEvents), I’d need the scene to set a variable or parameter in the behavior which stores the object / group which the think function then picks from: Is this or a better solution possible?
Here’s a view of the first practical issue I’m encountering: My custom enemy behavior currently contains walking from left to right and flipping when reaching an edge. Before I used a point intersection check to see when the monster is about to run into a wall and change direction, by having colliders in a collider global object group. Extensions can’t see that group any more so how do I detect collisions now?
Hello again, MirceaKitsune!
I don’t think I’ll be able to remove all your doubts, but I hope I can shed some light.
Using extensions you need create a new parameter to every object do you want (can be Sprite, Particles emitter, Text etc). I did an example creating an extension for enemy attack using the action fuction like you did. And like you said, the Custom Behavior already come with a parameter for the Object, so I don’t need to create another parameter to the Enemy because I’ll use this parameter Object for him, but I need a new parameter for the Players. I choose Sprite:
In the “Setence in Events Sheet” I add my two Parameters 0 and 2 inserted in a phrase. I also did my colision event:
In the events I can use a group instead an object sprite:
Here is the link for the Gdevelop Wiki about Custom behaviors with a more detailed explanation: Custom behaviors - create your own behaviors with events - GDevelop documentation
Thanks! So it’s a lot like what I suspected I’ll need. Only one thing I still don’t understand there:
So you create a new parameter of type Objects and can give it the type Sprite, the one named Players in this example. But then where do you connect this parameter to the Object Group of the players, so that it actually refers to the objects you want it to? I can’t quite tell where the last 3 screenshots are from, whether it’s the scene events or the extension / behavior events. On its own I presume that parameter either does nothing or will refer to every object of type Sprite.
Sorry. My last screenshots weren’t clear.
Because it is an action function I need to insert it in the events of my scene. It will not run by itself even if the object that have this behavior is in the scene, because it’s an action and needs to be in the events of the scene. It’s like the action of Platform Character Behavior to make the player jump.
In “Setence in Events Sheet” I added the parameters in the Custom Behavior and wrote like a phrase, right? It’s because it need to make sense. This Setence will appear when we use this action in the events of the scene.
I added the Behavior to my Enemy and now in the events of scene it shows the action for him. Again, like the action of Platform Character Behavior to jump:
Using this action I can choose who of my scene gonna be the paramaters of my Behavior. Look, it shows exactly like I did in my “Setence in Events Sheet” of my Custom Behavior with my phrase (to make sense when i use it):
So, I choose the Enemy to the first paramater and the group “GroupPlayers” to be the second.
There are the other functions inside the Custom Behavior to make condition, expression… and what is called Lifecycle methods. The link for wiki explains a little about them.
You also can add more informations in your Behavior. I add a description:
And now it shows on top of the action:
One way to try to better understand the use of behaviors is to install some simple behavior and see how it works. I did this with the “Health Points and Damage” extension when it was even simpler before it got a lot of updates.
I hope I managed to clear your doubt.
This definitely helps, will give it a try. Still can’t think of how to get rid of my initial problem though.
Like I said the think function of the enemy runs in the extension / behavior, its action is executed by the
doStepPreEvents builtin function. As it’s not called by the scene, it doesn’t have anything parsing the players object group to it. Only workaround seems like the scene calling a one-time action in the behavior that sets this group, but I’m not aware of a way to store it for the think function to use each frame; You can have a string or number or boolean variable, but I’m not aware of a variable that stores object references. Is some kind of solution to this presently possible?
Update 1: Haven’t tried it yet but I’m seeing a “copy function parameter to variable” and “copy variable to function parameter”. Can this be safely used for the scene to only once inform the behavior about the group, then have the behavior retrieve and use this information per frame?
Update 2: Never mind, won’t work. Those actions only work for scene variables, there’s no way to convert an object group into one of those. Please let me know what else you suggest.
For the time being I went with the only obvious option: I’ll be calling the attack action in the enemy behavior from within the scene events with a simple Pick All. It does feel like an ugly hack, maybe I can better justify having to do it this way… at the very least however it will work as intended.
I think you are trying to use the “wrong” Behavior function for what you want. If you look it says that have 2 paramaters and don’t have the option to make more than that.
Wiki says: “You’ll be given the choice between some predefined functions, called lifecycle methods, or a custom function.”
So, this predefined functions DoStepPreEvents/onStepPostEvents can run before/after your events sheets. Probably this must be important to update information, but I don’t know exactly when to use it. And I don’t know why we cannot put other paramaters.
Anyway, maybe you could take your events that’s in DoStepPreEvents and put in an action to use paramaters?
Edit: Did you use the “Extract events to a function” or are you doing all the extension manually?
Yes, I did just that. I use DoStepPreEvents / onStepPostEvents as they’re the ones that run per-frame: If I execute a custom action from them, I can indeed add the required parameters… of course custom actions that check other objects need to be executed from the scene as to deliver those objects as a parameter, so for them I left my exception and am running them per-frame from events instead.