Skip to content

Commit

Permalink
API Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
GuilhermeGSousa committed Sep 4, 2024
1 parent cef2f5d commit 51b623f
Show file tree
Hide file tree
Showing 46 changed files with 873 additions and 405 deletions.
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@

![](https://github.com/GuilhermeGSousa/godot-motion-matching/blob/master/motion_matching_demo.gif)

A very simple motion matching implementation example in Godot 4.3, that allows for both strafe and non strafe movement, implemented following [Dan Holden's article](https://www.theorangeduck.com/page/code-vs-data-driven-displacement).
A motion matching implementation in Godot 4.3, implemented following [Dan Holden's article](https://www.theorangeduck.com/page/code-vs-data-driven-displacement).

### Implementation
- `MMAnimationLibrary`: a **Resource** that holds not only a list of animations, but also all the extracted features data for every frame, as well as their statistics data.
- `MMFeature`: an **Resource** that describes data used to match movement to a specific animation frame. You can find implementation examples `src/features`.
- `MMAnimationPlayer`: an animation player that supports inertialization to transition between animations. Its it also used to make queries to a `MMAnimationLibrary`.
- `MMController`: A simple 3rd person controller, that also generates trajectories used for motion matching queries.
- `MotionMatcher`: Coordinates fetching query information from `MMController` and transitioning to the resulting animation.
### Wiki
[You can find this repo's wiki here!](https://github.com/GuilhermeGSousa/godot-motion-matching/wiki)


### Todo
- Implement better debugging tools
- Use a KD Tree to accelerate queries
- Finish implementing `MMBoneDataFeature`
- Get more complete animation data
- Support jumping, crouching, and parkour movements
### Features
You'll find on this repo:
- A plugin that allow you to run motion matching queries on an animation dataset!
- A `CharacterBody3D` implementing a simple movement logic.
- Trajectory generation, including collisions and environmental checks.
- An editor to bake and visualize motion matching features.
- Blending nodes to qllow you to smoothly transition when switching animations.

### Credits

Expand Down
2 changes: 2 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ env = SConscript("godot-cpp/SConstruct")
# tweak this if you want to use different folders, or more folders, to store your source code in.
env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp")
sources += Glob("src/editor/*.cpp")
sources += Glob("src/features/*.cpp")
sources += Glob("src/math/*.cpp")
sources += Glob("src/synchronizers/*.cpp")

if env["platform"] == "macos":
library = env.SharedLibrary(
Expand Down
11 changes: 0 additions & 11 deletions addons/motion_matching/MMAnimationLibraryEditor.gd

This file was deleted.

23 changes: 0 additions & 23 deletions addons/motion_matching/MMAnimationLibraryEditor.tscn

This file was deleted.

41 changes: 0 additions & 41 deletions addons/motion_matching/MMPlugin.gd

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7 changes: 0 additions & 7 deletions addons/motion_matching/plugin.cfg

This file was deleted.

49 changes: 46 additions & 3 deletions demo/main.tscn
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
[gd_scene load_steps=9 format=3 uid="uid://dxkchm2v0ynla"]
[gd_scene load_steps=12 format=3 uid="uid://dxkchm2v0ynla"]

[ext_resource type="PackedScene" uid="uid://cjhit7pg3fwuo" path="res://scenes/debug_table.tscn" id="1_cpbqa"]
[ext_resource type="Texture2D" uid="uid://bubooafum5q7l" path="res://textures/grid_texture.png" id="1_yaac5"]
[ext_resource type="PackedScene" uid="uid://1io8uso2bop2" path="res://scenes/rin.tscn" id="2_ady0f"]
[ext_resource type="PackedScene" uid="uid://b542pai5xpeq3" path="res://scenes/camera_pivot.tscn" id="4_xdhai"]
[ext_resource type="Script" path="res://scripts/trajectory_debug_draw.gd" id="5_gaa5p"]

[sub_resource type="Environment" id="Environment_b0k67"]
background_energy_multiplier = 7.75
Expand All @@ -20,12 +22,15 @@ material = SubResource("StandardMaterial3D_vcm8j")
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_cgbp0"]
data = PackedVector3Array(-0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5)

[sub_resource type="MMClampSynchronizer" id="MMClampSynchronizer_70fpb"]
clamp_distance = 0.0

[node name="main" type="Node3D"]

[node name="DebugTable" parent="." node_paths=PackedStringArray("motion_matcher") instance=ExtResource("1_cpbqa")]
offset_right = -167.0
offset_bottom = -490.0
motion_matcher = NodePath("../Rin/MotionMatcher")
motion_matcher = NodePath("../Rin")

[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -0.676876, 0.736097, 0, -0.736097, -0.676876, 0, 0, 0)
Expand Down Expand Up @@ -67,6 +72,44 @@ transform = Transform3D(11.0225, 0, 0, 0, 3.04705, 0, 0, 0, 1, 0, -0.467445, 0)
shape = SubResource("ConcavePolygonShape3D_cgbp0")

[node name="Rin" parent="." instance=ExtResource("2_ady0f")]
synchronizer = SubResource("MMClampSynchronizer_70fpb")
trajectory_point_count = 5
camera_pivot = NodePath("../CameraPivot")

[node name="Skeleton3D" parent="Rin/rin/Armature" index="0"]
bones/0/position = Vector3(0.129963, 0, 0.0355273)
bones/0/rotation = Quaternion(0, 0.911942, 0, 0.410319)
bones/1/rotation = Quaternion(0.478197, 0.518828, 0.461072, 0.538105)
bones/2/rotation = Quaternion(0.677403, 0.735577, 0.00678377, -0.00218327)
bones/3/rotation = Quaternion(-0.00134251, 0.00281955, -0.0182867, 0.999828)
bones/4/rotation = Quaternion(-0.00134251, 0.00281882, -0.0182869, 0.999828)
bones/5/rotation = Quaternion(-0.00106083, 0.00211265, -0.0137159, 0.999903)
bones/6/rotation = Quaternion(-0.753812, -0.0315326, -0.0130199, 0.656205)
bones/7/rotation = Quaternion(-0.862301, -0.103433, 0.0876848, 0.487904)
bones/8/rotation = Quaternion(-0.120382, -0.00813427, -0.394171, 0.911082)
bones/9/rotation = Quaternion(0.00210261, -0.00261865, -0.0267671, 0.999636)
bones/49/rotation = Quaternion(0.00191046, -0.00414369, -0.138382, 0.990368)
bones/50/rotation = Quaternion(0.00230286, -0.0039394, -0.0419292, 0.99911)
bones/51/rotation = Quaternion(0.677856, 0.734585, 0.0285927, 0.00891637)
bones/213/rotation = Quaternion(-0.00588888, 0.676628, 0.735735, -0.0288667)
bones/214/rotation = Quaternion(-0.860615, 0.0667581, -0.146371, 0.483178)
bones/215/rotation = Quaternion(-0.0877294, -0.0129264, 0.450692, 0.888264)
bones/216/rotation = Quaternion(0.00846243, 0.0462203, -0.00894549, 0.998855)
bones/256/rotation = Quaternion(0.954014, -0.299763, 7.39757e-08, -1.16333e-07)
bones/272/rotation = Quaternion(0.0498225, -0.0265959, 0.759554, 0.647987)
bones/273/rotation = Quaternion(0.00712901, 0.0165768, 0.120527, 0.992546)
bones/274/rotation = Quaternion(-0.0602353, 0.175422, -0.615958, 0.765634)
bones/281/rotation = Quaternion(0.755141, -0.653877, 0.0451307, 0.0130335)
bones/282/rotation = Quaternion(-0.00462105, 0.0392285, -0.174953, 0.983784)
bones/283/rotation = Quaternion(-0.117743, 0.0610783, 0.611722, 0.779873)

[node name="CameraPivot" parent="." instance=ExtResource("4_xdhai")]

[node name="DebugDrawTrajectory" type="Node" parent="." node_paths=PackedStringArray("character", "controller", "anim_player")]
script = ExtResource("5_gaa5p")
character = NodePath("../Rin/rin/Armature/Skeleton3D")
controller = NodePath("../Rin")
anim_player = NodePath("../Rin/MMAnimationPlayer")

[editable path="Rin"]
[editable path="Rin/Character Entity/rin"]
[editable path="Rin/rin"]
4 changes: 0 additions & 4 deletions demo/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.3", "Forward Plus")
config/icon="res://icon.svg"

[editor_plugins]

enabled=PackedStringArray("res://addons/motion_matching/plugin.cfg")

[filesystem]

import/blend/blender_path="blender"
Expand Down
7 changes: 7 additions & 0 deletions demo/scenes/camera_pivot.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[gd_scene format=3 uid="uid://b542pai5xpeq3"]

[node name="CameraPivot" type="Node3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.40566, 0)

[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, -7.21807)
52 changes: 10 additions & 42 deletions demo/scenes/rin.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[gd_scene load_steps=7 format=3 uid="uid://1io8uso2bop2"]
[gd_scene load_steps=6 format=3 uid="uid://1io8uso2bop2"]

[ext_resource type="Script" path="res://scripts/trajectory_debug_draw.gd" id="1_embri"]
[ext_resource type="PackedScene" uid="uid://bjpmux7mfthoa" path="res://animation/rin.fbx" id="2_0oumo"]
[ext_resource type="MMAnimationLibrary" uid="uid://ci0xd77t1swxb" path="res://animation/rin_anim_lib.tres" id="3_j41h7"]
[ext_resource type="Script" path="res://scripts/loop_animation.gd" id="4_a1ab8"]
Expand All @@ -9,47 +8,22 @@

[sub_resource type="CapsuleMesh" id="CapsuleMesh_e64fr"]

[node name="Rin" type="Node3D"]

[node name="CameraPivot" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.40566, 0)

[node name="Camera3D" type="Camera3D" parent="CameraPivot"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, -7.21807)

[node name="DebugDraw" type="Node" parent="." node_paths=PackedStringArray("character", "controller", "matcher", "anim_player")]
script = ExtResource("1_embri")
character = NodePath("../Character Entity")
controller = NodePath("../Simulation Entity")
matcher = NodePath("../MotionMatcher")
anim_player = NodePath("../MMAnimationPlayer")

[node name="Simulation Entity" type="MMController" parent="."]
camera_pivot = NodePath("../CameraPivot")
trajectory_point_count = 20
simulation_samples_per_second = 2.0
[node name="Simulation Entity" type="MMController"]
skeleton_path = NodePath("rin/Armature/Skeleton3D")
animation_player_path = NodePath("MMAnimationPlayer")
max_speed = 3.0

[node name="CollisionShape3D" type="CollisionShape3D" parent="Simulation Entity"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_nhkn4")

[node name="MeshInstance3D" type="MeshInstance3D" parent="Simulation Entity/CollisionShape3D"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="CollisionShape3D"]
visible = false
mesh = SubResource("CapsuleMesh_e64fr")

[node name="Character Entity" type="CharacterBody3D" parent="."]
collision_layer = 0
collision_mask = 0
[node name="rin" parent="." instance=ExtResource("2_0oumo")]

[node name="CollisionShape3D" type="CollisionShape3D" parent="Character Entity"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_nhkn4")
disabled = true

[node name="rin" parent="Character Entity" instance=ExtResource("2_0oumo")]

[node name="Skeleton3D" parent="Character Entity/rin/Armature" index="0"]
[node name="Skeleton3D" parent="rin/Armature" index="0"]
bones/1/position = Vector3(0, 1.01445, -3.02878e-15)
bones/1/scale = Vector3(1, 1, 1)
bones/2/position = Vector3(0.0410021, 1.16488e-14, 1.79225e-09)
Expand Down Expand Up @@ -567,21 +541,15 @@ bones/296/position = Vector3(0.0011635, 0.0935117, 5.08575e-11)
bones/296/rotation = Quaternion(0, 1, 6.23271e-17, 7.54979e-08)

[node name="MMAnimationPlayer" type="MMAnimationPlayer" parent="."]
root_motion_character_path = NodePath("../Character Entity")
root_node = NodePath("../Character Entity/rin")
root_node = NodePath("../rin")
root_motion_track = NodePath("Armature/Skeleton3D:root")
callback_mode_process = 0
libraries = {
"rin_anim_lib": ExtResource("3_j41h7")
}
script = ExtResource("4_a1ab8")

[node name="MotionMatcher" type="MotionMatcher" parent="."]
controller_path = NodePath("../Simulation Entity")
character_path = NodePath("../Character Entity")
animation_player_path = NodePath("../MMAnimationPlayer")

[node name="RootMotionView" type="RootMotionView" parent="."]
animation_path = NodePath("../MMAnimationPlayer")

[editable path="Character Entity/rin"]
[editable path="rin"]
25 changes: 9 additions & 16 deletions demo/scenes/rin_simple.tscn
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
[gd_scene load_steps=5 format=3 uid="uid://dhalyu0huf050"]
[gd_scene load_steps=4 format=3 uid="uid://dhalyu0huf050"]

[ext_resource type="PackedScene" uid="uid://bjpmux7mfthoa" path="res://animation/rin.fbx" id="1_l001c"]
[ext_resource type="MMAnimationLibrary" uid="uid://ci0xd77t1swxb" path="res://animation/rin_anim_lib.tres" id="2_y4tkp"]
[ext_resource type="Script" path="res://scripts/loop_animation.gd" id="3_22m82"]

[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_nhkn4"]

[node name="Rin Simple" type="Node3D"]

[node name="Character Entity" type="CharacterBody3D" parent="."]
collision_layer = 0
collision_mask = 0

[node name="CollisionShape3D" type="CollisionShape3D" parent="Character Entity"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_nhkn4")
disabled = true
[node name="rin" parent="." instance=ExtResource("1_l001c")]

[node name="rin" parent="Character Entity" instance=ExtResource("1_l001c")]

[node name="Skeleton3D" parent="Character Entity/rin/Armature" index="0"]
[node name="Skeleton3D" parent="rin/Armature" index="0"]
bones/1/position = Vector3(0, 1.01445, -3.02878e-15)
bones/1/scale = Vector3(1, 1, 1)
bones/2/position = Vector3(0.0410021, 1.16488e-14, 1.79225e-09)
Expand Down Expand Up @@ -537,7 +526,7 @@ bones/296/position = Vector3(0.0011635, 0.0935117, 5.08575e-11)
bones/296/rotation = Quaternion(0, 1, 6.23271e-17, 7.54979e-08)

[node name="MMAnimationPlayer" type="MMAnimationPlayer" parent="."]
root_node = NodePath("../Character Entity/rin")
root_node = NodePath("../rin")
root_motion_track = NodePath("Armature/Skeleton3D:root")
callback_mode_process = 0
libraries = {
Expand All @@ -548,4 +537,8 @@ script = ExtResource("3_22m82")
[node name="RootMotionView" type="RootMotionView" parent="."]
animation_path = NodePath("../MMAnimationPlayer")

[editable path="Character Entity/rin"]
[node name="RootMotion" type="RootMotion" parent="."]
animation_mixer_path = NodePath("../MMAnimationPlayer")
root_path = NodePath("../rin")

[editable path="rin"]
2 changes: 1 addition & 1 deletion demo/scripts/debug_table.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extends Control

@export var motion_matcher : MotionMatcher
@export var motion_matcher : MMController
@export var title_scene : PackedScene
@export var cell_scene : PackedScene

Expand Down
4 changes: 3 additions & 1 deletion demo/scripts/loop_animation.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ func _input(event: InputEvent) -> void:
func _next() -> void:
var anim_list = get_animation_list()
print(anim_list[current_anim])
inertialize_transition(anim_list[current_anim], 0.1)
play(anim_list[current_anim])
seek(0.1)
#inertialize_transition(anim_list[current_anim], 0.1)
current_anim += 1
if current_anim >= len(anim_list):
current_anim = 0
5 changes: 2 additions & 3 deletions demo/scripts/trajectory_debug_draw.gd
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
extends Node

@export var character : CharacterBody3D
@export var character : Node3D
@export var controller : MMController
@export var matcher : MotionMatcher
@export var anim_player : MMAnimationPlayer

func _ready():
matcher.on_query_result.connect(_on_query_result)
controller.on_query_result.connect(_on_query_result)

func _physics_process(delta: float) -> void:
DebugDraw3D.draw_position(character.transform, Color.FOREST_GREEN)
Expand Down
Loading

0 comments on commit 51b623f

Please sign in to comment.