Add AnimatableBody inherited from StaticBody for moving platforms

Instead of having a physics node named Static that can be either Static
or Kinematic, AnimatableBody is added again as a separate node:
-Inherited from StaticBody to make its usage clearer
-Still separated from CharacterBody to make its usage more focused

Properly implemented constant velocity for kinematic bodies in godot
physics servers (induced velocity without actually moving).

Also updated description for the different physics nodes to make their
usage clearer.
This commit is contained in:
PouleyKetchoupp 2021-08-30 11:48:43 -07:00
parent 036b7a0985
commit 83baecdff0
21 changed files with 291 additions and 429 deletions

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AnimatableBody2D" inherits="StaticBody2D" version="4.0">
<brief_description>
Physics body for 2D physics which moves only by script or animation. Useful for moving platforms and doors.
</brief_description>
<description>
Animatable body for 2D physics.
An animatable body can't be moved by external forces or contacts, but can be moved by script or animation to affect other bodies in its path. It is ideal for implementing moving objects in the environment, such as moving platforms or doors.
When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide].
</member>
</members>
<constants>
</constants>
</class>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AnimatableBody3D" inherits="StaticBody3D" version="4.0">
<brief_description>
Physics body for 3D physics which moves only by script or animation. Useful for moving platforms and doors.
</brief_description>
<description>
Animatable body for 3D physics.
An animatable body can't be moved by external forces or contacts, but can be moved by script or animation to affect other bodies in its path. It is ideal for implementing moving objects in the environment, such as moving platforms or doors.
When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
</description>
<tutorials>
<link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
</tutorials>
<methods>
</methods>
<members>
<member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody3D.move_and_collide].
</member>
</members>
<constants>
</constants>
</class>

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CharacterBody2D" inherits="PhysicsBody2D" version="4.0">
<brief_description>
Character body 2D node.
Specialized 2D physics body node for characters moved by script.
</brief_description>
<description>
Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses:
[b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics.
[b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path.
Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a [AnimatableBody2D]. However, they have two main uses:
[b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody2D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics.
[b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody2D]), which allows them to be moved by code and push other bodies on their path.
</description>
<tutorials>
<link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CharacterBody3D" inherits="PhysicsBody3D" version="4.0">
<brief_description>
Character body 3D node.
Specialized 3D physics body node for characters moved by script.
</brief_description>
<description>
Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a static body. However, they have two main uses:
Character bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a rigid body, these are the same as a [AnimatableBody3D]. However, they have two main uses:
[b]Kinematic characters:[/b] Character bodies have an API for moving objects with walls and slopes detection ([method move_and_slide] method), in addition to collision detection (also done with [method PhysicsBody3D.move_and_collide]). This makes them really useful to implement characters that move in specific ways and collide with the world, but don't require advanced physics.
[b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [member StaticBody3D.kinematic_motion] when enabled), which allows them to be moved by code and push other bodies on their path.
[b]Kinematic motion:[/b] Character bodies can also be used for kinematic motion (same functionality as [AnimatableBody3D]), which allows them to be moved by code and push other bodies on their path.
</description>
<tutorials>
<link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>

View file

@ -913,7 +913,7 @@
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
Constant for static bodies. In this mode, a body can be only moved by user code.
Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved.
</constant>
<constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode">
Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path.

View file

@ -1262,7 +1262,7 @@
This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
</constant>
<constant name="BODY_MODE_STATIC" value="0" enum="BodyMode">
Constant for static bodies. In this mode, a body can be only moved by user code.
Constant for static bodies. In this mode, a body can be only moved by user code and doesn't collide with other bodies along its path when moved.
</constant>
<constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode">
Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path.

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RigidBody2D" inherits="PhysicsBody2D" version="4.0">
<brief_description>
A body that is controlled by the 2D physics engine.
Physics Body which is moved by 2D physics simulation. Useful for objects that have gravity and can be pushed by other objects.
</brief_description>
<description>
This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties.
@ -131,6 +131,7 @@
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody2D.Mode" default="0">
The body's mode. See [enum Mode] for possible values.
For a body that uses only Static or Kinematic mode, use [StaticBody2D] or [AnimatableBody2D] instead.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
@ -199,7 +200,7 @@
Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate.
</constant>
<constant name="MODE_KINEMATIC" value="3" enum="Mode">
Kinematic body mode. The body behaves like a [StaticBody2D] with [member StaticBody2D.kinematic_motion] enabled, and must be moved by user code.
Kinematic body mode. The body behaves like a [AnimatableBody2D], and must be moved by code.
</constant>
<constant name="CCD_MODE_DISABLED" value="0" enum="CCDMode">
Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RigidBody3D" inherits="PhysicsBody3D" version="4.0">
<brief_description>
Physics Body whose position is determined through physics simulation in 3D space.
Physics Body which is moved by 3D physics simulation. Useful for objects that have gravity and can be pushed by other objects.
</brief_description>
<description>
This is the node that implements full 3D physics. This means that you do not control a RigidBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc.
@ -130,7 +130,8 @@
The body's mass.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody3D.Mode" default="0">
The body mode. See [enum Mode] for possible values.
The body's mode. See [enum Mode] for possible values.
For a body that uses only Static or Kinematic mode, use [StaticBody3D] or [AnimatableBody3D] instead.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
@ -201,7 +202,7 @@
Locked dynamic body mode. Similar to [constant MODE_DYNAMIC], but the body can not rotate.
</constant>
<constant name="MODE_KINEMATIC" value="3" enum="Mode">
Kinematic body mode. The body behaves like a [StaticBody3D] with [member StaticBody3D.kinematic_motion] enabled, and can only move by user code.
Kinematic body mode. The body behaves like a [AnimatableBody3D], and can only move by user code.
</constant>
</constants>
</class>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="StaticBody2D" inherits="PhysicsBody2D" version="4.0">
<brief_description>
Static body for 2D physics.
Physics body for 2D physics which is static or moves only by script. Useful for floor and walls.
</brief_description>
<description>
Static body for 2D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], they don't consume any CPU resources as long as they don't move.
They however have extra functionalities to move and affect other bodies:
[b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
[b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path.
[b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path.
Static body for 2D physics.
A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], it doesn't consume any CPU resources as long as they don't move.
They have extra functionalities to move and affect other bodies:
[b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path.
[b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels.
</description>
<tutorials>
</tutorials>
@ -16,22 +16,15 @@
</methods>
<members>
<member name="constant_angular_velocity" type="float" setter="set_constant_angular_velocity" getter="get_constant_angular_velocity" default="0.0">
The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating.
The body's constant angular velocity. This does not rotate the body, but affects touching bodies, as if it were rotating.
</member>
<member name="constant_linear_velocity" type="Vector2" setter="set_constant_linear_velocity" getter="get_constant_linear_velocity" default="Vector2(0, 0)">
The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving.
</member>
<member name="kinematic_motion" type="bool" setter="set_kinematic_motion_enabled" getter="is_kinematic_motion_enabled" default="false">
If [code]true[/code], the body will act the same as a [RigidBody2D] in [constant RigidBody2D.MODE_KINEMATIC] mode.
When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
The body's constant linear velocity. This does not move the body, but affects touching bodies, as if it were moving.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide].
</member>
</members>
<constants>
</constants>

View file

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="StaticBody3D" inherits="PhysicsBody3D" version="4.0">
<brief_description>
Static body for 3D physics.
Physics body for 3D physics which is static or moves only by script. Useful for floor and walls.
</brief_description>
<description>
Static body for 3D physics. A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], they don't consume any CPU resources as long as they don't move.
They however have extra functionalities to move and affect other bodies:
[b]Constant velocity:[/b] [member constant_linear_velocity] and [member constant_angular_velocity] can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
[b]Transform change:[/b] Static bodies can be also moved by code. Unless [member kinematic_motion] is enabled, they are just teleported in this case and don't affect other bodies on their path.
[b]Kinematic motion:[/b] Static bodies can have [member kinematic_motion] enabled to make them kinematic bodies that can be moved by code and push other bodies on their path.
Static body for 3D physics.
A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], it doesn't consume any CPU resources as long as they don't move.
They have extra functionalities to move and affect other bodies:
[b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path.
[b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels.
</description>
<tutorials>
<link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link>
@ -19,22 +19,15 @@
</methods>
<members>
<member name="constant_angular_velocity" type="Vector3" setter="set_constant_angular_velocity" getter="get_constant_angular_velocity" default="Vector3(0, 0, 0)">
The body's constant angular velocity. This does not rotate the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were rotating.
The body's constant angular velocity. This does not rotate the body, but affects touching bodies, as if it were rotating.
</member>
<member name="constant_linear_velocity" type="Vector3" setter="set_constant_linear_velocity" getter="get_constant_linear_velocity" default="Vector3(0, 0, 0)">
The body's constant linear velocity. This does not move the body (unless [member kinematic_motion] is enabled), but affects other bodies that touch it, as if it were moving.
</member>
<member name="kinematic_motion" type="bool" setter="set_kinematic_motion_enabled" getter="is_kinematic_motion_enabled" default="false">
If [code]true[/code], the body will act the same as a [RigidBody3D] in [constant RigidBody3D.MODE_KINEMATIC] mode.
When the body is moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to [code]physics[/code]), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
The body's constant linear velocity. This does not move the body, but affects touching bodies, as if it were moving.
</member>
<member name="physics_material_override" type="PhysicsMaterial" setter="set_physics_material_override" getter="get_physics_material_override">
The physics material override for the body.
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
<member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody3D.move_and_collide].
</member>
</members>
<constants>
</constants>

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#8da5f3" fill-opacity=".99" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#8da5f3"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1 @@
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".99" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#fc7f7f"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -165,21 +165,13 @@ void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
constant_linear_velocity = p_vel;
if (kinematic_motion) {
_update_kinematic_motion();
} else {
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
}
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
}
void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
constant_angular_velocity = p_vel;
if (kinematic_motion) {
_update_kinematic_motion();
} else {
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
Vector2 StaticBody2D::get_constant_linear_velocity() const {
@ -209,158 +201,22 @@ Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
return physics_material_override;
}
void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
if (p_enabled == kinematic_motion) {
return;
}
kinematic_motion = p_enabled;
if (kinematic_motion) {
set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
} else {
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
update_configuration_warnings();
return;
}
#endif
_update_kinematic_motion();
}
bool StaticBody2D::is_kinematic_motion_enabled() const {
return kinematic_motion;
}
void StaticBody2D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
sync_to_physics = p_enable;
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
update_configuration_warnings();
return;
}
#endif
if (kinematic_motion) {
_update_kinematic_motion();
}
}
bool StaticBody2D::is_sync_to_physics_enabled() const {
return sync_to_physics;
}
void StaticBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
StaticBody2D *body = (StaticBody2D *)p_instance;
body->_body_state_changed(p_state);
}
void StaticBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
if (!sync_to_physics) {
return;
}
last_valid_transform = p_state->get_transform();
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
set_notify_local_transform(true);
}
TypedArray<String> StaticBody2D::get_configuration_warnings() const {
TypedArray<String> warnings = PhysicsBody2D::get_configuration_warnings();
if (sync_to_physics && !kinematic_motion) {
warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
}
return warnings;
}
void StaticBody2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
last_valid_transform = get_global_transform();
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
// Used by sync to physics, send the new transform to the physics...
Transform2D new_transform = get_global_transform();
double delta_time = get_physics_process_delta_time();
new_transform.translate(constant_linear_velocity * delta_time);
new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
// ... but then revert changes.
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
set_notify_local_transform(true);
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
ERR_FAIL_COND(!kinematic_motion);
Transform2D new_transform = get_global_transform();
double delta_time = get_physics_process_delta_time();
new_transform.translate(constant_linear_velocity * delta_time);
new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
if (sync_to_physics) {
// Propagate transform change to node.
set_global_transform(new_transform);
} else {
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
// Propagate transform change to node.
set_block_transform_notify(true);
set_global_transform(new_transform);
set_block_transform_notify(false);
}
} break;
}
}
void StaticBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody2D::set_kinematic_motion_enabled);
ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody2D::is_kinematic_motion_enabled);
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody2D::set_sync_to_physics);
ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody2D::is_sync_to_physics_enabled);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
StaticBody2D::StaticBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) {
StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
PhysicsBody2D(p_mode) {
}
void StaticBody2D::_reload_physics_characteristics() {
@ -373,14 +229,28 @@ void StaticBody2D::_reload_physics_characteristics() {
}
}
void StaticBody2D::_update_kinematic_motion() {
void AnimatableBody2D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
sync_to_physics = p_enable;
_update_kinematic_motion();
}
bool AnimatableBody2D::is_sync_to_physics_enabled() const {
return sync_to_physics;
}
void AnimatableBody2D::_update_kinematic_motion() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
if (kinematic_motion && sync_to_physics) {
if (sync_to_physics) {
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
set_only_update_transform_changes(true);
set_notify_local_transform(true);
@ -389,15 +259,54 @@ void StaticBody2D::_update_kinematic_motion() {
set_only_update_transform_changes(false);
set_notify_local_transform(false);
}
}
bool needs_physics_process = false;
if (kinematic_motion) {
if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) {
needs_physics_process = true;
}
void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
AnimatableBody2D *body = (AnimatableBody2D *)p_instance;
body->_body_state_changed(p_state);
}
void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
if (!sync_to_physics) {
return;
}
set_physics_process_internal(needs_physics_process);
last_valid_transform = p_state->get_transform();
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
set_notify_local_transform(true);
}
void AnimatableBody2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
last_valid_transform = get_global_transform();
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
// Used by sync to physics, send the new transform to the physics...
Transform2D new_transform = get_global_transform();
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
// ... but then revert changes.
set_notify_local_transform(false);
set_global_transform(last_valid_transform);
set_notify_local_transform(true);
} break;
}
}
void AnimatableBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics);
ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
AnimatableBody2D::AnimatableBody2D() :
StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
_update_kinematic_motion();
}
void RigidBody2D::_body_enter_tree(ObjectID p_id) {

View file

@ -63,21 +63,13 @@ public:
class StaticBody2D : public PhysicsBody2D {
GDCLASS(StaticBody2D, PhysicsBody2D);
private:
Vector2 constant_linear_velocity;
real_t constant_angular_velocity = 0.0;
Ref<PhysicsMaterial> physics_material_override;
bool kinematic_motion = false;
bool sync_to_physics = false;
Transform2D last_valid_transform;
static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
void _body_state_changed(PhysicsDirectBodyState2D *p_state);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
@ -90,18 +82,33 @@ public:
Vector2 get_constant_linear_velocity() const;
real_t get_constant_angular_velocity() const;
virtual TypedArray<String> get_configuration_warnings() const override;
StaticBody2D();
StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC);
private:
void _reload_physics_characteristics();
};
class AnimatableBody2D : public StaticBody2D {
GDCLASS(AnimatableBody2D, StaticBody2D);
private:
bool sync_to_physics = false;
Transform2D last_valid_transform;
static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
void _body_state_changed(PhysicsDirectBodyState2D *p_state);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
AnimatableBody2D();
private:
void _update_kinematic_motion();
void set_kinematic_motion_enabled(bool p_enabled);
bool is_kinematic_motion_enabled() const;
void set_sync_to_physics(bool p_enable);
bool is_sync_to_physics_enabled() const;
};

