0
\$\begingroup\$

I've been reading the CharacterBody2D tutorial on Godot: https://docs.godotengine.org/en/4.2/tutorials/physics/using_character_body_2d.html

It states:

What is a character body?

CharacterBody2D is for implementing bodies that are controlled via code. Character bodies detect collisions with other bodies when moving, but are not affected by engine physics properties, like gravity or friction. While this means that you have to write some code to create their behavior, it also means you have more precise control over how they move and react.

Furthermore:

move_and_collide

This method takes one required parameter: a Vector2 indicating the body's relative movement. Typically, this is your velocity vector multiplied by the frame timestep (delta). If the engine detects a collision anywhere along this vector, the body will immediately stop moving. If this happens, the method will return a KinematicCollision2D object.

move_and_collide is most useful when you just want to move the body and detect collision, but don't need any automatic collision response. For example, if you need a bullet that ricochets off a wall, you can directly change the angle of the velocity when you detect a collision. See below for an example.

move_and_slide

The move_and_slide() method is intended to simplify the collision response in the common case where you want one body to slide along the other. It is especially useful in platformers or top-down games, for example.

The accompanying sample code (basic_movement.gd) demonstrates:

Examples

To see these examples in action, download the sample project: character_body_2d_starter.zip

extends CharacterBody2D

var speed = 300

func get_input():
  var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
  velocity = input_dir * speed

func _physics_process(delta):
  get_input()
  move_and_collide(velocity * delta)

This object stops the body when it hits a wall.

In physics classes, we often discuss velocity (e.g., when colliding with walls, producing sounds and converting energy which affects the velocity). However, the documentation for Godot states:

"Character bodies detect collisions with other bodies when moving, but are not affected by engine physics properties, like gravity or friction."

When I tried running the sample code, the object stopped when it collided. This can be said as the object's velocity becoming zero.

Is velocity not related to physics in a game engine? It seems puzzling.

Alternatively, if the object comes to a stop without any physical impact, what would have influenced it? Is the wall not physical?

Also, even though it says, "you have to write some code to create their behavior, it also means you have more precise control over how they move and react." their speed automatically becomes zero. What exactly do I need to implement myself?


Goal:

The documentation only mentions "physics properties, like gravity or friction," so I want to clarify what constitutes "physics."

Since it’s unclear what qualifies as physics, I don’t know what to implement. For example, should I not implement anything because velocity automatically becomes zero? Or should I handle what happens after stopping myself?

I plan to start programming for physics, but it’s ambiguous where the game engine's built-in functionality ends and where it doesn’t (due to vague expressions like “like”). This makes it hard to get started programming, so I want to make the starting point clearer.

The sample code bullet.gd seems to calculate the bounce velocity manually (requiring the game developer to determine the bounce velocity themselves).

extends CharacterBody2D

var speed = 750

func start(_position, _direction):
  rotation = _direction
  position = _position
  velocity = Vector2(speed, 0).rotated(rotation)

func _physics_process(delta):
  var collision = move_and_collide(velocity * delta)
  if collision:
      velocity = velocity.bounce(collision.get_normal())
      if collision.get_collider().has_method("hit"):
          collision.get_collider().hit()

func _on_VisibilityNotifier2D_screen_exited():
  # Deletes the bullet when it exits the screen.
  queue_free()

Related: What does the phrase "Kinematic bodies do not collide with other kinematic or static bodies" mean?

\$\endgroup\$
2
  • \$\begingroup\$ What is your goal? Making a perfect physics simulation or creating a play good/ feel good game with smooth controls? \$\endgroup\$
    – Zibelas
    Commented 2 days ago
  • \$\begingroup\$ @Zibelas I add the goal. \$\endgroup\$ Commented 2 days ago

2 Answers 2

3
\$\begingroup\$

Disclaimer: The specifics depend on the implementation so I will only comment on the general case, i.e. what "most" physics engines do.

In game physics there are usually three types of bodies:

  1. Static bodies: These are physics bodies that are never affected by any other object, it does not respond to any force and it does not move if another object collides with it (basically it has infinite mass). Static bodies are primarily a performance optimization and are usually used for things like terrain, buildings, trees, or other things that never move in a game.
  2. Kinematic bodies: These are physics bodies that, much like static bodies, ignore all forces and have infinite mass. The primary difference between a static and kinematic body is that kinematic bodies are allowed to move via modifying their velocity. If an object is moved via a script it is usually a kinematic body because it's easier to create good-feeling movement when you have full control over the object's velocity and don't have to worry about unintended forces (imagine playing a game, walking into a wall, and bouncing back!). This is why CharacterBody[2|3]D are kinematic bodies which is why in your example they don't bounce (because bouncing is caused by a force imparted on the object when hitting the wall, and kinematic bodies do not respond to forces).
  3. Dynamic bodies: These are physics bodies that behave like you would expect a physics-enabled object to behave. They respond to forces, bounce off surfaces, slow down due to friction, etc. Most inanimate objects are dynamic bodies (barrels, balls, dead NPCs, etc.).

Godot

