-
Notifications
You must be signed in to change notification settings - Fork 6
Setting up your first character
This page will go over everything you need to setup a character that uses motion matching. Note that all of this may be subject to change in upcomming releases.
The character capsule is the main node that controls motion matching. It is resposible for compiling all the data needed to run a motion matching query and select an animation. The first step is to create a new scene of type MMCharacter
.
This will be your character scene!
You should also add a node to hold the logic that will control your character. Were are some examples for AI vs Player characters. Tip: by setting target_velocity
, the MMCharacter
will interpolate its velocity to reach the target, based off its halflife
value. For better results, your target velocity should be similar to the velocities of your animations: slower velocities will generate trajectories that will more easily match against slower animations!
extends Node
@export var max_speed = 3.0
@export var jump_speed = 3.0
@export var character: MMCharacter
@export var camera_pivot: Node3D
func _physics_process(delta: float) -> void:
var stick_input = Input.get_vector("left", "right", "down", "up")
var stick_input_world = Vector3(-stick_input.x, 0, stick_input.y)
var desired_velocity = (stick_input_world * max_speed).rotated(Vector3.UP, camera_pivot.rotation.y)
character.target_velocity = desired_velocity
func _input(event: InputEvent) -> void:
if event.is_action_pressed("jump") and character.is_on_floor():
character.velocity += Vector3.UP * jump_speed
extends Node3D
@export var character : MMCharacter
@export var nav_agent : NavigationAgent3D
@export var speed = 3.0
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_accept"):
var random_pos: = Vector3.ZERO
random_pos.x = randf_range(-5.0, 5.0)
random_pos.z = randf_range(-5.0, 5.0)
nav_agent.target_position = random_pos # This position controls player movement
print(random_pos)
func _physics_process(delta: float) -> void:
var next_destination = nav_agent.get_next_path_position()
var delta_pos_next = next_destination - global_position
var distance_remaining = nav_agent.get_final_position().distance_to(global_position)
character.target_velocity = delta_pos_next
if distance_remaining > speed:
character.target_velocity = delta_pos_next.normalized() * speed
nav_agent.velocity = character.velocity
The next step is to import you character mesh, with all the animations that go with it. You'll need to save all your animations as separate files.
You can then add it to your character scene, and fill the character's properties with the the skeleton and animation player.
This skeleton will use root motion to move around, the root motion track must therefore be specified on the animation player:
The last step is to setup your motion matching library! This is the resource that holds all your libraries, as well as the motion matching features that will be used to select animation.
You should first create a MMAnimationLibrary
You can now use the animation player's editor to add all your animations to your MMAnimationLibrary
These features define how animations from you MMAnimationLibrary are selected. Let's start with a MMTrajectory
, that is used to select animation based on your character's future trajectory.
- Past/Future delta time: time used to sample the trajectory
- Past/Future frames: number of trajectory points used for selection
You should also set your sampling rate to something sensible to your dataset size. Lower sampling crates will create more animation points to select from, at the cost of selection performance.
Baking is the process of computing all the features for your animations, so that they can be use at runtime for selection. To bake your animation library, select your MMCharacter node. The Motion Matching editor should show up:
For motion matching to work well, your character's generated trajectories should be similar to those computed from your features. This might require some tuning, but here are some tips:
- The trajectory's delta time and point count should be identical to the one used on your feature (this is planned to be automated away soon).
You can press the bake button to compute your features. You should be able to see them on your animation library
You can also use this editor to visualize the features computed from your animations!