View file

@ -223,72 +223,98 @@ Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
return physics_material_override;
}
void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) {
if (p_enabled == kinematic_motion) {
return;
}
kinematic_motion = p_enabled;
if (kinematic_motion) {
set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
} else {
set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
update_configuration_warnings();
return;
}
#endif
_update_kinematic_motion();
}
bool StaticBody3D::is_kinematic_motion_enabled() const {
return kinematic_motion;
}
void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
constant_linear_velocity = p_vel;
if (kinematic_motion) {
_update_kinematic_motion();
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
}
void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
constant_angular_velocity = p_vel;
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
Vector3 StaticBody3D::get_constant_linear_velocity() const {
return constant_linear_velocity;
}
Vector3 StaticBody3D::get_constant_angular_velocity() const {
return constant_angular_velocity;
}
void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
}
StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) :
PhysicsBody3D(p_mode) {
}
void StaticBody3D::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
} else {
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
void StaticBody3D::set_sync_to_physics(bool p_enable) {
Vector3 AnimatableBody3D::get_linear_velocity() const {
return linear_velocity;
}
Vector3 AnimatableBody3D::get_angular_velocity() const {
return angular_velocity;
}
void AnimatableBody3D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
sync_to_physics = p_enable;
_update_kinematic_motion();
}
bool AnimatableBody3D::is_sync_to_physics_enabled() const {
return sync_to_physics;
}
void AnimatableBody3D::_update_kinematic_motion() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
update_configuration_warnings();
return;
}
#endif
if (kinematic_motion) {
_update_kinematic_motion();
if (sync_to_physics) {
set_only_update_transform_changes(true);
set_notify_local_transform(true);
} else {
set_only_update_transform_changes(false);
set_notify_local_transform(false);
}
}
bool StaticBody3D::is_sync_to_physics_enabled() const {
return sync_to_physics;
}
void StaticBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
StaticBody3D *body = (StaticBody3D *)p_instance;
void AnimatableBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
AnimatableBody3D *body = (AnimatableBody3D *)p_instance;
body->_body_state_changed(p_state);
}
void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
linear_velocity = p_state->get_linear_velocity();
angular_velocity = p_state->get_angular_velocity();
@ -303,43 +329,7 @@ void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
_on_transform_changed();
}
TypedArray<String> StaticBody3D::get_configuration_warnings() const {
TypedArray<String> warnings = PhysicsBody3D::get_configuration_warnings();
if (sync_to_physics && !kinematic_motion) {
warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
}
return warnings;
}
void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
constant_angular_velocity = p_vel;
if (kinematic_motion) {
_update_kinematic_motion();
} else {
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
}
Vector3 StaticBody3D::get_constant_linear_velocity() const {
return constant_linear_velocity;
}
Vector3 StaticBody3D::get_constant_angular_velocity() const {
return constant_angular_velocity;
}
Vector3 StaticBody3D::get_linear_velocity() const {
return linear_velocity;
}
Vector3 StaticBody3D::get_angular_velocity() const {
return angular_velocity;
}
void StaticBody3D::_notification(int p_what) {
void AnimatableBody3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
last_valid_transform = get_global_transform();
@ -349,17 +339,6 @@ void StaticBody3D::_notification(int p_what) {
// Used by sync to physics, send the new transform to the physics...
Transform3D new_transform = get_global_transform();
double delta_time = get_physics_process_delta_time();
new_transform.origin += constant_linear_velocity * delta_time;
real_t ang_vel = constant_angular_velocity.length();
if (!Math::is_zero_approx(ang_vel)) {
Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
Basis rot(ang_vel_axis, ang_vel * delta_time);
new_transform.basis = rot * new_transform.basis;
new_transform.orthonormalize();
}
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
// ... but then revert changes.
@ -368,108 +347,21 @@ void StaticBody3D::_notification(int p_what) {
set_notify_local_transform(true);
_on_transform_changed();
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
ERR_FAIL_COND(!kinematic_motion);
Transform3D new_transform = get_global_transform();
double delta_time = get_physics_process_delta_time();
new_transform.origin += constant_linear_velocity * delta_time;
real_t ang_vel = constant_angular_velocity.length();
if (!Math::is_zero_approx(ang_vel)) {
Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
Basis rot(ang_vel_axis, ang_vel * delta_time);
new_transform.basis = rot * new_transform.basis;
new_transform.orthonormalize();
}
if (sync_to_physics) {
// Propagate transform change to node.
set_global_transform(new_transform);
} else {
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
// Propagate transform change to node.
set_ignore_transform_notification(true);
set_global_transform(new_transform);
set_ignore_transform_notification(false);
_on_transform_changed();
}
} break;
}
}
void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
void AnimatableBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody3D::set_sync_to_physics);
ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody3D::is_sync_to_physics_enabled);
ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody3D::set_kinematic_motion_enabled);
ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody3D::is_kinematic_motion_enabled);
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody3D::set_sync_to_physics);
ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody3D::is_sync_to_physics_enabled);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
StaticBody3D::StaticBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
}
AnimatableBody3D::AnimatableBody3D() :
StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
void StaticBody3D::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
} else {
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
void StaticBody3D::_update_kinematic_motion() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
if (kinematic_motion && sync_to_physics) {
set_only_update_transform_changes(true);
set_notify_local_transform(true);
} else {
set_only_update_transform_changes(false);
set_notify_local_transform(false);
}
bool needs_physics_process = false;
if (kinematic_motion) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &StaticBody3D::_body_state_changed_callback);
if (!constant_angular_velocity.is_equal_approx(Vector3()) || !constant_linear_velocity.is_equal_approx(Vector3())) {
needs_physics_process = true;
}
} else {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
}
set_physics_process_internal(needs_physics_process);
_update_kinematic_motion();
}
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
@ -1042,7 +934,7 @@ void RigidBody3D::_bind_methods() {
RigidBody3D::RigidBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &RigidBody3D::_body_state_changed_callback);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
}
RigidBody3D::~RigidBody3D() {
@ -2713,7 +2605,7 @@ void PhysicalBone3D::_start_physics_simulation() {
set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &PhysicalBone3D::_body_state_changed_callback);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
set_as_top_level(true);
_internal_simulate_physics = true;
}