Like you mentioned Godot's documentation states this:

Character bodies detect collisions with other bodies when moving, but are not affected by engine physics properties, like gravity or friction.

This is because, like I mentioned above, it is a kinematic body. It does not respond to any force imparted on it. If you want your character to bounce off walls you need to use a normal dynamic body instead.

When I tried running the sample code, the object stopped when it collided. This can be said as the object's velocity becoming zero.

In Godot's case this depends on the method you used to move the character body. In your example you use move_and_collide which will indeed stop the body when it collides with anything, expecting you to resolve the collision manually. However you could also have used move_and_slide which would allow the body to slide back and forth on the wall, basically only cancelling velocity in the direction it was moving in.

Is velocity not related to physics in a game engine? It seems puzzling.

All non-static objects have a velocity that they use to move.

Alternatively, if the object comes to a stop without any physical impact, what would have influenced it? Is the wall not physical?

Video game physics cheat a lot. In the real world the thing that prevents two objects from intersecting is the force created by the proximity of the atoms in the two objects pushing them away from each other. But in video games there are no atoms so the thing that prevents two objects from intersecting is "because we said so", i.e. we just manually separate objects that intersect without relying on forces to do so (side note, there are engines that do use forces to separate intersecting objects. In engines like this kinematic bodies are not separated from other objects when they are intersecting).

Since it’s unclear what qualifies as physics, I don’t know what to implement. For example, should I not implement anything because velocity automatically becomes zero? Or should I handle what happens after stopping myself?

Unless the thing you are programming is meant to respond to all forces then yes, you will have to program the behaviour yourself.

What exactly do I need to implement myself?

The physics engine will prevent objects from intersecting and will allow your body to push other non-kinematic bodies but that's about it. If you need your body to bounce when it hits a wall, get knocked back when it's hit by a bullet, or anything else like this you will have to do it yourself.

\$\endgroup\$
5
  • \$\begingroup\$ Generally speaking (setting Godot aside for now), what happens when two non-static bodies collide? For example, if body A collides with body B, does A require custom code for its rebound behavior while B automatically starts moving due to the impulse? Or do both A and B need to be programmed explicitly? \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ Do we need to consider all four combinations where A and B are either Kinematic or Dynamic bodies? Or is it sufficient to only consider the case where both A and B are non-static bodies? \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @shingo.nakanishi Only kinematic bodies need any manual code. If a kinematic body collides with a dynamic body the dynamic body will act like it collided with something with infinite mass. If two kinematic bodies collide and they are both meant to bounce away they both need code for this (I think in Godot the bodies will not intersect, at least). If two dynamic bodies collide they should handle that themselves entirely, from a physics perspective. \$\endgroup\$
    – Charanor
    Commented 2 days ago
  • \$\begingroup\$ If the behavior of Dynamic bodies is unsatisfactory, what are some possible approaches to address it? For instance, I’m particularly concerned about the statement "the dynamic body will act like it collided with something with infinite mass," as it seems unnatural since such a scenario doesn’t exist in the real world (although I understand I won’t know for sure until I actually try it). \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ Would potential solutions include switching from Dynamic bodies to Kinematic bodies, or adjusting the properties (e.g., making them heavier)? / Is it that Dynamic bodies cannot be programmed, or that they can be but should not be programmed due to convention? / Now that I think about it, even if programming Dynamic bodies directly is discouraged, it seems plausible that modifying properties like weight is acceptable. \$\endgroup\$ Commented 2 days ago
2
\$\begingroup\$

It's probably easier to answer this specifically for Godot. If we ignore objects that deform during collisions (with or without bones) there are basically four choices for your physics objects.

  • RigidBody3D
  • StaticBody3D
  • AnimatableBody3D
  • CharacterBody3D

RigidBody3D

Are your "normal" physics objects they have mass they bounce off each other. I think they are the only objects which have mass, hence the only objects which can do "proper" collisions are RigidBody3D's.

StaticBody3D

Are used for things that don't (usually) move (floors, walls, terrain). Effectively they behave as if they have infinite mass so a rigid body hitting it will either: Stop, Bounce or Slide - depending upon the properties of the Rigid body / the angle of impact.

However the StaticBody3D will still be stationary after the collision.

AnimatableBody3D

Is a subclass of StaticBody3D. If an AnimatableBody3D is not currently moving, it is basically identical to a StaticBody3D, rigid bodies will collide in the same way.

However if code (or an animation) is used to move the AnimatableBody3D, it will push any rigid bodies out of the way.

Note: AnimatableBody3D and StaticBody3D don't interact with each other - a moving AnimatableBody3D will simply pass through other AnimatableBody3D or StaticBody3Ds

CharacterBody3D

Is a special case, typically used for the player character, when it hits a StaticBody3d (or AnimatableBody3D) it will either stop or slide along it - by default it won't bounce off (but you can add code to do that).

A CharacterBody3D can't pass through rigid bodies, typically a collision results in pushing the RigidBody out of the way - however if the rigid body is blocked (by a wall) the CharacterBody3D can't push the rigid, so the characters movement gets blocked.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .