Home

Awesome

SRMove

license WebGL Demo

SRMove is a rigidbody character movement solution that uses efficient slope approximation to move smoothly on stairs and obstacles.

This project aims to recreate the low-level character movement logic used in Genshin Impact and Honkai: Star Rail.

<img src="https://github.com/NoiRC256/SRMove/assets/33998067/33ac7870-36e6-4c35-9390-4bbd4c5b6832" alt="SRMove-Side-By-Side-Example" width="320">

In Genshin Impact, even though character IK is disabled while the character is moving, the character is still able to travel smoothly on stairs that have unmodified mesh colliders. This may partially be the result of some slope approximation system, which allows character movement logic to consider stairs as angled ground for the purpose of aligning movement velocity with ground surface.

WebGL Demo

Key Features

:heavy_check_mark: Ground detection - Ground contact information is provided each physics frame. Performs ground detection with configurable parameters, using spherecast to support ledge perching

:heavy_check_mark: Slope traversal with ground snapping - Snap to ground surface while moving. Correctly handles velocity on angled surfaces

:heavy_check_mark: Smooth stair traversal - Smoothly move up and down on steps and stairs. Produces reliable smoothing behaviour when combined with slope approximation

:heavy_check_mark: Velocity physics - Optional built-in accleration and deceleration.

:heavy_check_mark: Supports moving surfaces - Correctly handles velocity on moving platforms

:heavy_check_mark: Intuitive collider adjustment - Configure collider height or step height while keeping collider bottom or top fixed

Environment

Developed and tested in Unity 2022.3.4f1

Quick Start

CharacterMover is an equivalent of Unity's CharacterContoller.

A simple example:

using UnityEngine;
using NekoLab.SRMove;

// Example third-person movement controller.
public class MyMovementController : MonoBehaviour
{
    [SerializeField] private MyInputSource _inputSource; // Example input source.
    [SerializeField] private CharacterMover _characterMover;
    [SerializeField] private Transform _cameraTr; // Reference transform used to determine movement direction.
    [SerializeField] private float _speed = 3f;

    private void FixedUpdate()
    {
        if (!_inputSource.HasMoveInput())
        {
            _characterMover.Move(Vector3.zero);
            return;
        }

        // Calculate the direction you want to move along.
        Vector3 moveDirection = GetMoveDirection(_input.GetMoveInput(), _cameraTr);

        // Move.
        _characterMover.Move(_speed * moveDirection);
    }

    // Convert 2D input vector to 3D worldspace direction relative to the reference transform.
    private Vector3 GetMoveDirection(Vector2 input, Transform directionReference)
    {
         Vector3 direction = (input.x * Vector3.ProjectOnPlane(directionReference.right, Vector3.up)).normalized;
         direction += (input.y * Vector3.ProjectOnPlane(directionReference.forward, Vector3.up)).normalized;
         return direction.normalized;
    }
}

Usage

Movement Methods

CharacterMover provides several methods for movement.

1. Move

This is the easiest way to get moving. Call Move every fixed update to set the intended movement velocity.

Move(Vector3 velocity);
Move(float speed, Vector3 direction);

2. Active Velocity

activeVelocity is an internal velocity field that CharacterMover uses to set Rigidbody velocity at the end of each fixed update. When the Velocity Mode inspector field is set to a mode that uses velocity physics (i.e. acceleration, deceleration, friction), activeVelocity will persist across fixed updates and gradually change based on the configured velocity physics logic.

To ignore any applicable velocity physics and directly set CharacerMover velocity, you can set activeVelocity by:

SetActiveVelocity(Vector3 velocity);

You can clear the activeVelocity by:

ClearActiveVelocity();

3. Delta Position

Directly sets the intended position change for the current fixed update.

This can be used to drive CharacterMover by animation root motion.

MoveDeltaPosition(Vector3 deltaPosition, bool alignToGround, bool restrictToGround)

Velocity Physics Modes

Use the Velocity Mode inspector field on a CharacerMover to configure velocity physics behaviour.