View file

@ -73,24 +73,13 @@ public:
class StaticBody3D : public PhysicsBody3D {
GDCLASS(StaticBody3D, PhysicsBody3D);
private:
Vector3 constant_linear_velocity;
Vector3 constant_angular_velocity;
Vector3 linear_velocity;
Vector3 angular_velocity;
Ref<PhysicsMaterial> physics_material_override;
bool kinematic_motion = false;
bool sync_to_physics = false;
Transform3D last_valid_transform;
static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
void _body_state_changed(PhysicsDirectBodyState3D *p_state);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
@ -103,21 +92,39 @@ public:
Vector3 get_constant_linear_velocity() const;
Vector3 get_constant_angular_velocity() const;
virtual Vector3 get_linear_velocity() const override;
virtual Vector3 get_angular_velocity() const override;
virtual TypedArray<String> get_configuration_warnings() const override;
StaticBody3D();
StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC);
private:
void _reload_physics_characteristics();
};
class AnimatableBody3D : public StaticBody3D {
GDCLASS(AnimatableBody3D, StaticBody3D);
private:
Vector3 linear_velocity;
Vector3 angular_velocity;
bool sync_to_physics = false;
Transform3D last_valid_transform;
static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
void _body_state_changed(PhysicsDirectBodyState3D *p_state);
protected:
void _notification(int p_what);
static void _bind_methods();
public:
virtual Vector3 get_linear_velocity() const override;
virtual Vector3 get_angular_velocity() const override;
AnimatableBody3D();
private:
void _update_kinematic_motion();
void set_kinematic_motion_enabled(bool p_enabled);
bool is_kinematic_motion_enabled() const;
void set_sync_to_physics(bool p_enable);
bool is_sync_to_physics_enabled() const;
};

