# Table of Contents
- [Easy Character Movement 2](#easy-character-movement-2)
- [Components | Easy Character Movement 2](#components-easy-character-movement-2)
- [General | Easy Character Movement 2](#general-easy-character-movement-2)
- [Animating a Character | Easy Character Movement 2](#animating-a-character-easy-character-movement-2)
- [Controlling a Character | Easy Character Movement 2](#controlling-a-character-easy-character-movement-2)
- [Collision Detection and Events | Easy Character Movement 2](#collision-detection-and-events-easy-character-movement-2)
- [Extending a Character | Easy Character Movement 2](#extending-a-character-easy-character-movement-2)
- [Moving Platforms | Easy Character Movement 2](#moving-platforms-easy-character-movement-2)
- [AI Navigation | Easy Character Movement 2](#ai-navigation-easy-character-movement-2)
- [Physics | Easy Character Movement 2](#physics-easy-character-movement-2)
- [Cinemachine | Easy Character Movement 2](#cinemachine-easy-character-movement-2)
- [Getting Started | Easy Character Movement 2](#getting-started-easy-character-movement-2)
- [Change Log | Easy Character Movement 2](#change-log-easy-character-movement-2)
- [Package Contents | Easy Character Movement 2](#package-contents-easy-character-movement-2)
- [Examples | Easy Character Movement 2](#examples-easy-character-movement-2)
- [Creating a Character | Easy Character Movement 2](#creating-a-character-easy-character-movement-2)
- [Customer Support | Easy Character Movement 2](#customer-support-easy-character-movement-2)
- [NavMesh Character | Easy Character Movement 2](#navmesh-character-easy-character-movement-2)
- [Physics Volume | Easy Character Movement 2](#physics-volume-easy-character-movement-2)
- [Root Motion Controller | Easy Character Movement 2](#root-motion-controller-easy-character-movement-2)
- [Slope Limit Behaviour | Easy Character Movement 2](#slope-limit-behaviour-easy-character-movement-2)
- [Character Movement | Easy Character Movement 2](#character-movement-easy-character-movement-2)
- [Character | Easy Character Movement 2](#character-easy-character-movement-2)
- [General | Easy Character Movement 2](#general-easy-character-movement-2)
- [Creating a Character | Easy Character Movement 2](#creating-a-character-easy-character-movement-2)
- [Customer Support | Easy Character Movement 2](#customer-support-easy-character-movement-2)
---
# Easy Character Movement 2
[Easy Character Movement 2](https://oscar-gracian.gitbook.io/easy-character-movement-2)
(ECM2 for short) is a powerful, versatile, and easy-to-customize kinematic character controller designed for any character – be it player-controlled or AI – and compatible with a variety of game genres such as platformer, first person, third person, adventure, and more!
[NextGeneralchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general)
Last updated 1 year ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---
# Components | Easy Character Movement 2
These are the core components included in ECM2:
* [Character](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character)
The `Character` is built on top of the `CharacterMovement` component and serves as a base for all your game avatars, whether they are player-controlled or AI-controlled.
* [NavMesh Character](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character)
The `NavMeshCharacter` component extends a `Character` through composition, providing additional navigation capabilities based on a `NavMesh`.
* [Character Movement](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement)
The `CharacterMovement` component is a robust and feature-rich fully kinematic character controller, also known as a motor.
* [Slope Limit Behaviour](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour)
The `SlopeLimitBehaviour` component overrides the `CharacterMovement slopeLimit` property, enabling the definition of per-object walk-ability behavior instead of per-face.
* [Physics Volume](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/physics-volume)
The `PhysicsVolume` component allows you to define physics volumes (trigger areas) such as water, air, oil, etc. Characters will react according to these settings when inside this volume.
* [Root Motion Controller](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/root-motion-controller)
The `RootMotionController` is a helper component designed to retrieve the `Animator`'s root motion velocity vector, denoted as `animRootMotionVelocity`. When root motion is enabled, this provides the animation velocity to the associated `Character` class.
[PreviousChange Logchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log)
[NextCharacterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character)
Last updated 2 years ago
---
# General | Easy Character Movement 2
**Easy Character Movement 2 (ECM2)** is a comprehensive set of components designed to facilitate smooth character movement in both 3D and 2D (specifically 2.5D, as it remains 3D based) environments.
The primary objective of ECM2 is to simplify the process of maneuvering game characters, empowering developers to construct game mechanics effortlessly on this foundation.
At the core of ECM2 is the **CharacterMovement** component, a robust and feature-rich fully kinematic character controller (aka motor). This component serves as a direct replacement for Unity's built-in character controller, employing a similar operational methodology (i.e. `Move` method) but with many features and advantages over it.
The cornerstone of the ECM2 system is the `Character` class. This class utilizes the `CharacterMovement` component as its character controller / motor, incorporating common modes of movement for characters, such as walking, falling, flying, swimming or any custom mode you may create. It serves as a highly customizable foundation for all your game avatars, whether they are controlled by players or AI.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general#features)
Features
----------------------------------------------------------------------------------------------------------------
* `CharacterMovement` a **AAA Kinematic Character Controller** .
* **Robust Ground Detection:**
* Achieve realistic surface interaction with a robust ground detection system based on real surface normals.
* **Slope Limit Override:**
* Define walk-able areas on a per-face or per-object basis, ensuring precise control over character movement.
* **Configurable Walk-able Area:**
* Customize the character's 'feet' radius with the `perchOffset` feature, enhancing configurability.
* **Capsule-Based with Flat Base:**
* Opt for a capsule-based design with a Flat Base for ground checks to prevent characters from slowly sliding off ledges.
* **Ground Constraint:**
* Safeguard characters from being launched off ramps with a ground constraint feature.
* **Configurable Plane Constraint:**
* Control movement along locked axes with the Configurable Plane Constraint, enhancing directional precision.
* **Auto-Stepping with Momentum Preservation:**
* Enable auto-stepping that seamlessly preserves the character's momentum, including stride effects.
* **Gravity and Up Vector Customization:**
* Achieve Mario Galaxy-like effects with user-defined gravity and up vector options.
* **Physics Interactions:**
* Experience realistic physics interactions for immersive character movements.
* **Character vs Character Interactions:**
* Engage in dynamic character vs character interactions within the virtual environment.
* **Transparent Platform Support:**
* Enjoy first-class, transparent platform support for animated, scripted, or physics-based platforms without additional steps.
* **Collision and Grounding Events:**
* Receive comprehensive collision and grounding events for enhanced control and feedback.
* **Network-Friendly Design:**
* Retain full control over update and simulation time-step, ensuring network-friendly performance.
* **Friction-Based Movement Options:**
* Configure friction-based movement, including water buoyancy, for diverse environmental interactions.
* **Root Motion Support:**
* Incorporate root motion support for enhanced character animations and realism.
* **Designed for Extensibility:**
* Developed with extensibility in mind, allowing for use as-is, or complete extension through **inheritance** or **composition**.
* **Easy Integration into Existing Projects:**
* Seamlessly integrate into existing Unity projects with minimal effort.
* **Well-Commented Source Code:**
* Access fully commented C# source code for clarity, readability, and ease of extension.
* **Garbage-Collector Friendly:**
* Optimize performance with a software design that minimizes garbage collector allocations for a smoother experience.
[PreviousEasy Character Movement 2chevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2)
[NextPackage Contentschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents)
Last updated 2 years ago
---
# Animating a Character | Easy Character Movement 2
When animating a character, you should query the character's state and/or subscribe to its numerous events, feeding this information to your `AnimationController` parameters to ensure your animation stays perfectly in sync with the character's state, such as whether it is grounded, falling, jumping, etc.
> ECM2 does not require the use of animation or any specific animation techniques. You have the freedom to animate your characters using 'plain Unity code' or your preferred method.
In this example, we will animate the included **UnityCharacter** model, syncing its animator with the information provided by the `Character` class.
Copy
///
/// This example shows how to animate a Character,
/// using the Character data (movement direction, velocity, is jumping, etc) to feed your Animator.
///
public class AnimationController : MonoBehaviour
{
// Cache Animator parameters
private static readonly int Forward = Animator.StringToHash("Forward");
private static readonly int Turn = Animator.StringToHash("Turn");
private static readonly int Ground = Animator.StringToHash("OnGround");
private static readonly int Crouch = Animator.StringToHash("Crouch");
private static readonly int Jump = Animator.StringToHash("Jump");
private static readonly int JumpLeg = Animator.StringToHash("JumpLeg");
// Cached Character
private Character _character;
private void Awake()
{
// Cache our Character
_character = GetComponentInParent();
}
private void Update()
{
float deltaTime = Time.deltaTime;
// Get Character animator
Animator animator = _character.GetAnimator();
// Compute input move vector in local space
Vector3 move = transform.InverseTransformDirection(_character.GetMovementDirection());
// Update the animator parameters
float forwardAmount = _character.useRootMotion && _character.GetRootMotionController()
? move.z
: Mathf.InverseLerp(0.0f, _character.GetMaxSpeed(), _character.GetSpeed());
animator.SetFloat(Forward, forwardAmount, 0.1f, deltaTime);
animator.SetFloat(Turn, Mathf.Atan2(move.x, move.z), 0.1f, deltaTime);
animator.SetBool(Ground, _character.IsGrounded());
animator.SetBool(Crouch, _character.IsCrouched());
if (_character.IsFalling())
animator.SetFloat(Jump, _character.GetVelocity().y, 0.1f, deltaTime);
// Calculate which leg is behind, so as to leave that leg trailing in the jump animation
// (This code is reliant on the specific run cycle offset in our animations,
// and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)
float runCycle = Mathf.Repeat(animator.GetCurrentAnimatorStateInfo(0).normalizedTime + 0.2f, 1.0f);
float jumpLeg = (runCycle < 0.5f ? 1.0f : -1.0f) * forwardAmount;
if (_character.IsGrounded())
animator.SetFloat(JumpLeg, jumpLeg);
}
}
As you can observe, this is standard Unity code that leverages the character's state information to control our animator.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character#root-motion)
Root Motion
------------------------------------------------------------------------------------------------------------------------------------
The `Character` class, includes built-in support for root motion.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character#utilizing-root-motion)
Utilizing Root Motion
--------------------------------------------------------------------------------------------------------------------------------------------------------
To enable root motion, follow these steps:
1. Add the `RootMotionController` component to your model's `GameObject`. This `RootMotionController` is responsible for providing the animation's velocity, rotation, etc., to the `Character`.
2. Enable the `useRootMotion` property in the `Character`. This property can be toggled as needed.
Once a character is moved using root motion, the animation assumes complete control over the character's movement. This replaces all procedural movement, rendering properties such as `maxWalkSpeed`, `maxFallSpeed`, etc., irrelevant, as the character is entirely driven by the animation.
Worth noting, the character's ground constraint still applies when root motion is enabled. This implies that any vertical movement in your root motion-based animation won't function unless you explicitly disable this constraint. In such cases, it's advisable to assign the **Flying** movement mode, as it automatically disables the ground constraint and allows for vertical movement.
circle-exclamation
To enable vertical root motion movement, the character's movement mode must be set to **Flying**.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character#toggling-root-motion)
Toggling Root Motion
------------------------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to toggle root motion at run-time. In this case, enabling root motion only while the character is in the **Walking** movement mode.
Copy
public class RootMotionToggle : MonoBehaviour
{
private Character _character;
private void OnMovementModeChanged(Character.MovementMode prevMovementMode, int prevCustomMovementMode)
{
// Allow root motion only while walking
_character.useRootMotion = _character.IsWalking();
}
private void Awake()
{
_character = GetComponent();
}
private void OnEnable()
{
// Subscribe to Character events
_character.MovementModeChanged += OnMovementModeChanged;
}
private void OnDisable()
{
// Un-Subscribe from Character events
_character.MovementModeChanged -= OnMovementModeChanged;
}
}
In this example, we utilize the `MovementModeChange` event, which is triggered each time the character changes its current movement mode, making it perfect this case.
[PreviousControlling a Characterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character)
[NextExtending a Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character)
Last updated 2 years ago
---
# Controlling a Character | Easy Character Movement 2
A `Character` encompasses a collection of methods designed to facilitate action execution. For instance, the `SetMovementDirection` method prompts the character to move in a specified direction (in world space).
Similarly, the `Jump` method initiates a jump, while the `StopJumping` method halts the ongoing jump—particularly crucial when a variable jump height is in use.
Likewise, the `Crouch` method is utilized to initiate the character's crouching action, and the `UnCrouch` method is employed to cease the crouching state.
These actions can be managed using a custom character class through inheritance, through an external script or visual scripting solution, as preferred.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character#custom-character)
Custom Character
------------------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to control a player derived from the `Character` class:
Copy
///
/// This example shows how to extend a Character (through inheritance)
/// adding input management.
///
public class PlayerCharacter : Character
{
private void Update()
{
// Movement input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// If character has a camera assigned...
if (camera)
{
// Make movement direction relative to its camera view direction
movementDirection = movementDirection.relativeTo(cameraTransform);
}
SetMovementDirection(movementDirection);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
Jump();
else if (Input.GetButtonUp("Jump"))
StopJumping();
}
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character#controlling-a-character)
Controlling a Character
--------------------------------------------------------------------------------------------------------------------------------------------------------------
The following example illustrates how to control a character from an external 'entity,' specifically the `CharacterInput` script:
Copy
using UnityEngine;
using ECM2;
public class CharacterInput : MonoBehaviour
{
// The controlled Character
private Character _character;
private void Awake()
{
// Cache controlled character
_character = GetComponent();
}
private void Update()
{
// Poll movement input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// Compose a movement direction vector in world space
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// If character has a camera assigned,
// make movement direction relative to this camera view direction
if (_character.camera)
{
movementDirection
= movementDirection.relativeTo(_character.cameraTransform);
}
// Set character's movement direction vector
_character.SetMovementDirection(movementDirection);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
_character.Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
_character.UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
_character.Jump();
else if (Input.GetButtonUp("Jump"))
_character.StopJumping();
}
}
Finally, add the newly created `CharacterInput` script to your **Character** GameObject. You should be able to **move**, **jump** and **crouch**!
circle-exclamation
**Crouching** and **Uncrouching** solely manipulate the character's capsule collider, without influencing the visual representation of your character.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character#using-input-system)
Using Input System
----------------------------------------------------------------------------------------------------------------------------------------------------
The following example shows how to control a character using the [`InputSystem`arrow-up-right](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/index.html)
. In this case, we'll utilize the [`PlayerInput`arrow-up-right](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/PlayerInput.html)
component, which streamlines the setup and management of input controls.
The `PlayerInput` component efficiently handles input actions, taking care of initialization, de-initialization, input processing, event triggering, and more. Consequently, our main task involves simply creating event handlers for our actions, a process reminiscent of the old input manager.
Copy
using ECM2;
using UnityEngine;
using UnityEngine.InputSystem;
public class CharacterInput : MonoBehaviour
{
// Cached controlled character
private Character _character;
///
/// Movement InputAction event handler.
///
public void OnMove(InputAction.CallbackContext context)
{
// Read input values
Vector2 inputMovement = context.ReadValue();
// Compose a movement direction vector in world space
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.forward * inputMovement.y;
movementDirection += Vector3.right * inputMovement.x;
// If character has a camera assigned,
// make movement direction relative to this camera view direction
if (_character.camera)
{
movementDirection
= movementDirection.relativeTo(_character.cameraTransform);
}
// Set character's movement direction vector
_character.SetMovementDirection(movementDirection);
}
///
/// Jump InputAction event handler.
///
public void OnJump(InputAction.CallbackContext context)
{
if (context.started)
_character.Jump();
else if (context.canceled)
_character.StopJumping();
}
///
/// Crouch InputAction event handler.
///
public void OnCrouch(InputAction.CallbackContext context)
{
if (context.started)
_character.Crouch();
else if (context.canceled)
_character.UnCrouch();
}
private void Awake()
{
//
// Cache controlled character.
_character = GetComponent();
}
}
As you can see, the operation of the character closely resembles that of the old input manager (or any other input package), where we rely on the character's action methods to control it.
circle-info
Please refer to the [`PlayerInput`arrow-up-right](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/PlayerInput.html)
component documentation for more detailed information.
[PreviousCreating a Characterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/creating-a-character)
[NextAnimating a Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character)
Last updated 1 year ago
---
# Collision Detection and Events | Easy Character Movement 2
The `Character` class includes numerous events that allow you to manage different character interactions. For instance, there is `OnCollided`, which is triggered when the character makes contact with a collider while executing a `Move`, `OnFoundGround`, which is triggered when a character detects any ground surface (whether **walkable** or **not-walkable**), among others.
When extending a `Character` class, it is advisable to override its corresponding event trigger method. For example, override the `OnCollided` method to handle a collision:
Copy
public class PlayerCharacter : Character
{
protected override void OnCollided(ref CollisionResult collisionResult)
{
// Call base method implementation
base.OnCollided(ref collisionResult);
// Add your code here...
Debug.Log($"Collided with {collisionResult.collider.name}");
}
}
On the other hand, when extending a `Character` through composition, it's advisable to listen to its exposed events. For example, subscribe to its `Collided` event to handle a collision:
Copy
public class PlayerController : MonoBehaviour
{
// The controlled Character
private Character _character;
protected void OnCollided(ref CollisionResult collisionResult)
{
Debug.Log($"Collided with {collisionResult.collider.name}");
}
private void OnEnable()
{
// Subscribe to Character events
_character.Collided += OnCollided;
}
private void OnDisable()
{
// Un-subscribe from Character events
_character.Collided -= OnCollided;
}
}
The procedure is the same for its other events.
[PreviousExtending a Characterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character)
[NextPhysicschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/physics)
Last updated 2 years ago
---
# Extending a Character | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character#custom-character-inheritance)
Custom Character (Inheritance)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
One of the notable features of the `Character` class is its role as a highly robust foundation for all your game avatars. It enables users to expand its functionality by adding specific features and mechanics tailored to the requirements of their game.
In this example, we will demonstrate how to extend a `Character` using inheritance. In this particular case, we will add a **Sprint** ability.
One of the advantages of inheritance over composition is the ability to extend methods from the base class, allowing us to modify them to suit our purpose. In particular, we will use the `GetMaxSpeed` method. As the name suggests, this method returns the maximum speed at which the character can move, depending on its state or movement mode, making it perfect for **Sprint**.
Furthermore, we will leverage a newly introduced method in version 1.4, namely `OnBeforeSimulationUpdate`. This method simplifies the process of modifying the character's state within the character's simulation loop, enhancing the overall flexibility and control over the character controller's functionality.
Firstly, we create our custom character named `SprintableCharacter`:
Copy
public class SprintableCharacter : Character
{
// TODO
}
When extending a `Character`, it is advisable to adhere to the established conventions of the `Character` class by creating a set of methods to control the execution of newly added abilities. Ensure these methods follow the pattern of the character's built-in functions, such as `Jump`, `StopJumping`, `Crouch`, `UnCrouch`, and so forth. In this specific scenario, these methods are designed to manage the **Sprint** ability.
For example:
Copy
public class SprintableCharacter : Character
{
[Space(15.0f)]
public float maxSprintSpeed = 10.0f;
private bool _isSprinting;
private bool _sprintInputPressed;
public void Sprint()
{
_sprintInputPressed = true;
}
public void StopSprinting()
{
_sprintInputPressed = false;
}
public bool IsSprinting()
{
return _isSprinting;
}
private bool CanSprint()
{
// A character can only sprint if:
// A character is in its walking movement mode and not crouched
return IsWalking() && !IsCrouched();
}
private void CheckSprintInput()
{
if (!_isSprinting && _sprintInputPressed && CanSprint())
{
_isSprinting = true;
}
else if (_isSprinting && (!_sprintInputPressed || !CanSprint()))
{
_isSprinting = false;
}
}
}
The `SprintableCharacter` class serves as an illustration of this methodology. The variable `maxSprintSpeed` defines the character's top speed during sprinting, while the `_isSprinting` variable indicates the character's ongoing state. Moreover, the `_sprintInputPressed` variable oversees the activation of the ability, commonly triggered by input events such as key-down or key-up actions.
The `CheckSprintInput` method adheres to the previously mentioned pattern. Action execution methods, like `Sprint` and `StopSprinting`, prompt the character to carry out a specific action. This request undergoes processing in the `CheckSprintInput` method, where the `CanSprint` method determines whether the character is capable of initiating or should cease sprinting.
circle-info
While not obligatory, it is advisable to embrace a comparable approach when extending a `Character`. This methodology is actively utilized by the `Character` class to implement its inherent **jump** and crouch functionalities.
The final step involves modifying the character's maximum speed while sprinting. To achieve this, we extend the character's `GetMaxSpeed` method. This extension enables us to return `maxSprintSpeed` when the character is in a sprinting state.
Copy
public override float GetMaxSpeed()
{
return _isSprinting ? maxSprintSpeed : base.GetMaxSpeed();
}
Finally, we will expand upon the previously mentioned `OnBeforeSimulationUpdate` method to incorporate the management of our sprint ability.
Copy
protected override void OnBeforeSimulationUpdate(float deltaTime)
{
// Call base method implementation
base.OnBeforeSimulationUpdate(deltaTime);
// Handle sprint
CheckSprintInput();
}
To initiate sprinting, we utilize the `Sprint` method, while the `StopSprinting` method is employed to conclude a sprint in response to input events:
Copy
private void Update()
{
..
if (Input.GetKeyDown(KeyCode.LeftShift))
Sprint();
else if (Input.GetKeyUp(KeyCode.LeftShift))
StopSprinting();
}
Here is the entire script:
Copy
///
/// This example shows how to extend a Character (through inheritance) to perform a sprint ability.
/// This uses one of the new methods (introduced in v1.4) OnBeforeSimulationUpdate,
/// to easily modify the character's state within Character's simulation loop.
///
public class SprintableCharacter : Character
{
[Space(15.0f)]
public float maxSprintSpeed = 10.0f;
private bool _isSprinting;
private bool _sprintInputPressed;
///
/// Request the character to start to sprint.
///
public void Sprint()
{
_sprintInputPressed = true;
}
///
/// Request the character to stop sprinting.
///
public void StopSprinting()
{
_sprintInputPressed = false;
}
public bool IsSprinting()
{
return _isSprinting;
}
///
/// Determines if the character is able to sprint in its current state.
///
private bool CanSprint()
{
// A character can only sprint if:
// A character is in its walking movement mode and not crouched
return IsWalking() && !IsCrouched();
}
///
/// Start / stops a requested sprint.
///
private void CheckSprintInput()
{
if (!_isSprinting && _sprintInputPressed && CanSprint())
{
_isSprinting = true;
}
else if (_isSprinting && (!_sprintInputPressed || !CanSprint()))
{
_isSprinting = false;
}
}
///
/// Override GetMaxSpeed method to return maxSprintSpeed while sprinting.
///
public override float GetMaxSpeed()
{
return _isSprinting ? maxSprintSpeed : base.GetMaxSpeed();
}
protected override void OnBeforeSimulationUpdate(float deltaTime)
{
// Call base method implementation
base.OnBeforeSimulationUpdate(deltaTime);
// Handle sprint
CheckSprintInput();
}
private void Update()
{
// Movement input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// If character has a camera assigned...
if (camera)
{
// Make movement direction relative to its camera view direction
movementDirection = movementDirection.relativeTo(cameraTransform);
}
SetMovementDirection(movementDirection);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
Jump();
else if (Input.GetButtonUp("Jump"))
StopJumping();
// SPRINT input
if (Input.GetKeyDown(KeyCode.LeftShift))
Sprint();
else if (Input.GetKeyUp(KeyCode.LeftShift))
StopSprinting();
}
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character#character-extension-composition)
Character Extension (Composition)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
In the previous section, we illustrated the process of extending a `Character` through inheritance. Now, we will replicate the same example of adding sprint functionality to a character. However, unlike the previous approach, we will utilize composition.
Composition, in object-oriented programming, involves constructing a class using instances of other classes to achieve the desired functionality. It's worth noting that composition offers certain advantages over inheritance. With composition, components can be dynamically combined to create more flexible and modular designs. This contrasts with the more rigid structure of inheritance, allowing for easier modification and extension of code.
In essence, composition enables the building of complex structures by assembling simpler, independent parts. This approach often leads to more maintainable and scalable code, fostering a design that prioritizes flexibility and reusability.
To achieve this, we'll make use of the recently introduced 'hooks' (events) in version 1.4.0. These hooks empower us to influence the character's state without the need for inheritance from the `Character` base class. In particular, the `BeforeSimulationUpdated` event essentially serves the same purpose as the previously utilized `OnBeforeSimulationUpdate` method.
Copy
///
/// Event called before character simulation updates.
/// This 'hook' lets you externally update the character 'state'.
///
public event BeforeSimulationUpdateEventHandler BeforeSimulationUpdated;
In essence, the code remains quite similar with some minor modifications. Specifically, the `CheckSprintInput` method now directly modifies the Character's `maxWalkSpeed` property. This adjustment is necessary because, unlike the previous approach (inheritance), extending the `GetMaxSpeed` method is not feasible in this context.
Below is the complete script:
Copy
///
/// This example shows how to extend a Character (through composition) to perform a sprint ability.
/// This one use the new simulation OnBeforeSimulationUpdate event (introduced in v1.4),
/// to easily modify the character's state within Character's simulation loop.
///
public class SprintAbility : MonoBehaviour
{
[Space(15.0f)]
public float maxSprintSpeed = 10.0f;
private Character _character;
private bool _isSprinting;
private bool _sprintInputPressed;
private float _cachedMaxWalkSpeed;
///
/// Request the character to start to sprint.
///
public void Sprint()
{
_sprintInputPressed = true;
}
///
/// Request the character to stop sprinting.
///
public void StopSprinting()
{
_sprintInputPressed = false;
}
public bool IsSprinting()
{
return _isSprinting;
}
private bool CanSprint()
{
return _character.IsWalking() && !_character.IsCrouched();
}
private void CheckSprintInput()
{
if (!_isSprinting && _sprintInputPressed && CanSprint())
{
_isSprinting = true;
_cachedMaxWalkSpeed = _character.maxWalkSpeed;
_character.maxWalkSpeed = maxSprintSpeed;
}
else if (_isSprinting && (!_sprintInputPressed || !CanSprint()))
{
_isSprinting = false;
_character.maxWalkSpeed = _cachedMaxWalkSpeed;
}
}
private void OnBeforeSimulationUpdated(float deltaTime)
{
// Handle sprinting
CheckSprintInput();
}
private void Awake()
{
// Cache character
_character = GetComponent();
}
private void OnEnable()
{
// Subscribe to Character BeforeSimulationUpdated event
_character.BeforeSimulationUpdated += OnBeforeSimulationUpdated;
}
private void OnDisable()
{
// Un-Subscribe from Character BeforeSimulationUpdated event
_character.BeforeSimulationUpdated -= OnBeforeSimulationUpdated;
}
}
Finally, we will employ the `Sprint` and `StopSprinting` methods to commence or halt sprinting in response to input events.
Copy
private SprintAbility _sprintAbility;
private void Update()
{
..
if (Input.GetKeyDown(KeyCode.LeftShift))
_sprintAbility.Sprint();
else if (Input.GetKeyUp(KeyCode.LeftShift))
_sprintAbility.StopSprinting();
}
As you can observe, the process is quite similar to what we've seen before, with the distinction that now it's the `SprintAbility` responsible for initiating or stopping the sprint.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character#creating-a-custom-movement-mode)
Creating a Custom Movement Mode
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The `Character` class incorporates various movement modes and allows for the creation of custom modes. Before creating a new movement mode, it is recommended to attempt implementing your desired mechanics on one of the available movement modes. For instance, the jump ability is built upon the falling movement mode, while the crouch mechanic is built upon the walking movement mode.
This approach is employed to leverage and extend the functionality of existing code, making it easier to maintain and expand. By using a base movement mode and adding or modifying specific mechanics, a more modular and flexible system is created.
For example, if you already have a walking movement mode, implementing the crouch mechanic on top of it allows you to reuse the walking logic while only adding the necessary adjustments for crouching.
Similarly, building the jump ability on top of the falling movement mode allows you to reuse the falling logic while introducing specific rules for initiating and controlling jumps. This modular approach not only streamlines development but also ensures consistent and predictable behavior across different movement modes.
To create a new movement mode, you first define an ID for it. For instance:
Copy
public enum ECustomMovementMode
{
None,
Dashing,
Climbing
}
This identifier will be used to establish the new movement mode using the `SetMovementMode` method:
Copy
SetMovementMode(MovementMode.Custom, (int)ECustomMovementMode.Dashing);
In this example, you've created an enumeration called `ECustomMovementMode`, which includes values for different movement modes like `None`, `Dashing`, `Climbing`, etc. This enumeration helps you easily identify and switch between various movement modes.
Next, extend the `CustomMovementMode` method. Depending on whether you're developing a derived class from the `Character` class (using inheritance) or subscribing to the `CustomMovementModeUpdated` event (utilizing composition), this is where you'll implement the logic for the new movement mode.
####
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character#using-inheritance)
Using Inheritance:
When inheriting from the `Character` class, it is advisable to extend its `CustomMovementMode` method:
Copy
public class CustomCharacter : Character
{
protected override void CustomMovementMode(float deltaTime)
{
// Call base method implementation
base.CustomMovementMode(deltaTime);
// Update dashing movement mode
if (customMovementMode == (int)ECustomMovementMode.Dashing)
DashingMovementMode(deltaTime);
}
}
####
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/extending-a-character#using-composition)
Using Composition:
On the other hand, when using composition, you should subscribe to its `CustomMovementModeUpdated` event.
Copy
protected void OnEnable()
{
// Subscribe to Character Event
character.CustomMovementModeUpdated += OnCustomMovementModeUpdated;
}
protected void OnDisable()
{
character.CustomMovementModeUpdated += OnCustomMovementModeUpdated;
}
private void OnCustomMovementModeUpdated(float deltaTime)
{
// Update dashing movement mode
if (customMovementMode == (int)ECustomMovementMode.Dashing)
DashingMovementMode(deltaTime);
}
In both cases, customize the logic inside the `CustomMovementMode` method to define how your character behaves in the "**Dashing**," "**Climbing**," or other custom movement modes. This flexibility allows for a tailored and dynamic user experience based on different movement scenarios.
circle-check
To exit a custom movement mode, it is suggested to use the **Walking** or **Falling** movement modes, as they are automatically managed based on the character's grounding status.
Additionally, when configuring 'enter' or 'exit' settings for movement modes, it is advisable to use the `OnMovementModeChanged` method in the case of inheritance, or its corresponding `MovementModeChanged` event when employing composition. These features enable you to execute specific setup actions upon entering or leaving a particular movement mode.
circle-info
Classes derived from `Character` are encouraged to extend the `OnCustomMovementModeUpdated` method instead of subscribing to the event for enhanced customization and seamless integration.
Please refer to the included examples for a complete implementation of custom movement modes.
[PreviousAnimating a Characterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/animating-a-character)
[NextCollision Detection and Eventschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/collision-detection-and-events)
Last updated 2 years ago
---
# Moving Platforms | Easy Character Movement 2
The `CharacterMovement` component can seamlessly handle moving platforms, whether they are dynamic rigidbodies, scripted, or animated, without requiring any additional steps from you. The only condition for the character to stay on the moving platform is that it should be walkable.
For instance, you can jump onto a fully dynamic vehicle, and the character will automatically use it as a moving platform without the need for additional tasks or custom scripts.
Moreover, you have the option to 'parent' the character to a specific moving platform. This way, the character will move with the assigned platform, even if the character is not standing or touching it.
When implementing a scripted dynamic platform, its movement logic should be implemented in the `FixedUpdate` method. This allows the `Character` to be aware of its current state, for example:
Copy
public void FixedUpdate()
{
float t = EaseInOut(Mathf.PingPong(Time.time, _moveTime), _moveTime);
Vector3 p = Vector3.Lerp(_startPosition, _targetPosition, t);
_rigidbody.MovePosition(p);
}
circle-check
If your dynamic platform is animated using an **Animator**, remember to set its **Animator Update Mode to Animate Physics** for proper integration.
Here's an example of how to implement a one-way platform. This example makes use of the `IgnoreCollision` function from the `Character` class to enable or disable collision between the character and the platform as needed.
Copy
public class OneWayPlatform : MonoBehaviour
{
public Collider platformCollider;
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player"))
return;
Character character = other.GetComponent();
if (character)
character.IgnoreCollision(platformCollider);
}
private void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player"))
return;
Character character = other.GetComponent();
if (character)
character.IgnoreCollision(platformCollider, false);
}
}
[PreviousPhysicschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/physics)
[NextAI Navigationchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/ai-navigation)
Last updated 2 years ago
---
# AI Navigation | Easy Character Movement 2
In this example, we make use of the new `NavMeshCharacter` component introduced in version 1.4.0 to implement a typical click-to-move movement.
Copy
public class ClickToMove : MonoBehaviour
{
public Camera mainCamera;
public Character character;
public LayerMask groundMask;
private NavMeshCharacter _navMeshCharacter;
private void Awake()
{
_navMeshCharacter = character.GetComponent();
}
private void Update()
{
if (Input.GetMouseButton(0))
{
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hitResult, Mathf.Infinity, groundMask))
_navMeshCharacter.MoveToDestination(hitResult.point);
}
}
}
This utilizes the `NavMeshCharacter` to instruct the character to move to the world position where the player clicked. Internally, this uses a `NavMeshAgent` to intelligently traverse the world.
[PreviousMoving Platformschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/moving-platforms)
[NextCinemachinechevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/cinemachine)
Last updated 2 years ago
---
# Physics | Easy Character Movement 2
While functioning as a kinematic character controller, the `CharacterMovement` component, also known as the motor, can seamlessly perform physics interactions, including pushing rigid bodies or other characters, responding to external forces, and handling dynamic platforms.
The following example demonstrates how to utilize the `Character` `LaunchCharacter` function to implement a bouncer.
Copy
public class Bouncer : MonoBehaviour
{
public float launchImpulse = 15.0f;
public bool overrideVerticalVelocity;
public bool overrideLateralVelocity;
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player"))
return;
if (!other.TryGetComponent(out Character character))
return;
character.PauseGroundConstraint();
character.LaunchCharacter(transform.up * launchImpulse, overrideVerticalVelocity, overrideLateralVelocity);
}
}
It's important to note the use of `PauseGroundConstraint`. This temporarily disables the character's ground constraint, allowing the character to freely leave **walkable** ground.
The following example demonstrates how to extend a `Character` through composition to apply a landing force. This utilizes the `Landed` event.
Copy
public class ApplyLandingForce : MonoBehaviour
{
public float landingForceScale = 1.0f;
private Character _character;
private void Awake()
{
_character = GetComponent();
}
private void OnEnable()
{
_character.Landed += OnLanded;
}
private void OnDisable()
{
_character.Landed -= OnLanded;
}
private void OnLanded(Vector3 landingVelocity)
{
Rigidbody groundRigidbody = _character.characterMovement.groundRigidbody;
if (!groundRigidbody)
return;
Vector3 force = _character.GetGravityVector() *
(_character.mass * landingVelocity.magnitude * landingForceScale);
groundRigidbody.AddForceAtPosition(force, _character.position);
}
}
Here, the landing force is calculated as (`characterMass * characterGravity * landingVelocity * landingForceMag`) and is applied along the character's gravity direction.
[PreviousCollision Detection and Eventschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/collision-detection-and-events)
[NextMoving Platformschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/moving-platforms)
Last updated 2 years ago
---
# Cinemachine | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/cinemachine#first-person-controller)
First-Person Controller
--------------------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to implement a first-person controller in Unity using **Cinemachine**. It utilizes the **Cinemachine** **Virtual Camera's 3rd Person Follow** for a comprehensive experience. The script includes configurations for camera settings, mouse sensitivity, and managing player input for movement, rotation, crouching, and jumping.
Furthermore, the example seamlessly integrates events to handle camera transitions during **crouch** and **uncrouch** actions. Overall, it provides a solid foundation for a first-person perspective with **Cinemachine** integration, effectively managing both camera and player interactions.
In this setup, the `Character` will manage the yaw rotation (rotation along the character's up-axis), while the parented '**Camera Target**' `GameObject` will handle the camera's pitch rotation.
Copy
public class FirstPersonController : MonoBehaviour
{
..
///
/// Add input (affecting Yaw).
/// This is applied to the Character's rotation.
///
public void AddControlYawInput(float value)
{
_character.AddYawInput(value);
}
///
/// Add input (affecting Pitch).
/// This is applied to the cameraTarget's local rotation.
///
public void AddControlPitchInput(float value, float minValue = -80.0f, float maxValue = 80.0f)
{
if (value == 0.0f)
return;
_cameraTargetPitch = MathLib.ClampAngle(_cameraTargetPitch + value, minValue, maxValue);
cameraTarget.transform.localRotation = Quaternion.Euler(-_cameraTargetPitch, 0.0f, 0.0f);
}
}
It's important to disable the character's rotation mode since, in this example, we'll handle it ourselves.
Copy
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
// Disable Character's rotation mode, we'll handle it here
_character.SetRotationMode(Character.RotationMode.None);
}
Additionally, we'll use the `Character` `Crouched` and `UnCrouched` events to trigger a crouch/uncrouch animation, relying on **Cinemachine**'s transitions.
Copy
private void OnEnable()
{
// Subscribe to Character events
_character.Crouched += OnCrouched;
_character.UnCrouched += OnUnCrouched;
}
private void OnDisable()
{
// Unsubscribe to Character events
_character.Crouched -= OnCrouched;
_character.UnCrouched -= OnUnCrouched;
}
..
///
/// When character crouches, toggle Crouched / UnCrouched cameras.
///
private void OnCrouched()
{
crouchedCamera.SetActive(true);
unCrouchedCamera.SetActive(false);
}
///
/// When character un-crouches, toggle Crouched / UnCrouched cameras.
///
private void OnUnCrouched()
{
crouchedCamera.SetActive(false);
unCrouchedCamera.SetActive(true);
}
Finally, we handle player input:
Copy
private void Update()
{
// Movement input
Vector2 moveInput = new Vector2
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// Movement direction relative to Character's forward
Vector3 movementDirection = Vector3.zero;
movementDirection += _character.GetRightVector() * moveInput.x;
movementDirection += _character.GetForwardVector() * moveInput.y;
// Set Character movement direction
_character.SetMovementDirection(movementDirection);
// Look input
Vector2 lookInput = new Vector2
{
x = Input.GetAxisRaw("Mouse X"),
y = Input.GetAxisRaw("Mouse Y")
};
// Add yaw input, this update character's yaw rotation
AddControlYawInput(lookInput.x * lookSensitivity.x);
// Add pitch input (look up / look down), this update cameraTarget's local rotation
AddControlPitchInput(lookInput.y * lookSensitivity.y, minPitch, maxPitch);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
_character.Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
_character.UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
_character.Jump();
else if (Input.GetButtonUp("Jump"))
_character.StopJumping();
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/cinemachine#third-person-controller)
Third-Person Controller
--------------------------------------------------------------------------------------------------------------------------------------------------
The following example illustrates the implementation of a third-person controller in Unity using **Cinemachine**. It leverages the **Cinemachine Virtual Camera's 3rd Person Follow** feature for a comprehensive experience. The controller encompasses configurations for camera settings, mouse sensitivity, and the management of player input for movement, rotation, crouching, and jumping.
Initially, we implement methods to control the camera's rotation and adjust its follow distance:
Copy
///
/// Add input (affecting Yaw).
/// This is applied to the followTarget's yaw rotation.
///
public void AddControlYawInput(float value, float minValue = -180.0f, float maxValue = 180.0f)
{
if (value != 0.0f) _cameraTargetYaw = MathLib.ClampAngle(_cameraTargetYaw + value, minValue, maxValue);
}
///
/// Add input (affecting Pitch).
/// This is applied to the followTarget's pitch rotation.
///
public void AddControlPitchInput(float value, float minValue = -80.0f, float maxValue = 80.0f)
{
if (value == 0.0f)
return;
if (invertLook)
value = -value;
_cameraTargetPitch = MathLib.ClampAngle(_cameraTargetPitch + value, minValue, maxValue);
}
///
/// Adds input (affecting follow distance).
///
public virtual void AddControlZoomInput(float value)
{
followDistance = Mathf.Clamp(followDistance - value, followMinDistance, followMaxDistance);
}
Subsequently, we adjust both the rotation of the `followTarget` `GameObject` and the `CameraDistance` of the **Cinemachine** virtual camera. This essentially means that we are exerting control over the **Cinemachine** camera by manipulating the `followTarget` `GameObject`.
Copy
///
/// Update followTarget rotation using _cameraTargetYaw and _cameraTargetPitch values and its follow distance.
///
private void UpdateCamera()
{
followTarget.transform.rotation = Quaternion.Euler(_cameraTargetPitch, _cameraTargetYaw, 0.0f);
_cmThirdPersonFollow.CameraDistance =
Mathf.SmoothDamp(_cmThirdPersonFollow.CameraDistance, followDistance, ref _followDistanceSmoothVelocity, 0.1f);
}
private void LateUpdate()
{
// Update cameraTarget rotation using our yaw and pitch values
UpdateCamera();
}
Finally, we handle player input:
Copy
private void Update()
{
// Movement input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// Set Movement direction in world space
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// If character has a camera assigned...
if (_character.camera)
{
// Make movement direction relative to its camera view direction
movementDirection = movementDirection.relativeTo(_character.cameraTransform);
}
// Set Character movement direction
_character.SetMovementDirection(movementDirection);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
_character.Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
_character.UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
_character.Jump();
else if (Input.GetButtonUp("Jump"))
_character.StopJumping();
// Look input
Vector2 lookInput = new Vector2
{
x = Input.GetAxisRaw("Mouse X"),
y = Input.GetAxisRaw("Mouse Y")
};
AddControlYawInput(lookInput.x * lookSensitivity.x);
AddControlPitchInput(lookInput.y * lookSensitivity.y, minPitch, maxPitch);
// Zoom (in / out) input
float mouseScrollInput = Input.GetAxisRaw("Mouse ScrollWheel");
AddControlZoomInput(mouseScrollInput);
}
[PreviousAI Navigationchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/ai-navigation)
[NextCustomer Supportchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/support/customer-support)
Last updated 8 months ago
---
# Getting Started | Easy Character Movement 2
This document describes the steps for creating and controlling a character.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/getting-started#creating-a-character)
Creating a Character
--------------------------------------------------------------------------------------------------------------------------------------------------------
* Right-click on the hierarchy window to open the creation dialog and select the **Character** option from the **ECM2** category.

* It will create an empty character (no visual representation) named **Character.**

Newly created Character
circle-check
Make sure its origin is set to (0, 0, 0) as this will save you troubles when parenting your model.
* Parent your model to this newly `Character` `GameObject`. For this example, we'll use the included **ECM2\_Capsule** model.

Character's model
* In the `CharacterMovement` component, adjust its **radius** and **height** values (this will automatically configure your character’s capsule collider) to better fit your character’s model.

CharacterMovement component
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/getting-started#controlling-a-character)
Controlling a Character
--------------------------------------------------------------------------------------------------------------------------------------------------------------
In the previous section, we discussed the steps to create and configure our `Character`. However, at this point, we are unable to move or control it. We will address and resolve this creating a new `CharacterInput` script.
A `Character` encompasses a collection of methods designed to facilitate action execution. For instance, its `SetMovementDirection` method is employed to prompt the character to move in a specified direction (in world space).
Similarly, the `Jump` method initiates a jump, while the `StopJumping` method halts the ongoing jump—particularly crucial when a variable jump height is in use.
Likewise, the `Crouch` method is utilized to initiate the character's crouching action, and the `UnCrouch` method is employed to cease the crouching state.
The complete script is shown below:
Copy
using UnityEngine;
using ECM2;
namespace ECM2.Examples
{
public class CharacterInput : MonoBehaviour
{
// The controlled Character
private Character _character;
private void Awake()
{
// Cache controlled character
_character = GetComponent();
}
private void Update()
{
// Poll movement input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// Compose a movement direction vector in world space
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// If character has a camera assigned,
// make movement direction relative to this camera view direction
if (_character.camera)
{
movementDirection
= movementDirection.relativeTo(_character.cameraTransform);
}
// Set character's movement direction vector
_character.SetMovementDirection(movementDirection);
// Crouch input
if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.C))
_character.Crouch();
else if (Input.GetKeyUp(KeyCode.LeftControl) || Input.GetKeyUp(KeyCode.C))
_character.UnCrouch();
// Jump input
if (Input.GetButtonDown("Jump"))
_character.Jump();
else if (Input.GetButtonUp("Jump"))
_character.StopJumping();
}
}
}
Finally, add the newly created `CharacterInput` script to your **Character** GameObject. You should be able to **move**, **jump** and **crouch**!
circle-exclamation
**Crouching** and **UnCrouching** only modify the character's capsule collider.
[PreviousPackage Contentschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents)
[NextChange Logchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log)
Last updated 2 years ago
---
# Change Log | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#version-1.4.3)
Version 1.4.3
-------------------------------------------------------------------------------------------------------------------------------------
Character
* The `_desiredVelocity` field is now marked as `protected` (was previously `private`), allowing modification from the `CalcDesiredVelocity` method in derived classes.
* The methods `IsJumpAllowed` and `CanJump` are now `public`, enabling access from external (non-derived) classes.
####
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#charactermovement)
CharacterMovement
* The **Advanced** properties are now marked as `public`.
####
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#examples)
Examples
* Updated **FishNet** example to its latest version.
* Added a **Third Person** example for **Fusion 2**.
* Added a **Cinemachine Path Following** example.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#version-1.4.2)
Version 1.4.2
-------------------------------------------------------------------------------------------------------------------------------------
* **New Distribution Versions**: ECM2 is now available in two versions—one for **Unity 2021+** and a native version for **Unity 6**, which includes support for **URP**, the **Input System**, and the latest **Cinemachine** version.
* **Removed Cinemachine Requirement**: The demo scene now uses the `ThirdPersonController` (non-Cinemachine based). `Cinemachine` examples are still available as a separate package.
* **Added New Input System Examples**: New examples demonstrate character control in both `First` and `Third` person views using **Unity’s Input System**.
* **New useFastGeomNormalPath Option for** `**CharacterMovement**`: Added the `useFastGeomNormalPath` option, which allows the `FindGeomOpposingNormal` method to compute `surfaceNormal` using a faster, though slightly less accurate, approximation.
* **InvokeMovementModeChangedEvent in** `**Character**` **Class**: Introduced `InvokeMovementModeChangedEvent` to centralize the `OnMovementModeChanged` method. This allows derived classes to override it, improving modularity and flexibility.
* **ApplyDownwardsForce Now Public**: The `ApplyDownwardsForce` method in the `Character` class is now publicly accessible.
* **Enhanced AddExplosionForce**: Improved the `AddExplosionForce` method for behavior more closely aligned with Unity's native `AddExplosionForce`.
* **Updated FishNet Example**: The FishNet example has been updated to its latest version.
* **Bug Fixes**:
* **Platform Landing Synchronization**: Resolved a slight de-synchronization in character velocity when landing on moving platforms. The issue, influenced by ground friction and falling lateral friction, was due to execution order, where character velocity was adjusted by movement mode before platform velocity was applied.
* **Photon Fusion 2 Initialization**: Fixed an issue in Photon Fusion 2 examples where `NetworkData` was sometimes not initialized under specific conditions.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#version-1.4.1)
Version 1.4.1
-------------------------------------------------------------------------------------------------------------------------------------
* Added networking examples for the latest versions of Fusion, FishNet, Mirror, and NetCode.
* Added Input system example.
* Updated swimming example. This demonstrates the implementation of a jump out of water.
* Minor bug fixes and improvements.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#version-1.4.0)
Version 1.4.0
-------------------------------------------------------------------------------------------------------------------------------------
triangle-exclamation
This version is a complete package revision; as such, there are some significant changes that may affect compatibility with previous versions.
It is recommended to import it into a clean project before applying the update in your main environment.
circle-exclamation
**Important note on package dependencies**
**ECM2 does not require any external package**, however its **Demos** and **Examples** requires **Cinemachine** package to work.
Please make sure to install the **Cinemachine** package into your project when importing **demos** and **examples**.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#general)
General
* The entire package now resides under the `ECM2` namespace.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#character-movement)
**Character Movement**
* The `CollisionBehavior` enum has been renamed to `CollisionBehaviour` to align with Unity's nomenclature and now uses the \[Flags\] attribute.
* The callback associated with `CollisionBehavior` has been renamed to `CollisionBehaviourCallback` to match Unity's nomenclature.
* The `DepenetrationBehavior` enum has been renamed to `DepenetrationBehaviour` to align with Unity's nomenclature, and it now uses the \[Flags\] attribute.
* All fields have been corrected to reflect the 'behaviour' changes.
* The `IComparer` interface has been removed as it was causing runtime allocations.
* The use of `Array.Sort` (which caused runtime allocations) has been replaced with a custom implementation (insertion sort).
* The `State` struct, along with the `GetState` and `SetState` methods, has been removed.
* Collision and overlap limits (`kMaxCollisionCount` and `kMaxOverlapCount`) have been increased to 16 (previously 8).
* The `Velocity` property is now a ref.
* The current plane constraint normal is exposed through the `GetPlaneConstraintNormal()` method.
* The `SetPlatform` method has been renamed to `AttachTo`.
* Fixed an issue with `ImpartPlatformRotation` causing incorrect rotation when upside down.
* Minor bug fixes and improvements.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#mesh-utility)
Mesh Utility
* Resolved a bug causing reversed normals in certain mesh instances.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#slope-limit-behaviour)
Slope Limit Behaviour
* Renamed the `SlopeLimitBehaviour` component and its associated fields to `SlopeLimitBehavior` to align with Unity's naming conventions.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/change-log#character)
Character
circle-exclamation
The `Character` class has undergone a complete refactoring (breaking changes). Among its new features, it now supports extension through composition.
* **Input Code Removal:** All input-related code has been removed for a streamlined codebase.
* **Sprint and Related Fields:** The `Sprint` and related fields have been removed and are now available as examples.
* **Jump Refactor:** The `Jump` functionality has been completely refactored. The original jump can be found in examples as an ability.
* **MovementMode and RotationMode Enums:** `Enums` (`MovementMode` and `RotationMode`) are now part of the `Character` class. Example usage: `Character.MovementMode.Walking`, `Character.RotationMode.OrientRotationToMovement`.
* **deltaTime Property Removal:** The `deltaTime` property has been removed and is now a parameter for functions requiring it.
* **Method Name Changes:** Movement mode-related methods have been renamed for clarity (e.g. `Walking` to `WalkingMovementMode`, `Falling` to `FallingMovementMode, etc`).
* **Move Method Removal:** The `Move` method has been removed.
* **Simulation Method Refactor:** The `Simulation` method has been refactored and split into inner methods and events for increased flexibility.
* **Character Class Removals:**
* `FirstPersonCharacter` has been removed and is now available as an example.
* `ThirdPersonCharacter` has been removed and is now available as an example.
* `AgentCharacter` class has been replaced by the new `NavMeshCharacter` component, an extension adding `NavMesh` based navigation capabilities.
For more details, please refer to the updated documentation.
[PreviousGetting Startedchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/getting-started)
[NextComponentschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components)
Last updated 8 months ago
---
# Package Contents | Easy Character Movement 2

ECM2 Package Contents
circle-info
For a **minimal installation** you should import the **Editor** and **Source** folder only.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents#editor)
Editor
-----------------------------------------------------------------------------------------------------------------------------
Includes editor related source code (**required**).
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents#examples)
Examples
---------------------------------------------------------------------------------------------------------------------------------
Includes all the package fully-commented examples.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents#shared-assets)
Shared Assets
-------------------------------------------------------------------------------------------------------------------------------------------
Includes assets used by examples and walk-through guide.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents#source)
Source
-----------------------------------------------------------------------------------------------------------------------------
Include all the package source code (**required**).
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents#walk-through)
Walk through
-----------------------------------------------------------------------------------------------------------------------------------------
Walk through guide examples.
circle-exclamation
**Important note on package dependencies**
**ECM2 does not require any external package,** however its **Demos** and **Examples** requires **Cinemachine** package to work.
Please make sure to install the **Cinemachine** package into your project when importing **demos** and **examples**.
[PreviousGeneralchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general)
[NextGetting Startedchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/getting-started)
Last updated 2 years ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---
# Examples | Easy Character Movement 2
ECM2 encompasses a diverse set of examples designed to assist you in maximizing its potential.
circle-check
For a thorough understanding, it is strongly suggested to read this document alongside the corresponding examples' source code. Each example provides clean, clear, and fully commented source code, offering valuable insights into ECM2 functionality and how to tailor it to your game's requirements.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#demo)
Demo
-----------------------------------------------------------------------------------------------------------------
This showcases some of the many features that ECM2 offers.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#first-person)
First Person
---------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to extend a `Character` (via inheritance), incorporating support for a standard first-person movement.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#first-person-fly)
First Person Fly
-----------------------------------------------------------------------------------------------------------------------------------------
This example utilizes the first-person character from the previous example and illustrates how to incorporate controls while flying.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#first-person-swim)
First Person Swim
-------------------------------------------------------------------------------------------------------------------------------------------
This example utilizes the first-person character from the previous example and illustrates how to incorporate controls while swimming.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#glide)
Glide
-------------------------------------------------------------------------------------------------------------------
This example demonstrates how to implement a **Glide** ability through composition. It utilizes one of the included 'hook' methods to influence the character's behavior without the need to inherit from the `Character` class.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#jump)
Jump
-----------------------------------------------------------------------------------------------------------------
This example illustrates how to replace the built-in jump of the `Character`, thereby creating a jump ability. This implementation reproduces the jump behavior from previous versions (before v1.4.0).
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#ladders)
Ladders
-----------------------------------------------------------------------------------------------------------------------
This example demonstrates how to implement ladder climbing mechanics by extending a `Character` through composition, introducing a new **Climbing** custom movement mode.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#networking)
Networking
-----------------------------------------------------------------------------------------------------------------------------
circle-info
These examples **illustrate a basic implementation** of ECM2 movement in a networked environment. Please note, they are **not designed to be a complete multiplayer solution** nor do they cover all ECM2 features in networked scenarios. Their primary role is to provide a **foundational starting point** that you can build upon and customize to suit your unique networking framework and project needs.
In this section, you will discover examples of major networking libraries, including the latest versions of **Fusion**, **FishNet**, **Mirror**, and **NetCode** for **GameObjects**.
These examples demonstrate the minimal data required to synchronize the `CharacterMovement` component and `Character` class across a network. Among them, the **Fusion** example stands out as the most comprehensive, implementing full client side prediction and reconciliation, and showcasing the implementation of a histogram (circular buffer) to efficiently store local data such as timers, states, and more while preserving full server authority.
The **FishNet** example is limited to synchronizing `CharacterMovement` only.
On the other hand, both the **Mirror** and **NetCode** examples demonstrate how to configure a `Character` to function with client authority. This approach is quite similar to standalone operation, with only minor differences, making it easier to work with and get started.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#orient-to-ground)
Orient To Ground
-----------------------------------------------------------------------------------------------------------------------------------------
This example illustrates how to orient a `Character` to follow the contour of a 'terrain'. It samples a predefined area to compute an average normal, which is then used to adjust the character's rotation.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#planet-walk)
Planet Walk
-------------------------------------------------------------------------------------------------------------------------------
This example extends a `Character` through inheritance, modifying its gravity and orientation to mimic a planet's curvature, reminiscent of the gameplay in Mario Galaxy.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#side-scrolling)
Side-Scrolling
-------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to configure and execute typical 2D side-scrolling movement.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#slide)
Slide
-------------------------------------------------------------------------------------------------------------------
This example illustrates extending a `Character` through inheritance to implement a slide mechanic. It is realized as a new **Sliding** custom movement mode.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#slope-speed-modifier)
Slope Speed Modifier
-------------------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to utilize the newly introduced `GetSignedSlopeAngle` function (introduced in v1.4.0) to adjust the characters' movement speed based on the slope angle.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#teleport)
Teleport
-------------------------------------------------------------------------------------------------------------------------
This example shows how to implement a basic teleport system. It enables the teleportation of the `Character` and adjusts its rotation to match the orientation of the teleporter.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#third-person-controller)
Third-Person Controller
-------------------------------------------------------------------------------------------------------------------------------------------------------
This example serves as a practical demonstration of how to implement a basic third-person character controller.
This example facilitates easy integration into Unity projects, offering customizable parameters for follow distance, sensitivity, and pitch constraints.
Users can understand and adapt the provided code to establish essential functionalities like character movement, camera rotation, and zoom input.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#toggle-gravity-direction)
Toggle Gravity Direction
---------------------------------------------------------------------------------------------------------------------------------------------------------
This example demonstrates how to extend a `Character` through composition, enabling the modification of its gravity direction with a toggle feature. Additionally, it orients the character along the world-up defined by the gravity direction.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples#twin-stick-movement)
Twin-Stick Movement
-----------------------------------------------------------------------------------------------------------------------------------------------
This example illustrates how to extend a `Character` through inheritance, incorporating a custom rotation mode. In this instance, it implements controls typical of a **Mouse** and **Keyboard** twin-stick shooter.
[PreviousRoot Motion Controllerchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/root-motion-controller)
[NextCreating a Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/creating-a-character)
Last updated 8 months ago
---
# Creating a Character | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/creating-a-character#creating-a-character)
Creating a Character
-----------------------------------------------------------------------------------------------------------------------------------------------------
* Right-click on the hierarchy window to open the creation dialog and select the **Character** option from the **ECM2** category.

* It will create an empty character (no visual representation) named **Character.**

Newly created Character
circle-info
Make sure its origin is set to (0, 0, 0) as this will save you troubles when parenting your model.
* Parent your model to this newly `Character` `GameObject`. For this example, we'll use the included **ECM2\_Capsule** model.

Character's model
* In the `CharacterMovement` component, adjust your **radius** and **height** values (this will automatically configure your character’s capsule collider) to better fit your character’s model.

CharacterMovement component
At this point, we have a fully configured and ready character; however, we are unable to move or control it. We will address and resolve this in the following section.
[PreviousExampleschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples)
[NextControlling a Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character)
Last updated 2 years ago
---
# Customer Support | Easy Character Movement 2
If you have any comments, need assistance, or have a feature you would like to see added, please don't hesitate to contact me at **ogracian@gmail.com**. I'll be happy to assist you.
circle-exclamation
Please make sure to **include the invoice number** you received with your purchase when requesting support via email.
[PreviousCinemachinechevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/cinemachine)
Last updated 2 years ago
---
# NavMesh Character | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character#description)
Description
---------------------------------------------------------------------------------------------------------------------------------------------------
The `NavMeshCharacter` component extends a `Character` through composition, incorporating `NavMesh`\-based navigation. This enables a `Character` to intelligently navigate through the world.
circle-exclamation
This component replaces the `AgentCharacter` class from previous versions.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character#properties)
Properties
-------------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// Cached NavMeshAgent component.
///
public NavMeshAgent agent
///
/// Cached Character component.
///
public Character character
///
/// Should the agent brake automatically to avoid overshooting the destination point?
/// If this property is set to true, the agent will brake automatically as it nears the destination.
///
public bool autoBraking
///
/// Distance from target position to start braking.
///
public float brakingDistance
///
/// The ratio (0 - 1 range) of the agent's remaining distance and the braking distance.
/// 1 If no auto braking or if agent's remaining distance is greater than brakingDistance.
/// less than 1, if agent's remaining distance is less than brakingDistance.
///
public float brakingRatio
///
/// Stop within this distance from the target position.
///
public float stoppingDistance
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character#public-methods)
Public Methods
---------------------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// Does the Agent currently has a path?
///
public virtual bool HasPath()
///
/// True if Agent is following a path, false otherwise.
///
public virtual bool IsPathFollowing()
///
/// Returns the destination set for this agent.
/// If a destination is set but the path is not yet processed,
/// the returned position will be valid navmesh position that's closest to the previously set position.
/// If the agent has no path or requested path - returns the agents position on the navmesh.
/// If the agent is not mapped to the navmesh (e.g. Scene has no navmesh) - returns a position at infinity.
///
public virtual Vector3 GetDestination()
///
/// Requests the character to move to the valid navmesh position that's closest to the requested destination.
///
public virtual void MoveToDestination(Vector3 destination)
///
/// Pause / Resume Character path following movement.
/// If set to True, the character's movement will be stopped along its current path.
/// If set to False after the character has stopped, it will resume moving along its current path.
///
public virtual void PauseMovement(bool pause)
///
/// Halts Character's current path following movement.
/// This will clear agent's current path.
///
public virtual void StopMovement()
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character#events)
Events
-----------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// Event triggered when agent reaches its destination.
///
public event DestinationReachedEventHandler DestinationReached;
[PreviousCharacterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character)
[NextCharacter Movementchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement)
Last updated 2 years ago
---
# Physics Volume | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/physics-volume#description)
Description
------------------------------------------------------------------------------------------------------------------------------------------------
A `PhysicsVolume` is a helper component used to define volumes such as water, air, oil, etc., and/or modify a character's behaviors. When a `Character` is inside this volume, it will react according to the defined settings.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/physics-volume#properties)
Properties
----------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// This volume collider (trigger).
///
public BoxCollider boxCollider
///
/// Determines which PhysicsVolume takes precedence if they overlap (higher value == higher priority).
///
public int priority
///
/// Determines the amount of friction applied by the volume as Character's using CharacterMovement move through it.
/// The higher this value, the harder it will feel to move through the volume.
///
public float friction
///
/// Determines the terminal velocity of Character's using CharacterMovement when falling.
///
public float maxFallSpeed
///
/// Determines if the volume contains a fluid, like water.
///
public bool waterVolume
[PreviousSlope Limit Behaviourchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour)
[NextRoot Motion Controllerchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/root-motion-controller)
Last updated 2 years ago
---
# Root Motion Controller | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/root-motion-controller#description)
Description
--------------------------------------------------------------------------------------------------------------------------------------------------------
The `RootMotionController` is a utility component designed to enhance root motion support. This component is responsible for calculating and supplying root motion velocity and rotation to the `Character` class.
circle-info
The `RootMotionController` component must be added to the `GameObject` with your `Animator`, usually the model of your character.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/root-motion-controller#public-methods)
Public Methods
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// Flush any accumulated deltas.
/// This prevents accumulation while character is toggling root motion.
///
public virtual void FlushAccumulatedDeltas()
///
/// Return current root motion rotation and clears accumulated delta rotation.
///
public virtual Quaternion ConsumeRootMotionRotation()
///
/// Return current root motion velocity and clears accumulated delta positions.
///
public virtual Vector3 ConsumeRootMotionVelocity(float deltaTime)
[PreviousPhysics Volumechevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/physics-volume)
[NextExampleschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples)
Last updated 2 years ago
---
# Slope Limit Behaviour | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour#description)
Description
-------------------------------------------------------------------------------------------------------------------------------------------------------
The `SlopeLimitBehaviour` component allows us to define the walk-able behavior of an object as a whole, rather than on a per-face basis. When enabled, it permits us to override the `CharacterMovement` `slopeLimit` property, providing greater flexibility.
This is particularly useful in cases where we want to constrain (or permit) specific objects or zones to a particular behavior, regardless of their slope limit value. For instance, marking other characters as non-walk-able, preventing a player character from landing on them.
To utilize this feature, add the `SlopeLimitBehaviour` to the `GameObject` with your `Collider`. Then, in the `CharacterMovement` component, make sure to set the `slopeLimitOverride` property to true.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour#enums)
Enums
-------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// The slope behaviour for attached collider.
///
public enum SlopeBehaviour
{
Default,
///
/// Sets the collider as walkable.
///
Walkable,
///
/// Sets the collider as not walkable.
///
NotWalkable,
///
/// Let you specify a custom slope limit value for collider.
///
Override
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour#properties)
Properties
-----------------------------------------------------------------------------------------------------------------------------------------------------
Copy
///
/// The current behaviour.
///
public SlopeBehaviour walkableSlopeBehaviour
///
/// The slope limit angle in degrees.
/// Only used on SlopeBehaviour.Override.
///
public float slopeLimit
///
/// The cosine of slope angle (in radians).
/// This is used for faster angle tests (e.g. dotProduct > slopeLimitCos)
///
public float slopeLimitCos
[PreviousCharacter Movementchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement)
[NextPhysics Volumechevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/physics-volume)
Last updated 2 years ago
---
# Character Movement | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#description)
Description
----------------------------------------------------------------------------------------------------------------------------------------------------
The `CharacterMovement` component is a robust and feature-rich fully kinematic character controller, also known as a motor.
It has been developed as a compelling alternative to Unity's character controller, maintaining the familiar workflow through functions like `Move` / `SimpleMove`, while surpassing it with a myriad of enhanced features and advantages.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#what-is-a-character-controller)
What is a character controller ?
A **Character Controller** facilitates straightforward movement constrained by collisions, eliminating the need to grapple with a dynamic `Rigidbody`.
Unlike a dynamic `Rigidbody`, a **Character Controller** remains unaffected by forces and will only initiate movement upon calling the `Move` function. Subsequently, it executes the intended movement while adhering to collision constraints.
In the earlier days of gaming, titles didn't rely on a 'true' physics engine like the **PhysX SDK** (Unity's underlying physics engine). However, they still employed a character controller to navigate players within a level. Games like **Quake** or **Doom** utilized a bespoke piece of code for collision detection and response, often constituting the sole physics aspect in the entire game. While these implementations lacked extensive physics, they heavily leaned on meticulously adjusted values to deliver an immersive player experience. The specific algorithm governing their behavior is commonly known as the '**collide and slide**' algorithm, refined over more than a decade for optimal performance.
The `CharacterMovement` component is an implementation of such an algorithm, delivering a reliable and widely recognized behavior for character control.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#the-character-movement-component)
The Character Movement Component
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Character Movement Component
Property:
Function:
**Plane Constraint**
Allow to constrain the Character so movement along the locked axis is not possible.
**Root Transform**
The root GameObject of your character's model.
**Root Transform Offset**
The root transform will be positioned at this offset from foot position.
**Radius**
The Character's capsule collider radius.
**Height**
The Character's capsule collider height.
**Slope Limit**
The maximum angle (in degrees) for a walk-able surface.
**Step Offset**
The maximum height (in meters) for a valid step.
**Perch Offset**
Allow a Character to perch on the edge of a surface if the horizontal distance from the Character's position to the edge is closer than this.
**Perch Additional Height**
When perching on a ledge, add this additional distance to step offset when determining how high above a walk-able ground we can perch.
**Slope Limit Override**
If enabled, colliders with `SlopeLimitBehaviour` component will be able to override this slope limit.
**Use Flat Top**
If enabled, will treat head collisions as if the character is using a shape with a flat top.
**Use Flat Base For Ground Checks**
If enabled, performs ground checks as if the character is using a shape with a flat base. This avoids the situation where characters slowly lower off the side of a ledge (as their capsule 'balances' on the edge).
**Collision Layers**
Character collision layers mask.
**Trigger Interaction**
Overrides the global `Physics.queriesHitTriggers` to specify whether queries (raycasts, spherecasts, overlap tests, etc.) hit Triggers by default.
`**Advanced**`**:**
**Min Move Distance**
The minimum move distance of the character controller. In most situations this value should be left at 0.
**Max Movement Iterations**
Max number of iterations used during movement.
**Max Depenetration Iterations**
Max number of iterations used to resolve penetrations.
**Enable Physics Interactions**
If enabled, the character will interact with dynamic rigidbodies when walking into them.
**Allow Push Characters**
If enabled, the character will interact with other characters when walking into them.
**Impart Platform Movement**
If enabled, the character will move with the moving platform it is standing on.
**Impart Platform Rotation**
If enabled, the character will rotate (**yaw-only**) with the moving platform it is standing on.
**Impart Platform Velocity**
If enabled, impart the platform's velocity when jumping or falling off it.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#details)
Details
--------------------------------------------------------------------------------------------------------------------------------------------
The `CharacterMovement` component, in addition to its primary function of constrained movement by collision, offers a broad range of specifically designed functions to leverage its capabilities to the fullest.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#properties)
Properties
Copy
///
/// Cached character's transform.
///
public new Transform transform
///
/// The Character's rigidbody.
///
public new Rigidbody rigidbody
///
/// The Rigidbody interpolation setting.
///
public RigidbodyInterpolation interpolation
///
/// The Character's collider.
///
public new Collider collider
///
/// The root bone in the avatar.
///
public Transform rootTransform
///
/// The root transform will be positioned at this offset.
///
public Vector3 rootTransformOffset
///
/// The character's current position.
///
public Vector3 position
///
/// The character's current rotation.
///
public Quaternion rotation
///
/// The character's center in world space.
///
public Vector3 worldCenter
///
/// The character's updated position.
///
public Vector3 updatedPosition
///
/// The character's updated rotation.
///
public Quaternion updatedRotation
///
/// The current relative velocity of the Character.
/// The velocity is relative because it won't track movements to the transform that happen outside of this,
/// e.g. character parented under another moving Transform, such as a moving vehicle.
///
public ref Vector3 velocity
///
/// The character's speed.
///
public float speed
///
/// The character's speed along its forward vector (e.g: in local space).
///
public float forwardSpeed
///
/// The character's speed along its right vector (e.g: in local space).
///
public float sidewaysSpeed
///
/// The Character's capsule collider radius.
///
public float radius
///
/// The Character's capsule collider height.
///
public float height
///
/// The maximum angle (in degrees) for a walkable slope.
///
public float slopeLimit
///
/// The maximum height (in meters) for a valid step.
///
public float stepOffset
///
/// Allow a Character to perch on the edge of a surface if the horizontal distance from the Character's position to the edge is closer than this.
/// Note that we still enforce stepOffset to start the step up, this just allows the Character to hang off the edge or step slightly higher off the ground.
///
public float perchOffset
///
/// When perching on a ledge, add this additional distance to stepOffset when determining how high above a walkable ground we can perch.
///
public float perchAdditionalHeight
///
/// Should allow external slope limit override ?
///
public bool slopeLimitOverride
///
/// When enabled, will treat head collisions as if the character is using a shape with a flat top.
///
public bool useFlatTop
///
/// Performs ground checks as if the character is using a shape with a flat base.
/// This avoids the situation where characters slowly lower off the side of a ledge (as their capsule 'balances' on the edge).
///
public bool useFlatBaseForGroundChecks
///
/// Layers to be considered during collision detection.
///
public LayerMask collisionLayers
///
/// Determines how the Character should interact with triggers.
///
public QueryTriggerInteraction triggerInteraction
///
/// Should perform collision detection ?
///
public bool detectCollisions
///
/// What part of the capsule collided with the environment during the last Move call.
///
public CollisionFlags collisionFlags
///
/// Is the Character's movement constrained to a plane ?
///
public bool isConstrainedToPlane
///
/// Should movement be constrained to ground when on walkable ground ?
/// Toggles ground constraint.
///
public bool constrainToGround
///
/// Is the Character constrained to walkable ground ?
///
public bool isConstrainedToGround
///
/// Is the ground constraint temporary disabled?
///
public bool isGroundConstraintPaused
///
/// If isGroundConstraintPaused is true, this represent the pause remaining time.
///
public float unconstrainedTimer
///
/// Was the character on ground last Move call ?
///
public bool wasOnGround
///
/// Is the character on ground ?
///
public bool isOnGround
///
/// Was the character on walkable ground last Move call ?
///
public bool wasOnWalkableGround
///
/// Is the character on walkable ground ?
///
public bool isOnWalkableGround
///
/// Was the character on walkable ground AND constrained to ground last Move call ?
///
public bool wasGrounded
///
/// Is the character on walkable ground AND constrained to ground.
///
public bool isGrounded
///
/// The signed distance to ground.
///
public float groundDistance
///
/// The current ground impact point.
///
public Vector3 groundPoint
///
/// The current ground normal.
///
public Vector3 groundNormal
///
/// The current ground surface normal.
///
public Vector3 groundSurfaceNormal
///
/// The current ground collider.
///
public Collider groundCollider
///
/// The current ground transform.
///
public Transform groundTransform
///
/// The Rigidbody of the collider that was hit. If the collider is not attached to a rigidbody then it is null.
///
public Rigidbody groundRigidbody
///
/// Structure containing information about current ground.
///
public FindGroundResult currentGround
///
/// Structure containing information about current moving platform (if any).
///
public MovingPlatform movingPlatform
///
/// The terminal velocity when landed (eg: isGrounded).
///
public Vector3 landedVelocity
///
/// Set this to true if riding on a moving platform that you know is clear from non-moving world obstructions.
/// Optimization to avoid sweeps during based movement, USE WITH CARE.
///
public bool fastPlatformMove
///
/// Whether the Character moves with the moving platform it is standing on.
/// If true, the Character moves with the moving platform.
///
public bool impartPlatformMovement
///
/// Whether the Character receives the changes in rotation of the platform it is standing on.
/// If true, the Character rotates with the moving platform.
///
public bool impartPlatformRotation
///
/// If true, impart the platform's velocity when jumping or falling off it.
///
public bool impartPlatformVelocity
///
/// If enabled, the player will interact with dynamic rigidbodies when walking into them.
///
public bool enablePhysicsInteraction
///
/// If enabled, the player will interact with other characters when walking into them.
///
public bool physicsInteractionAffectsCharacters
///
/// Force applied to rigidbodies when walking into them (due to mass and relative velocity) is scaled by this amount.
///
public float pushForceScale
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#public-methods)
Public Methods
Copy
///
/// Specifies the character's bounding volume (eg: capsule) dimensions.
///
/// The character's volume radius.
/// The character's volume height
public void SetDimensions(float characterRadius, float characterHeight)
///
/// Specifies the character's bounding volume (eg: capsule) height.
///
/// The character's volume height
public void SetHeight(float characterHeight)
///
/// Returns the character current position.
///
public Vector3 GetPosition()
///
/// Update character current position.
/// If updateGround is true, will find for ground and update character's current ground result.
///
public void SetPosition(Vector3 newPosition, bool updateGround = false)
///
/// Returns the character current rotation.
///
public Quaternion GetRotation()
///
/// Update character current rotation.
///
public void SetRotation(Quaternion newRotation)
///
/// Sets the world space position and rotation of this character.
/// If updateGround is true, will find for ground and update character's current ground result.
///
public void SetPositionAndRotation(Vector3 newPosition, Quaternion newRotation, bool updateGround = false)
///
/// Orient the character's towards the given direction (in world space) using maxDegreesDelta as the rate of rotation change.
///
/// The target direction in world space.
/// Change in rotation per second (Deg / s).
/// If True, the rotation will be performed on the Character's plane (defined by its up-axis).
public void RotateTowards(Vector3 worldDirection, float maxDegreesDelta, bool updateYawOnly = true)
///
/// Current plane constraint normal.
///
public Vector3 GetPlaneConstraintNormal()
///
/// Defines the axis that constraints movement, so movement along the given axis is not possible.
///
public void SetPlaneConstraint(PlaneConstraint constrainAxis, Vector3 planeNormal)
///
/// Returns the given DIRECTION (Normalized) vector constrained to current constraint plane (if _constrainToPlane != None)
/// or given vector (if _constrainToPlane == None).
///
public Vector3 ConstrainDirectionToPlane(Vector3 direction)
///
/// Constrain the given vector to current PlaneConstraint (if any).
///
public Vector3 ConstrainVectorToPlane(Vector3 vector)
///
/// Adds a force to the Character.
/// This forces will be accumulated and applied during Move method call.
///
public void AddForce(Vector3 force, ForceMode forceMode = ForceMode.Force)
///
/// Applies a force to this Character that simulates explosion effects.
/// The explosion is modeled as a sphere with a certain centre position and radius in world space;
/// normally, anything outside the sphere is not affected by the explosion and the force decreases in proportion to distance from the centre.
/// However, if a value of zero is passed for the radius then the full force will be applied regardless of how far the centre is from the rigidbody.
/// The force direction is from the given origin to the Character center.
///
public void AddExplosionForce(float strength, Vector3 origin, float radius, ForceMode forceMode = ForceMode.Force)
///
/// Set a pending launch velocity on the Character. This velocity will be processed next Move call.
///
/// The desired launch velocity.
/// If true replace the vertical component of the Character's velocity instead of adding to it.
/// If true replace the XY part of the Character's velocity instead of adding to it.
public void LaunchCharacter(Vector3 launchVelocity, bool overrideVerticalVelocity = false, bool overrideLateralVelocity = false)
///
/// Allows you to explicitly attach this to a moving 'platform' so it no depends of ground state.
///
public void AttachTo(Rigidbody parent)
///
/// Temporarily disable ground constraint allowing the Character to freely leave the ground.
/// Eg: LaunchCharacter, Jump, etc.
///
public void PauseGroundConstraint(float unconstrainedTime = 0.1f)
///
/// Moves the character along its current velocity.
/// This performs collision constrained movement resolving any collisions / overlaps found during this movement.
///
/// The simulation deltaTime.
public CollisionFlags Move(float deltaTime)
///
/// Moves the character along the given velocity vector.
/// This performs collision constrained movement resolving any collisions / overlaps found during this movement.
///
/// The updated velocity for current frame. It is typically a combination of vertical motion due to gravity and lateral motion when your character is moving.
/// The simulation deltaTime. If not assigned, it defaults to Time.deltaTime.
/// Return CollisionFlags. It indicates the direction of a collision: None, Sides, Above, and Below.
public CollisionFlags Move(Vector3 newVelocity, float deltaTime)
///
/// Update the character's velocity using a friction-based physical model and move the character along its updated velocity.
/// This performs collision constrained movement resolving any collisions / overlaps found during this movement.
///
/// Target velocity
/// The maximum speed when grounded. Also determines maximum horizontal speed when falling (i.e. not-grounded).
/// The rate of change of velocity when accelerating (i.e desiredVelocity != Vector3.zero).
/// The rate at which the character slows down when braking (i.e. not accelerating or if character is exceeding max speed).
/// This is a constant opposing force that directly lowers velocity by a constant value.
/// Setting that affects movement control. Higher values allow faster changes in direction.
/// Friction (drag) coefficient applied when braking (whenever desiredVelocity == Vector3.zero, or if character is exceeding max speed).
/// The current gravity force. Defaults to zero.
/// Determines if the vertical velocity component should be ignored when falling (i.e. not-grounded) preserving gravity effects. Defaults to true.
/// The simulation deltaTime.
/// Return CollisionFlags. It indicates the direction of a collision: None, Sides, Above, and Below.
public CollisionFlags SimpleMove(Vector3 desiredVelocity, float maxSpeed, float acceleration,
float deceleration, float friction, float brakingFriction, Vector3 gravity = default,
bool onlyHorizontal = true, float deltaTime = 0.0f)
///
/// Return the number of collisions found during last Move call.
///
public int GetCollisionCount()
///
/// Retrieves a CollisionResult from last Move call list.
///
public CollisionResult GetCollisionResult(int index)
///
/// Makes the character to ignore all collisions vs otherCollider.
///
public void IgnoreCollision(Collider otherCollider, bool ignore = true)
///
/// Makes the character to ignore collisions vs all colliders attached to the otherRigidbody.
///
public void IgnoreCollision(Rigidbody otherRigidbody, bool ignore = true)
///
/// Makes the character's collider (eg: CapsuleCollider) to ignore all collisions vs otherCollider.
/// NOTE: The character can still collide with other during a Move call if otherCollider is in CollisionLayers mask.
///
public void CapsuleIgnoreCollision(Collider otherCollider, bool ignore = true)
///
/// Sweeps the character's volume along its displacement vector, stopping at near hit point if collision is detected.
/// Returns True when the rigidbody sweep intersects any collider, otherwise false.
///
public bool MovementSweepTest(Vector3 characterPosition, Vector3 sweepDirection, float sweepDistance,
out CollisionResult collisionResult)
{
return MovementSweepTest(characterPosition, velocity, sweepDirection * sweepDistance, out collisionResult);
}
///
/// Compute distance to the ground from bottom sphere of capsule and store the result in collisionResult.
/// This distance is the swept distance of the capsule to the first point impacted by the lower hemisphere,
/// or distance from the bottom of the capsule in the case of a raycast.
///
public void ComputeGroundDistance(Vector3 characterPosition, float sweepRadius, float sweepDistance,
float castDistance, out FindGroundResult outGroundResult)
///
/// Sweeps a vertical cast to find the ground for the capsule at the given location.
/// Will attempt to perch if ShouldComputePerchResult() returns true for the downward sweep result.
/// No ground will be found if collision is disabled (eg: detectCollisions == false).
///
public void FindGround(Vector3 characterPosition, out FindGroundResult outGroundResult)
///
/// Checks if any colliders overlaps the character's capsule-shaped volume in world space using testHeight as capsule's height.
/// Returns true if there is a blocking overlap, false otherwise.
///
public bool CheckCapsule()
///
/// Checks if any colliders overlaps the character's capsule-shaped volume in world space using testHeight as capsule's height.
/// Returns true if there is a blocking overlap, false otherwise.
///
public bool CheckHeight(float testHeight)
///
/// Casts a ray, from point origin, in direction direction, of length distance, against specified colliders (by layerMask) in the Scene.
///
public bool Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask, out RaycastHit hitResult, float thickness = 0.0f)
///
/// Check the given capsule against the physics world and return all overlapping colliders.
/// Return overlapped colliders count.
///
public int OverlapTest(Vector3 characterPosition, Quaternion characterRotation, float testRadius,
float testHeight, int layerMask, Collider[] results, QueryTriggerInteraction queryTriggerInteraction)
///
/// Check the character's capsule against the physics world and return all overlapping colliders.
/// Return an array of overlapped colliders.
///
public Collider[] OverlapTest(int layerMask, QueryTriggerInteraction queryTriggerInteraction,
out int overlapCount)
///
/// Check the given capsule against the physics world and return all overlapping colliders.
/// Return an array of overlapped colliders.
///
public Collider[] OverlapTest(Vector3 characterPosition, Quaternion characterRotation, float testRadius,
float testHeight, int layerMask, QueryTriggerInteraction queryTriggerInteraction, out int overlapCount)
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#callbacks)
Callbacks
Copy
///
/// Let you define if the character should collide with given collider.
///
/// The collider.
/// True to filter (ignore) given collider, false to collide with given collider.
public delegate bool ColliderFilterCallback(Collider collider);
///
/// Let you define the character behaviour when collides with collider.
///
/// The collided collider
/// The desired collision behaviour flags.
public delegate CollisionBehaviour CollisionBehaviourCallback(Collider collider);
///
/// Let you modify the collision response vs dynamic objects,
/// eg: compute resultant impulse and / or application point (CollisionResult.point).
///
public delegate void CollisionResponseCallback(ref CollisionResult inCollisionResult, ref Vector3 characterImpulse, ref Vector3 otherImpulse);
///
/// Let you define if the character should collide with given collider.
/// Return true to filter (ignore) collider, false otherwise.
///
public ColliderFilterCallback colliderFilterCallback
///
/// Let you define the character behaviour when collides with collider.
///
public CollisionBehaviourCallback collisionBehaviourCallback
///
/// Let you modify the collision response vs dynamic objects,
/// eg: compute resultant impulse and / or application point (CollisionResult.point).
///
public CollisionResponseCallback collisionResponseCallback
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character-movement#events)
Events
Copy
///
/// Event triggered when characters collides with other during a Move.
/// Can be called multiple times.
///
public event CollidedEventHandler Collided;
///
/// Event triggered when a character finds ground (walkable or non-walkable) as a result of a downcast sweep (eg: FindGround method).
///
public event FoundGroundEventHandler FoundGround;
[PreviousNavMesh Characterchevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character)
[NextSlope Limit Behaviourchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/slope-limit-behaviour)
Last updated 2 years ago
---
# Character | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#description)
Description
-------------------------------------------------------------------------------------------------------------------------------------------
The `Character` class serves as the foundational element for all game avatars, whether under player control or managed by AI. This class employs the `CharacterMovement` component as its character controller / motor, seamlessly integrating typical modes of movement, such as walking, falling, flying, and swimming. Additionally, it boasts fully configurable jump and crouch mechanics.
The `Character` class dictates its movement based on its current mode, delegating the execution of this movement to the `CharacterMovement` component, which ultimately performs the physical motion.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#how-does-a-character-work)
How Does a Character Work?
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
By default, a `Character` implements an auto-simulation, taking on the responsibility of invoking its `Simulate` method. This method undertakes the heavy lifting of the character's movement, including updating its current movement mode, adjusting rotation based on its current rotation mode, handling jump and crouch actions, triggering events, and more.
When auto-simulation is enabled (the default operation), the `Character` implements a `LateFixedUpdate` through a coroutine. This ensures that the `Character` is simulated after Unity's internal physics update, a crucial step to deliver seamless physical interactions.
circle-info
Utilize the `enableAutoSimulation` property of the `Character` to enable or disable its auto-simulation.
In essence, a `Character` interprets input vectors and events, including keyboard inputs used to control the character. It translates these inputs into updates for the character's position and rotation. This process occurs through its different movement modes, such as walking, flying, swimming or any custom mode you may create. Each mode defines how inputs are processed and influences the resulting outputs.
All of this occurs within the `Simulate` method, with the following execution order:
Copy
public void Simulate(float deltaTime)
{
if (isPaused)
return;
BeforeSimulationUpdate(deltaTime);
SimulationUpdate(deltaTime);
AfterSimulationUpdate(deltaTime);
CharacterMovementUpdate(deltaTime);
}
Where:
Copy
private void BeforeSimulationUpdate(float deltaTime)
This is called before any movement mode is updated. It automatically switches between the **Walking** and **Falling** movement modes based on the `CharacterMovement` grounding status and handles the **jump** and **crouch** mechanics.
Finally, it triggers the `OnBeforeSimulationUpdate` event, allowing us to expand its functionality.
circle-info
Utilize the `OnBeforeSimulationUpdate` method/event to externally update the character's state.
Copy
private void SimulationUpdate(float deltaTime)
This utilizes the given movement direction vector (`SetMovementDirection`) to calculate a desired velocity vector. Subsequently, this information is handed over to the current movement mode, which, in turn, adjusts the character's velocity according to its defined rules.
Additionally, it performs the character's rotation according to its current rotation mode.
Copy
private void AfterSimulationUpdate(float deltaTime)
This method is responsible for triggering the `ReachedJumpApex` and `AfterSimulationUpdated` events. At this point, the character's **rotation** and **velocity** are updated according to its current modes, but the movement has not been applied yet. This occurs in the subsequent `CharacterMovementUpdate` method.
Copy
private void CharacterMovementUpdate(float deltaTime)
This final simulation method passes the character's **velocity** to the `CharacterMovement Move` method, which subsequently executes the requested movement. Finally, it triggers the `CharacterMovementUpdated` event. At this point, the character's state is up to date.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#character-movement-modes)
Character Movement Modes
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
The `Character` class introduces the concept of **Movement Modes**, such as **Walking**, **Falling**, **Flying**, **Swimming**, and **Custom**. Each movement mode has a set of predefined rules and properties that dictate how the character moves through the world. While this concept is somewhat related to character states (e.g., logical states like Jumping, Attacking, Dying, etc.), it should not be confused. The primary purpose of a **Movement Mode** is to determine how the character should move through the world.
For instance, the **Flying Movement Mode**, while implying that the character is in a flying logical state, specifically defines how the character is moved. For example, **it allows the character to move through the air without being affected by gravity, giving it the freedom to remain unbound to the ground, with its vertical velocity preserved**.
The movement modes are defined as follows:
Copy
public enum MovementMode
{
///
/// Disables movement clearing velocity and any pending forces / impulsed on Character.
///
None,
///
/// Walking on a surface, under the effects of friction, and able to "step up" barriers.
/// Vertical velocity is zero.
///
Walking,
///
/// Falling under the effects of gravity, after jumping or walking off the edge of a surface.
///
Falling,
///
/// Flying, ignoring the effects of gravity.
///
Flying,
///
/// Swimming through a fluid volume, under the effects of gravity and buoyancy.
///
Swimming,
///
/// User-defined custom movement mode, including many possible sub-modes.
///
Custom
}
You can change the character's movement mode by using its `SetMovementMode` function. This action automatically invokes the `OnMovementModeChanged` method and triggers the `MovementModeChanged` event. The `OnMovementModeChanged` method is specifically designed to handle the initiation of particular modes, such as enabling or disabling ground constraints, stopping jumps, resetting jump counts, and more.
It's important to note that **Walking** and **Falling** modes are automatically managed based on the character’s grounding status. When the character is constrained to the ground on a walk-able surface, the **Walking** movement mode is enabled. Conversely, if the character is not on the ground or is on a non-walkable surface, it will switch to the **Falling** movement mode.
For the **Flying** movement mode, you need to explicitly enable and disable it as necessary. Exiting the **Flying** state is safely achieved by transitioning to the **Falling** movement mode, which, in turn, automatically leads to the **Walking** mode. This principle also applies to **Custom** movement modes.
Copy
// Enter flying mode
SetMovementMode(MovementMode.Flying);
..
// Exits flying mode
SetMovementMode(MovementMode.Falling);
circle-info
While you can manually enable / disable the **Swimming** movement mode, this is automatically managed when using a`PhysicsVolume`.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#moving-a-character)
Moving a Character
---------------------------------------------------------------------------------------------------------------------------------------------------------
A `Character` comprises a set of methods specifically crafted to streamline the execution of actions, usually in response to input events like on-down, on-up, and so forth.
The methods incorporated are:
Copy
///
/// Assigns the Character's movement direction (in world space),
/// eg: our desired movement direction vector.
///
public void SetMovementDirection(Vector3 movementDirection)
///
/// Request the Character to jump.
/// The request is processed on the next simulation update.
/// Call this from an input event (such as a button 'down' event).
///
public virtual void Jump()
///
/// Request the Character to end a jump.
/// The request is processed on the next simulation update.
/// Call this from an input event (such as a button 'down' event).
///
public virtual void StopJumping()
///
/// Request the Character to crouch.
/// The request is processed on the next simulation update.
/// Call this from an input event (such as a button 'down' event).
///
public virtual void Crouch()
///
/// Request the Character to stop crouching.
/// The request is processed on the next simulation update.
/// Call this from an input event (such as a button 'up' event).
///
public virtual void UnCrouch()
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#movement-relative-to-camera)
Movement Relative to Camera
It is often necessary to align our character's movement with the camera's orientation, ensuring consistent motion regardless of the camera's viewing direction. To simplify this process, ECM2 incorporates a helpful `Vector3` extension method:
Copy
///
/// Transforms a vector to be relative to given transform.
/// If isPlanar == true, the transform will be applied on the plane defined by world up axis.
///
public static Vector3 relativeTo(this Vector3 vector3, Transform relativeToThis, bool isPlanar = true)
This can be employed to align our movement direction with the character's follow camera as follows:
Copy
// Poll input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// World space movement direction
Vector3 movementDirection = Vector3.zero;
movementDirection += Vector3.right * inputMove.x;
movementDirection += Vector3.forward * inputMove.y;
// Make movement direction relative to a given Transform
movementDirection = movementDirection.relativeTo(_character.cameraTransform);
// Assign camera's relative movement direction to character
_character.SetMovementDirection(movementDirection);
An alternative approach, without utilizing the `relativeTo` extension method, is demonstrated below:
Copy
// Pool input
Vector2 inputMove = new Vector2()
{
x = Input.GetAxisRaw("Horizontal"),
y = Input.GetAxisRaw("Vertical")
};
// Movement relative to a camera's Transform (cameraTransform)
Vector3 movementDirection = Vector3.zero;
movementDirection += cameraTransform.right * inputMove.x;
movementDirection += cameraTransform.forward * inputMove.y;
// Assign camera's relative movement direction to character
_character.SetMovementDirection(movementDirection);
The primary distinction lies in the `relativeTo` extension method, allowing us to execute the transformation on the plane defined by the given world-up axis. This becomes crucial when working with custom world-up directions, as seen in games like Mario Galaxy.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#character-rotation-modes)
Character Rotation Modes
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
A `Character`, although it can be rotated as desired by directly modifying its `rotation` property, also incorporates a set of predefined Rotation Modes, similar to the Movement Modes.
The rotation modes are defined as follows:
Copy
public enum RotationMode
{
///
/// Disable Character's rotation.
///
None,
///
/// Smoothly rotate the Character toward the direction of acceleration,
/// using rotationRate as the rate of rotation change.
///
OrientRotationToMovement,
///
/// Smoothly rotate the Character toward camera's view direction,
/// using rotationRate as the rate of rotation change.
///
OrientRotationToViewDirection,
///
/// Let root motion handle Character rotation.
///
OrientWithRootMotion,
///
/// User-defined custom rotation mode.
///
Custom
}
The `Character` incorporates the following functions designed for alter its rotation:
Copy
///
/// Sets the Character's current rotation mode.
///
public void SetRotationMode(RotationMode rotationMode)
///
/// Sets the yaw value.
/// This will reset current pitch and roll values.
///
public virtual void SetYaw(float value)
///
/// Amount to add to Yaw (up axis).
///
public virtual void AddYawInput(float value)
///
/// Amount to add to Pitch (right axis).
///
public virtual void AddPitchInput(float value)
///
/// Amount to add to Roll (forward axis).
///
public virtual void AddRollInput(float value)
This are processed on the next simulation update.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#ground-constraint)
Ground Constraint
-------------------------------------------------------------------------------------------------------------------------------------------------------
The `CharacterMovement` component, serving as our character controller / motor, introduces a crucial feature absent in Unity's built-in character controller—the **GroundConstraint**. This feature plays a pivotal role in ensuring the character remains grounded on walk-able surfaces, preventing unintended launches when moving at higher speeds. However, this enhancement necessitates informing the system when the character is permitted to disengage from the ground, for instance, when engaging in activities like climbing, flying, swimming, or jumping.
To achieve this, we leverage the `constrainToGround` property of the `CharacterMovement` component, allowing us to explicitly enable or disable it. Alternatively, the `Character PauseGroundConstraint` method can be employed to temporarily suspend the ground constraint for a specified duration (N seconds),
For example, a basic jump:
Copy
// Temporarily disable the ground constraint to allow the character to leave the ground
PauseGroundConstraint(0.1f);
// Apply a vertical impulse to the character
LaunchCharacter(Vector3.up * 10.0f);
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#events)
Events
---------------------------------------------------------------------------------------------------------------------------------
The `Character` class provides a diverse array of **events** and **event handlers** that can be utilized for responsive actions either within the local context (e.g., within a derived class of `Character`) or externally.
The included events are:
Copy
///
/// Event triggered when a character enter or leaves a PhysicsVolume.
///
public event PhysicsVolumeChangedEventHandler PhysicsVolumeChanged;
///
/// Event triggered when a MovementMode change.
///
public event MovementModeChangedEventHandler MovementModeChanged;
///
/// Event for implementing custom character movement mode.
/// Called if MovementMode is set to Custom.
///
public event CustomMovementModeUpdateEventHandler CustomMovementModeUpdated;
///
/// Event for implementing custom character rotation mode.
/// Called when RotationMode is set to Custom.
///
public event CustomRotationModeUpdateEventHandler CustomRotationModeUpdated;
///
/// Event called before character simulation updates.
/// This 'hook' lets you externally update the character 'state'.
///
public event BeforeSimulationUpdateEventHandler BeforeSimulationUpdated;
///
/// Event called after character simulation updates.
/// This 'hook' lets you externally update the character 'state'.
///
public event AfterSimulationUpdateEventHandler AfterSimulationUpdated;
///
/// Event called when CharacterMovement component is updated (ie. Move call).
/// At this point the character movement has completed and its state is current.
/// This 'hook' lets you externally update the character 'state'.
///
public event CharacterMovementUpdateEventHandler CharacterMovementUpdated;
///
/// Event triggered when characters collides with other during a Move.
/// Can be called multiple times.
///
public event CollidedEventHandler Collided;
///
/// Event triggered when a character finds ground (walkable or non-walkable)
/// as a result of a downcast sweep (eg: FindGround method).
///
public event FoundGroundEventHandler FoundGround;
///
/// Event triggered when a character is falling and finds walkable ground
/// as a result of a downcast sweep (eg: FindGround method).
///
public event LandedEventHandled Landed;
///
/// Event triggered when Character enters crouching state.
///
public event CrouchedEventHandler Crouched;
///
/// Event triggered when character exits crouching state.
///
public event UnCrouchedEventHandler UnCrouched;
///
/// Event triggered when character jumps.
///
public event JumpedEventHandler Jumped;
///
/// Triggered when Character reaches jump apex (eg: change in vertical speed
/// from positive to negative).
/// Only triggered if notifyJumpApex == true.
///
public event ReachedJumpApexEventHandler ReachedJumpApex;
And its corresponding virtual methods that raises the events are:
Copy
///
/// Called when this Character's PhysicsVolume has been changed.
///
protected virtual void OnPhysicsVolumeChanged(PhysicsVolume newPhysicsVolume)
///
/// Called after MovementMode has changed.
/// Does special handling for starting certain modes, eg:
/// enable / disable ground constraint, etc.
/// If overridden, base method MUST be called.
///
protected virtual void OnMovementModeChanged(MovementMode prevMovementMode, int prevCustomMode)
///
/// Event for implementing custom character movement mode.
/// Called if MovementMode is set to Custom.
/// Derived Character classes should override CustomMovementMode method instead.
///
protected virtual void OnCustomMovementMode(float deltaTime)
///
/// Event for implementing custom character rotation mode.
/// Called if RotationMode is set to Custom.
/// Derived Character classes should override CustomRotationMode method instead.
///
protected virtual void OnCustomRotationMode(float deltaTime)
///
/// Called at the beginning of the Character Simulation, before current movement mode update.
/// This 'hook' lets you externally update the character 'state'.
///
protected virtual void OnBeforeSimulationUpdate(float deltaTime)
///
/// Called after current movement mode update.
/// This 'hook' lets you externally update the character 'state'.
///
protected virtual void OnAfterSimulationUpdate(float deltaTime)
///
/// Event called when CharacterMovement component is updated (ie. Move call).
/// At this point the character movement has been applied and its state is current.
/// This 'hook' lets you externally update the character 'state'.
///
protected virtual void OnCharacterMovementUpdated(float deltaTime)
///
/// Event triggered when characters collides with other during a CharacterMovement Move call.
/// Can be called multiple times.
///
protected virtual void OnCollided(ref CollisionResult collisionResult)
///
/// Event triggered when a character find ground (walkable or non-walkable)
/// as a result of a downcast sweep (eg: FindGround method).
///
protected virtual void OnFoundGround(ref FindGroundResult foundGround)
///
/// Event triggered when character enter Walking movement mode
/// (ie: isOnWalkableGround AND isConstrainedToGround).
///
protected virtual void OnLanded(Vector3 landingVelocity)
///
/// Called when character crouches.
///
protected virtual void OnCrouched()
///
/// Called when character un crouches.
///
protected virtual void OnUnCrouched()
///
/// Called when a jump has been successfully triggered.
///
protected virtual void OnJumped()
///
/// Called when Character reaches jump apex
/// (eg: change in vertical speed from positive to negative).
/// Only triggered if notifyJumpApex == true.
///
protected virtual void OnReachedJumpApex()
circle-info
`Character`\-derived classes are encouraged to extend the `'On'` methods instead of subscribing to the event for enhanced customization and seamless integration.
circle-exclamation
In order to receive the `ReachedJumpApex` event, it is imperative to set the `notifyJumpApex` property to true beforehand; otherwise, this event will not be triggered.
For example:
Copy
protected override void OnJumped()
{
// Call base method implementation
base.OnJumped();
// Add your code here...
Debug.Log("Jumped!");
// Enable apex notification event
notifyJumpApex = true;
}
protected override void OnReachedJumpApex()
{
// Call base method implementation
base.OnReachedJumpApex();
// Add your code here...
Debug.Log($"Apex reached {GetVelocity():F4}");
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#collisions)
Collisions
-----------------------------------------------------------------------------------------------------------------------------------------
While you have the flexibility to utilize Unity's `OnTriggerXXX` and `OnEnterXXX` events, the `Character` class (just like the Unity built-in cc) encompasses dedicated methods and events specifically designed to manage character collisions detected during its most recent `CharacterMovement.Move` invocation.
Copy
///
/// Event triggered when character collides during a Move.
/// Can be called multiple times.
///
public event CollidedEventHandler Collided;
///
/// Event triggered when character collides during a CharacterMovement Move call.
/// Can be called multiple times.
///
protected virtual void OnCollided(ref CollisionResult collisionResult)
circle-info
`Character`\-derived classes are encouraged to extend the `OnCollided` method rather than subscribing to the `Collided` event for enhanced customization and seamless integration.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#custom-character-class-responding-to-collision-events)
Custom `Character` Class Responding to Collision Events:
Copy
public class PlayerCharacter : Character
{
protected override void OnCollided(ref CollisionResult collisionResult)
{
// Call base method implementation
base.OnCollided(ref collisionResult);
// Handle collision here...
Debug.Log($"Collided with {collisionResult.collider.name}");
}
}
Moreover, you can conveniently access all collisions found during the last movement in an iterative manner, as demonstrated below:
Copy
for (int i = 0, c = characterMovement.GetCollisionCount(); i < c; i++)
{
CollisionResult collisionResult = characterMovement.GetCollisionResult(i);
// Handle collision here...
}
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#listening-to-character-collision-events)
Listening to `Character` Collision Events
Non `Character`\-based classes should subscribe to the `Character` `Collided` event, for example:
Copy
public class OtherClass : MonoBehaviour
{
public Character character;
protected void OnCollided(ref CollisionResult collisionResult)
{
Debug.Log($"Collided with {collisionResult.collider.name}");
}
private void OnEnable()
{
// Subscribe to Character events
character.Collided += OnCollided;
}
private void OnDisable()
{
// Un-subscribe from Character events
character.Collided -= OnCollided;
}
}
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#collision-filtering)
Collision Filtering
In many game scenarios, there is a need to ignore collisions with another character, a specific collider, or even all colliders attached to a rigid body. To address this, the `CharacterMovement` component incorporates a set of functions that allow you to conveniently define your desired interaction.
Copy
///
/// Makes the character's collider (eg: CapsuleCollider) to ignore all collisions
/// vs otherCollider.
/// NOTE: The character can still collide with other during a Move call
/// if otherCollider is in its collisionLayers mask.
///
public void CapsuleIgnoreCollision(Collider otherCollider, bool ignore = true)
///
/// Makes the character to ignore all collisions vs otherCollider.
///
public void IgnoreCollision(Collider otherCollider, bool ignore = true)
///
/// Makes the character to ignore collisions vs all colliders attached
/// to the otherRigidbody.
///
public void IgnoreCollision(Rigidbody otherRigidbody, bool ignore = true)
When finer control is necessary, the `CharacterMovement ColliderFilterCallback` comes into play. This allows you to selectively ignore specific colliders based on your game criteria.
Copy
///
/// Let you define if the character should collide with given collider.
/// Return true to filter (ignore) collider, false otherwise.
///
public ColliderFilterCallback colliderFilterCallback { get; set; }
For example, to ignore collisions against other characters using the `CharacterMovement` component:
Copy
private bool ColliderFilterCallback(Collider collider)
{
// If collider is a character (e.g. using CharacterMovement component)
// ignore collisions with it (e.g. filter it)
if (collider.TryGetComponent(out CharacterMovement _))
return true;
return false;
}
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#physics-interactions)
Physics Interactions
-------------------------------------------------------------------------------------------------------------------------------------------------------------
When enabled, a `Character` can interact with other rigidbodies—pushing or being pushed—and other characters, applying forces, explosion forces, downward forces, etc. These interactions are managed by the `CharacterMovement` component, and by default, the resulting behavior is influenced by the masses of the characters, where larger mass will push others more easily, and vice versa.
This default behavior can be modified using the `CharacterMovement collisionResponseCallback` function. This allows us to adjust the computed collision response impulses in any manner that our game may require.
The callback function prototype is declared as follows:
Copy
///
/// Let you modify the collision response vs dynamic objects,
/// eg: compute resultant impulse and / or application point (CollisionResult.point).
///
public delegate void CollisionResponseCallback(ref CollisionResult inCollisionResult, ref Vector3 characterImpulse, ref Vector3 otherImpulse);
Where '`impulses`' represent the computed resulting collision response impulses, and this can be modified as needed.
Additionally, the `Character` class includes a set of functions to externally influence the character. These functions are similar to Unity's `Rigidbody` functions, such as `AddForce`, `AddExplosionForce`, and a custom one called `LaunchCharacter`.
Copy
///
/// Adds a force to the Character.
/// This forces will be accumulated and applied during Move method call.
///
public void AddForce(Vector3 force, ForceMode forceMode = ForceMode.Force)
///
/// Applies a force to a rigidbody that simulates explosion effects.
/// The explosion is modeled as a sphere with a certain centre position and radius in world space;
/// normally, anything outside the sphere is not affected by the explosion and the force decreases in proportion to distance from the centre.
/// However, if a value of zero is passed for the radius then the full force will be applied regardless of how far the centre is from the rigidbody.
///
public void AddExplosionForce(float forceMagnitude, Vector3 origin, float explosionRadius,
ForceMode forceMode = ForceMode.Force)
///
/// Set a pending launch velocity on the Character. This velocity will be processed
/// the next Move call.
/// If overrideVerticalVelocity is true replace the vertical component of the Character's velocity instead of adding to it.
/// If overrideLateralVelocity is true replace the XY part of the Character's velocity instead of adding to it.
///
public void LaunchCharacter(Vector3 launchVelocity, bool overrideVerticalVelocity = false,
bool overrideLateralVelocity = false)
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#animating-a-character)
Animating a Character
---------------------------------------------------------------------------------------------------------------------------------------------------------------
When animating a character, you should query the character's state and/or subscribe to its numerous events, feeding this information to your `AnimationController` parameters to ensure your animation stays perfectly in sync with the character's state, such as whether it is grounded, falling, jumping, etc.
> ECM2 does not require the use of animation or any specific animation techniques. You have the freedom to animate your characters using 'plain Unity code' or your preferred method.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#querying-character-state)
Querying Character State
The `Character` class provides an extensive array of methods, events, and delegates that you can leverage to access the character's information, including `GetPosition`, `GetRotation`, GetVelocity, `IsWalking`, `IsFalling`, `IsOnWalkableGround`, etc. This should be utilized to maintain seamless synchronization in your animations.
In addition to the information provided by the `Character` class, you can access further details through the `CharacterMovement` component. This includes ground-related information, retrieval and adjustment of capsule collider dimensions, access to collision detection functions, and even the ability to compute a new set of ground-related details (e.g., is walk-able, is a step, distance to the ground, etc.).
The following example illustrates how to animate the '**UnityCharacter**' using the information provided by the `Character` to feed parameters into its `Animator`.
Copy
private void Update()
{
float deltaTime = Time.deltaTime;
// Get Character animator
Animator animator = _character.GetAnimator();
// Compute input move vector in local space
Vector3 move = transform.InverseTransformDirection(_character.GetMovementDirection());
// Update the animator parameters
float forwardAmount = _character.useRootMotion && _character.GetRootMotionController()
? move.z
: Mathf.InverseLerp(0.0f, _character.GetMaxSpeed(), _character.GetSpeed());
animator.SetFloat(Forward, forwardAmount, 0.1f, deltaTime);
animator.SetFloat(Turn, Mathf.Atan2(move.x, move.z), 0.1f, deltaTime);
animator.SetBool(Ground, _character.IsGrounded());
animator.SetBool(Crouch, _character.IsCrouched());
if (_character.IsFalling())
animator.SetFloat(Jump, _character.GetVelocity().y, 0.1f, deltaTime);
// Calculate which leg is behind, so as to leave that leg trailing in the jump animation
// (This code is reliant on the specific run cycle offset in our animations,
// and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)
float runCycle = Mathf.Repeat(animator.GetCurrentAnimatorStateInfo(0).normalizedTime + 0.2f, 1.0f);
float jumpLeg = (runCycle < 0.5f ? 1.0f : -1.0f) * forwardAmount;
if (_character.IsGrounded())
animator.SetFloat(JumpLeg, jumpLeg);
}
As you can see, it updates the `Animator` parameters based on the information provided by the `Character` component.
###
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/character#utilizing-root-motion)
Utilizing Root Motion
Root motion refers to motion integrated directly into the animation, where the animation itself dictates how far an object moves rather than relying on code.
To incorporate root motion in a `Character`\-derived class, follow these steps:
1. Add the `RootMotionController` component to your model's `GameObject`. This `RootMotionController` is responsible for providing the animation's velocity, rotation, etc., to the `Character`.
2. Enable the `useRootMotion` property in the `Character`. This property can be toggled as needed.
Once a character is moved using root motion, the animation assumes complete control over the character's movement. This replaces all procedural movement, rendering properties such as `maxWalkSpeed`, `maxFallSpeed`, etc., irrelevant, as the character is entirely driven by the animation.
Worth noting, the character's ground constraint still applies when root motion is enabled. This implies that any vertical movement in your root motion-based animation won't function unless you explicitly disable this constraint. In such cases, it's advisable to assign the flying movement mode, as it automatically disables the ground constraint and allows for full vertical movement.
circle-info
To enable vertical root motion movement, the character's movement mode must be set to **Flying**.
[PreviousComponentschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components)
[NextNavMesh Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/components/navmesh-character)
Last updated 2 years ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---
# General | Easy Character Movement 2
**Easy Character Movement 2 (ECM2)** is a comprehensive set of components designed to facilitate smooth character movement in both 3D and 2D (specifically 2.5D, as it remains 3D based) environments.
The primary objective of ECM2 is to simplify the process of maneuvering game characters, empowering developers to construct game mechanics effortlessly on this foundation.
At the core of ECM2 is the **CharacterMovement** component, a robust and feature-rich fully kinematic character controller (aka motor). This component serves as a direct replacement for Unity's built-in character controller, employing a similar operational methodology (i.e. `Move` method) but with many features and advantages over it.
The cornerstone of the ECM2 system is the `Character` class. This class utilizes the `CharacterMovement` component as its character controller / motor, incorporating common modes of movement for characters, such as walking, falling, flying, swimming or any custom mode you may create. It serves as a highly customizable foundation for all your game avatars, whether they are controlled by players or AI.
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual#features)
Features
--------------------------------------------------------------------------------------------------------
* `CharacterMovement` a **AAA Kinematic Character Controller** .
* **Robust Ground Detection:**
* Achieve realistic surface interaction with a robust ground detection system based on real surface normals.
* **Slope Limit Override:**
* Define walk-able areas on a per-face or per-object basis, ensuring precise control over character movement.
* **Configurable Walk-able Area:**
* Customize the character's 'feet' radius with the `perchOffset` feature, enhancing configurability.
* **Capsule-Based with Flat Base:**
* Opt for a capsule-based design with a Flat Base for ground checks to prevent characters from slowly sliding off ledges.
* **Ground Constraint:**
* Safeguard characters from being launched off ramps with a ground constraint feature.
* **Configurable Plane Constraint:**
* Control movement along locked axes with the Configurable Plane Constraint, enhancing directional precision.
* **Auto-Stepping with Momentum Preservation:**
* Enable auto-stepping that seamlessly preserves the character's momentum, including stride effects.
* **Gravity and Up Vector Customization:**
* Achieve Mario Galaxy-like effects with user-defined gravity and up vector options.
* **Physics Interactions:**
* Experience realistic physics interactions for immersive character movements.
* **Character vs Character Interactions:**
* Engage in dynamic character vs character interactions within the virtual environment.
* **Transparent Platform Support:**
* Enjoy first-class, transparent platform support for animated, scripted, or physics-based platforms without additional steps.
* **Collision and Grounding Events:**
* Receive comprehensive collision and grounding events for enhanced control and feedback.
* **Network-Friendly Design:**
* Retain full control over update and simulation time-step, ensuring network-friendly performance.
* **Friction-Based Movement Options:**
* Configure friction-based movement, including water buoyancy, for diverse environmental interactions.
* **Root Motion Support:**
* Incorporate root motion support for enhanced character animations and realism.
* **Designed for Extensibility:**
* Developed with extensibility in mind, allowing for use as-is, or complete extension through **inheritance** or **composition**.
* **Easy Integration into Existing Projects:**
* Seamlessly integrate into existing Unity projects with minimal effort.
* **Well-Commented Source Code:**
* Access fully commented C# source code for clarity, readability, and ease of extension.
* **Garbage-Collector Friendly:**
* Optimize performance with a software design that minimizes garbage collector allocations for a smoother experience.
[PreviousEasy Character Movement 2chevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2)
[NextPackage Contentschevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/package-contents)
Last updated 2 years ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---
# Creating a Character | Easy Character Movement 2
[hashtag](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough#creating-a-character)
Creating a Character
--------------------------------------------------------------------------------------------------------------------------------
* Right-click on the hierarchy window to open the creation dialog and select the **Character** option from the **ECM2** category.

* It will create an empty character (no visual representation) named **Character.**

Newly created Character
circle-info
Make sure its origin is set to (0, 0, 0) as this will save you troubles when parenting your model.
* Parent your model to this newly `Character` `GameObject`. For this example, we'll use the included **ECM2\_Capsule** model.

Character's model
* In the `CharacterMovement` component, adjust your **radius** and **height** values (this will automatically configure your character’s capsule collider) to better fit your character’s model.

CharacterMovement component
At this point, we have a fully configured and ready character; however, we are unable to move or control it. We will address and resolve this in the following section.
[PreviousExampleschevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/user-manual/general/examples)
[NextControlling a Characterchevron-right](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/controlling-a-character)
Last updated 2 years ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---
# Customer Support | Easy Character Movement 2
If you have any comments, need assistance, or have a feature you would like to see added, please don't hesitate to contact me at **ogracian@gmail.com**. I'll be happy to assist you.
circle-exclamation
Please make sure to **include the invoice number** you received with your purchase when requesting support via email.
[PreviousCinemachinechevron-left](https://oscar-gracian.gitbook.io/easy-character-movement-2/walkthrough/cinemachine)
Last updated 2 years ago
This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies)
.
close
AcceptReject
---