In this tutorial, I’ll explain how to control a Rigidbody to move an entity around—this is especially useful for character controllers or other physics-based moving entities.
First, it’s important to understand that as soon as you attach a Rigidbody component to an entity, you no longer control the entity’s position or rotation directly through its properties. Instead, the Rigidbody now governs the entity's transformations, updating its position and rotation based on physics calculations.
For character movement, you can use the
If you want to move the character forward in the direction it’s currently facing, you can calculate the forward vector using the
Display All
First, it’s important to understand that as soon as you attach a Rigidbody component to an entity, you no longer control the entity’s position or rotation directly through its properties. Instead, the Rigidbody now governs the entity's transformations, updating its position and rotation based on physics calculations.
For character movement, you can use the
LinearVelocity
function, which allows you to set movement along specific axes. For rotation, the AngularVelocity
function works similarly, controlling rotational movement around the specified axes. Both functions take a Vec3 as input, allowing you to define the exact axis on which you want to move or rotate the entity.If you want to move the character forward in the direction it’s currently facing, you can calculate the forward vector using the
CalculateForwardVector
function. Below is an example of how to move a character around:C Source Code
- using Genesis.Core;
- using Genesis.Core.Behaviors.Physics3D;
- using Genesis.Core.GameElements;
- using Genesis.Graphics;
- using Genesis.Math;
- using Genesis.Physics;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace Test3D
- {
- public class ThirdPersonController : IGameBehavior
- {
- public enum Animation
- {
- ANIMATION_IDLE,
- ANIMATION_WALK,
- ANIMATION_RUNNING,
- ANIMATION_JUMPING,
- ANIMATION_STRAFE_RIGHT,
- ANIMATION_STRAFE_LEFT,
- }
- public RigidBodyBehavior3D RigidBody { get; set; }
- public String IdleAnimation { get; set; }
- public String WalkAnimation { get; set; }
- public String RunningAnimation { get; set; }
- public String JumpingAnimation { get; set; }
- public String StrafeLeftAnimation { get; set; }
- public String StrafeRightAnimation { get; set; }
- public bool Airborn { get; set; }
- private long lastJump = 0;
- public ThirdPersonController(RigidBodyBehavior3D rigidBody)
- {
- this.RigidBody = rigidBody;
- rigidBody.OnCollide += RigidBody_OnCollide;
- }
- private void RigidBody_OnCollide(Scene scene, Game game, GameElement collision)
- {
- Console.WriteLine($"Coliding with {collision.Name}");
- this.Airborn = false;
- }
- public override void OnDestroy(Game game, GameElement parent)
- {
- }
- public override void OnInit(Game game, GameElement parent)
- {
- game.BeforeUpdate += Game_BeforeUpdate;
- }
- private void Game_BeforeUpdate(Game game, IRenderDevice renderDevice)
- {
- if(this.Airborn)
- {
- this.Airborn = false;
- }
- }
- public override void OnRender(Game game, GameElement parent)
- {
- }
- public override void OnUpdate(Game game, GameElement parent)
- {
- // Defines the used variables
- var model = (Model)parent;
- var animation = Animation.ANIMATION_IDLE;
- Vec3 linearVelocity = RigidBody.GetLinearVelocity();
- float angularVelocity = 0f;
- float speed = ((float)game.DeltaTime) * 0.2f;
- // Moving forwards & backwards
- if (Input.IsKeyDown(Input.Keys.W))
- {
- animation = Animation.ANIMATION_WALK;
- if (Input.IsKeyDown(Input.Keys.Shift))
- {
- speed = ((float)game.DeltaTime) * 0.5f;
- animation = Animation.ANIMATION_RUNNING;
- }
- var vec = RigidBody.CalculateForwardVector(-speed);
- linearVelocity.X = vec.X;
- linearVelocity.Z = vec.Z;
- }
- else if (Input.IsKeyDown(Input.Keys.S))
- {
- var vec = RigidBody.CalculateForwardVector(speed);
- linearVelocity.X = vec.X;
- linearVelocity.Z = vec.Z;
- animation = Animation.ANIMATION_WALK;
- }
- // Straving
- if(Input.IsKeyDown(Input.Keys.A))
- {
- var vec = RigidBody.CalculateRightVector(speed);
- linearVelocity.X = vec.X;
- linearVelocity.Z = vec.Z;
- animation = Animation.ANIMATION_STRAFE_LEFT;
- }
- else if(Input.IsKeyDown(Input.Keys.D))
- {
- var vec = RigidBody.CalculateRightVector(-speed);
- linearVelocity.X = vec.X;
- linearVelocity.Z = vec.Z;
- animation = Animation.ANIMATION_STRAFE_RIGHT;
- }
- // Jumping
- if (Input.IsKeyDown(Input.Keys.Space) && this.CanJump())
- {
- linearVelocity.Y += 10f;
- animation = Animation.ANIMATION_JUMPING;
- lastJump = Utils.GetCurrentTimeMillis();
- }
- // Turning the model
- if (Input.IsKeyDown(Input.Keys.Q))
- {
- angularVelocity += 0.5f;
- }
- else if (Input.IsKeyDown(Input.Keys.E))
- {
- angularVelocity -= 0.5f;
- }
- // Setup the velocity for the behavior
- RigidBody.LinearVelocity(linearVelocity);
- RigidBody.AngularVelocity(0f, angularVelocity, 0f);
- // Animation
- switch (animation)
- {
- case Animation.ANIMATION_IDLE:
- this.PlayAnimation(this.IdleAnimation, model);
- break;
- case Animation.ANIMATION_WALK:
- this.PlayAnimation(this.WalkAnimation, model);
- break;
- case Animation.ANIMATION_RUNNING:
- this.PlayAnimation(this.RunningAnimation, model);
- break;
- case Animation.ANIMATION_JUMPING:
- this.PlayAnimation(this.JumpingAnimation, model);
- break;
- case Animation.ANIMATION_STRAFE_RIGHT:
- this.PlayAnimation(this.StrafeRightAnimation, model);
- break;
- case Animation.ANIMATION_STRAFE_LEFT:
- this.PlayAnimation(this.StrafeLeftAnimation, model);
- break;
- default:
- this.PlayAnimation(this.IdleAnimation, model);
- break;
- }
- // Setup the camera
- var camera = game.SelectedScene.Camera;
- var fwd = RigidBody.CalculateForwardVector(1.5f);
- camera.Location = RigidBody.GetLocation() + fwd;
- camera.Location.Y += 0.75f;
- Utils.LookAt(camera, RigidBody.GetLocation());
- }
- private void PlayAnimation(String animation, Model model)
- {
- if (model.Animator.CurrentAnimation.Name != animation)
- {
- model.PlayAnimation(animation);
- }
- }
- private bool CanJump()
- {
- var now = Utils.GetCurrentTimeMillis();
- if(now > lastJump + 500)
- {
- return true;
- }
- return false;
- }
- }
- }