Repository navigation
Add an action to change the body type of 3D physics objects - #9270
Merged
Merged
Conversation
An object can now switch between static, dynamic and kinematic during the game. For instance, an enemy moved by a pathfinding behavior can be kinematic (other objects can't push it), and become dynamic to be thrown by an impulse when it is hit. The body is created again right away, keeping its velocities, so that an impulse applied by the next action acts on the new body. Static bodies are in the layers 1 to 4, dynamic and kinematic bodies in the layers 5 to 8: with the default layers (1 and 5), the object collides with the same objects after the change. Bodies of 3D characters and 3D cars, and mesh shapes (which can only be static), are not changed. The body type is synchronized in multiplayer games. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
Contributor
⏱️ Game engine benchmarks: ✅ no significant change on the 31 benchmarksAll the 31 benchmarks and how they are measured
✅ The counters (draw calls, objects count and final state) of the 9 scene benchmarks run on both versions are unchanged. Comparing |
The 3D character and car behaviors replace the body updater of the physics behavior only when they first handle the body, at their first step. An action changing the body type right after the object is created (like "Create Player" then "Change the body type of Player") ran before that, and changed the body type of the character. They now mark the physics behavior when they are created, and the body type of a marked behavior is never changed. The test changes the body type of a character right after it is created. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
The body type can't be changed while a 3D character or 3D car behavior of the object is activated, and can be changed otherwise, like for any other physics object. When one of them is activated again, the body gets back its type from the editor. The physics behavior keeps the list of these behaviors instead of a flag, so an object with both (even activated together by mistake) stays locked until both are deactivated. A deactivated 3D car no longer takes the body back when its drive wheels are changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
Static objects use the layers 1 to 4 and moving objects the layers 5 to 8. The editor only showed the layers of the current type, and hid the masks of static objects, so they couldn't be set for an object whose type is changed during the game. Now both are shown: the layers of the current type, then "Layers if made static" (or "if made dynamic or kinematic"), and the masks, labelled "Masks if made dynamic or kinematic" for a static object, with descriptions saying when they are used. The description of the type mentions the "Body type" action. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
Contributor
|
Storybook for this branch: latest · commit cae1aee Updated automatically after each Storybook build. |
The layers and masks are shown in two sections of "Collision filtering": "If static" (the layers 1 to 4) and "If dynamic or kinematic" (the layers 5 to 8 and the masks, which say which layers the object collides with). Before, the rows were reordered and relabelled when the type changed, and the masks of a static object looked like they used static layers. Property groups can now contain a sub-group, written "Group > Sub-group": the properties panels show it as a section of the group, with a smaller title, in the order of its first property. The Physics3D behavior editor shows the same sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
Like the 3D physics behavior. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a "Body type" action to the 3D physics behavior, to switch an object between static, dynamic and kinematic during the game. The conditions to check the type ("Is static", "Is dynamic", "Is kinematic") already exist. The editor now shows the collision filtering of each type, and property groups can have sub-groups.
For instance, an enemy moved by a pathfinding behavior (like the navmesh) can be kinematic, so that the player bumps into it without pushing it, and become dynamic to be thrown by an impulse when it is shot. The 3D FPS starters with enemies (GDevelopApp/GDevelop-examples#1097, GDevelopApp/GDevelop-examples#1087) currently need a workaround for this: a dynamic body without gravity, with the collisions with static objects disabled and a much higher density while it walks, then the settings restored and the behavior deactivated and activated again to rebuild the body before the impulse. With this action, the death becomes "change the body type to Dynamic, apply the impulse".
Behavior
recreateBody, which keeps the linear and angular velocities. So an impulse applied by the next action acts on the new body (a kinematic body ignores impulses). A kinematic body moved by another behavior already gets that movement as its velocity at each step, so it keeps its momentum when it becomes dynamic.getLayersAccordingToBodyType). Between kinematic and dynamic, nothing changes. To or from static, the object collides with the same objects with the default layers (1 and 5).bodyTypein the props of the sync data; a client already recreates the body at each update, so the new type is used right away). The value is absent in data from older versions, and then ignored. It adds a short string per physics object to each sync message.3D characters and 3D cars
An object is always in one of these two states:
Adding, activating or deactivating these behaviors only moves an object between the two states:
onCreated, called when the object is created, before the next action runs), and the action checks whether one of them is activated. So an object with both a 3D character and a 3D car (even activated together by mistake) stays locked until both are deactivated.getPhysics3Dnow checks that the car is activated, like the character already did).This allows, for instance, deactivating a 3D car when the player gets out of it and making it static (or kinematic, to be moved along a path), then activating it again when the player gets back in.
Editor: collision filtering by body type
The editor only showed the layers of the current type, and hid the masks of static objects: they couldn't be set for an object whose type is changed during the game. Showing all of them in a flat list was confusing too (the masks of a static object looked like they used static layers). Now "Collision filtering" has two sections, always in the same order whatever the type:
The descriptions say that a static object has no masks: it collides with the dynamic and kinematic objects whose masks include its layers. Both layer rows edit the same
layersvalue (layersIfDynamicOrKinematicis a property shown in the editor only, written tolayers; Physics3D can't be overridden per instance). The description of the type mentions the "Body type" action (and the kinematic part is corrected: kinematic objects aren't moved by forces).Sub-groups of properties: a property group can now contain a sub-group, written
Group > Sub-group(hereCollision filtering > If static).propertiesMapToSchemashows it as a section of the group, in the order of its first property (sub-groups aren't sorted by name, so "If static", with thelayersproperty, comes before "If dynamic or kinematic"), and the compact properties panel draws its title smaller than the group title (isSubgroupin the schema). Groups without>are unchanged. The Physics3D behavior editor shows the same sections.The masks of the 2D physics behavior are labelled "Masks (collides with)" too.
Tests
In
Physics3DRuntimeBehavior.spec.js:In
PhysicsCharacter3DRuntimeBehavior.spec.js:In the new
PhysicsCar3DRuntimeBehavior.spec.js(the car script is added to the karma files):In
PropertiesMapToSchema.spec.js: sub-groups are sections of their group, in the order of their first property, next to the fields of the group (both tests fail without the change).Each part of the runtime change is caught by a test: without the restore of the type, 4 tests fail; checking that all of these behaviors are activated instead of one, the test with both behaviors fails; without the activation check of the car, the drive wheels test fails; without the synchronization of
bodyType, the multiplayer test fails. All 1440 GDJS tests pass (karma, headless Chromium), andtscandprettierpass. For the editor:flowandeslintpass, the extension sanity tests pass, and both panels were checked in Storybook (the screenshots above).Checked in a real game: the FPS with enemies starter, changed to use the action (kinematic enemies moved by the navmesh, "Body type: Dynamic" before the impulse of the shot), exported and run by the gameplay tests of the examples repository with GDevelop 5.6.284 and the Physics3D files of this PR (Physics3D is the same in 5.6.284 and
master): its 6 tests pass. A walking enemy blocks the player completely, and a shot enemy becomes dynamic, is thrown back, tumbles and lies on the ground. With the unchanged 5.6.284, the action is unknown and skipped: the enemy is not thrown, and the test fails.🤖 Generated with Claude Code
https://claude.ai/code/session_01Wa8uKpYuQrYqGYnqGCsquj