Skip to content

Setting up your first character

Guilherme Sousa edited this page Oct 25, 2024 · 5 revisions

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.

Character Capsule

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. image This will be your character scene!

Character Movement

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!

Player Movement

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

AI Movement

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

Character Skeleton

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. image

This skeleton will use root motion to move around, the root motion track must therefore be specified on the animation player: image

Motion Matching Library

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 image

You can now use the animation player's editor to add all your animations to your MMAnimationLibrary image image

Setting up Motion Matching Features

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. image

Baking Motion Matching Features

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: image

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). image

You can press the bake button to compute your features. You should be able to see them on your animation library image

You can also use this editor to visualize the features computed from your animations! image