View file

@ -488,6 +488,7 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
GDREGISTER_CLASS(StaticBody3D);
GDREGISTER_CLASS(AnimatableBody3D);
GDREGISTER_CLASS(RigidBody3D);
GDREGISTER_CLASS(KinematicCollision3D);
GDREGISTER_CLASS(CharacterBody3D);
@ -647,6 +648,7 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(CollisionObject2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D);
GDREGISTER_CLASS(StaticBody2D);
GDREGISTER_CLASS(AnimatableBody2D);
GDREGISTER_CLASS(RigidBody2D);
GDREGISTER_CLASS(CharacterBody2D);
GDREGISTER_CLASS(KinematicCollision2D);

View file

@ -269,11 +269,13 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: {
linear_velocity = p_variant;
constant_linear_velocity = linear_velocity;
wakeup();
} break;
case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: {
angular_velocity = p_variant;
constant_angular_velocity = angular_velocity;
wakeup();
} break;
@ -429,10 +431,10 @@ void Body2DSW::integrate_forces(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {
//compute motion, angular and etc. velocities from prev transform
motion = new_transform.get_origin() - get_transform().get_origin();
linear_velocity = motion / p_step;
linear_velocity = constant_linear_velocity + motion / p_step;
real_t rot = new_transform.get_rotation() - get_transform().get_rotation();
angular_velocity = remainder(rot, 2.0 * Math_PI) / p_step;
angular_velocity = constant_angular_velocity + remainder(rot, 2.0 * Math_PI) / p_step;
do_motion = true;
@ -621,8 +623,6 @@ Body2DSW::Body2DSW() :
direct_state_query_list(this) {
mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
active = true;
angular_velocity = 0;
biased_angular_velocity = 0;
mass = 1;
inertia = 0;
user_inertia = false;

View file

@ -44,10 +44,13 @@ class Body2DSW : public CollisionObject2DSW {
PhysicsServer2D::BodyMode mode;
Vector2 biased_linear_velocity;
real_t biased_angular_velocity;
real_t biased_angular_velocity = 0.0;
Vector2 linear_velocity;
real_t angular_velocity;
real_t angular_velocity = 0.0;
Vector2 constant_linear_velocity;
real_t constant_angular_velocity = 0.0;
real_t linear_damp;
real_t angular_damp;

View file

@ -302,10 +302,12 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va
} break;
case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: {
linear_velocity = p_variant;
constant_linear_velocity = linear_velocity;
wakeup();
} break;
case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: {
angular_velocity = p_variant;
constant_angular_velocity = angular_velocity;
wakeup();
} break;
@ -473,7 +475,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
//compute motion, angular and etc. velocities from prev transform
motion = new_transform.origin - get_transform().origin;
do_motion = true;
linear_velocity = motion / p_step;
linear_velocity = constant_linear_velocity + motion / p_step;
//compute a FAKE angular velocity, not so easy
Basis rot = new_transform.basis.orthonormalized() * get_transform().basis.orthonormalized().transposed();
@ -482,7 +484,7 @@ void Body3DSW::integrate_forces(real_t p_step) {
rot.get_axis_angle(axis, angle);
axis.normalize();
angular_velocity = axis * (angle / p_step);
angular_velocity = constant_angular_velocity + axis * (angle / p_step);
} else {
if (!omit_force_integration && !first_integration) {
//overridden by direct state query

View file

@ -44,6 +44,9 @@ class Body3DSW : public CollisionObject3DSW {
Vector3 linear_velocity;
Vector3 angular_velocity;
Vector3 constant_linear_velocity;
Vector3 constant_angular_velocity;
Vector3 biased_linear_velocity;
Vector3 biased_angular_velocity;
real_t mass;