Implementing conveyor belt in 2D

Godot Version

v4.4.1.stable.mono.official [49a5bc7b6]

Question

I have a StaticBody2D that contains AnimatedSprite2D, CollisionShape2D, and Area2D for detection of CharacterBody2D on top of it. Entire package represents 2D conveyor belt.

This is the script that controls it:

public partial class Conveyor : StaticBody2D
{
	[Export] private float speed = 700f;
	private Area2D detectionZone;
	private readonly List<CharacterBody2D> bodiesOnBelt = new();
	public override void _Ready()
	{
		detectionZone = GetNode<Area2D>("DetectionZone");
		if (detectionZone == null)
		{
			throw new NullReferenceException();
		}
		detectionZone.BodyEntered += OnBodyEntered;
		detectionZone.BodyExited += OnBodyExited;
	}

	public override void _PhysicsProcess(double delta)
	{
		if (bodiesOnBelt.Count > 0)
		{
			foreach (var body in bodiesOnBelt.Distinct())
			{
				if (body.IsOnFloor())
				{
					var v = body.Velocity;
					v.X = v.X + (speed * (float)delta);
					body.Velocity = v;
				}
			}
		}
	}

	private void OnBodyEntered(Node body)
	{
		if (body is CharacterBody2D character)
			bodiesOnBelt.Add(character);
	}

	private void OnBodyExited(Node body)
	{
		if (body is CharacterBody2D character)
			bodiesOnBelt.Remove(character);
	}
}

The thing I can’t figure out is how to only apply constant force to the CharacterBody2D. In current solution CharacterBody2D is pushed faster and faster every frame.

Standing CharacterBody2D should be pushed with speed value, when CharacterBody2D moves their speed should be adjusted depending on speed.

It should be easier to handle within CharacterBody2D script, but then I would have to implement it into every CharacterBody2D (player and NPCs have different scripts), and the more states you have, the messier things become.

To make a conveyor belt, you don’t need to do anything special. Staticbodies already have a Constant Linear Velocity property that can be set, and any physics body on it will be affected.

An example of how it works.

4 Likes