Movement Package - EasterEggProductions/adventure-mode-godot GitHub Wiki
MovementPackage is a resource that is to be treated as an abstract class, and extended into the usable movement packages. Note that this and resources that extend it are classes, and you will need to make instances of them in the editor. This point is expanded upon in the mvpk_combat section.
This resource has 3 properties:
- Name - a descriptive name of the package.
- anim_tree - A reference to the root animation tree that is used for this package.
- anim_library - A reference to the animation library that this movement package is to use. This is not actually used at this time, and will likely be replaced with a more robust dependency system. The intent here is for the movement package to be able to make sure the required animations are on the Actor it is applied to.
- pack_type - This can be overridden to allow for various special checks. This was done because Godot does not support checking custom class names.
- transfer_situation_check - Every frame the actor iterates through every package it has, passing itself in as _thrall, and this function returns a boolean, true if this package should take control, and false otherwise.
- release_situation_check - Every frame the actor calls this on it's current package, and it returns true if the current package should not be in charge. It no other package says it should be in charge, the Actor defaults to the package at index 0.
- move_thrall - This is the actual update method, taking in the Actor as _thrall, and the delta time.
func move_thrall(thrall : Actor, delta : float):
var old_vel = thrall.velocity
# Get the motion delta.
thrall.velocity = ((thrall.animation_tree.get_root_motion_rotation_accumulator().inverse() * thrall.get_quaternion()) * thrall.animation_tree.get_root_motion_position() / delta) * 1
# Add the gravity.
if not thrall.is_on_floor():
thrall.velocity = old_vel
thrall.velocity.y -= gravity * delta
thrall.quaternion = thrall.quaternion * ((thrall.animation_tree.get_root_motion_rotation() / delta) * 10)
# Actually move thrall
thrall.move_and_slide()For another example, look at vmpk_glide.gd in whole,
extends MovementPackage
class_name mvpk_glide
var termnalVel = -1.0
func pack_type() -> String:
return "mvpk_glide" # godot does not support getting custom class names
func transfer_situation_check(thrall : Actor) -> bool:
if thrall.is_on_floor() == false:
if Input.is_action_just_pressed("p1_jump"):
thrall.combat_mode = false
return true
return false
func release_situation_check(thrall : Actor) -> bool:
if thrall.is_on_floor() or Input.is_action_just_pressed("p1_crouch"):
return true
return false
func move_thrall(thrall : Actor, delta : float):
var old_fallVel = thrall.velocity.y
# Get the motion delta.
thrall.velocity = ((thrall.animation_tree.get_root_motion_rotation_accumulator().inverse() * thrall.get_quaternion()) * thrall.animation_tree.get_root_motion_position() / delta) * 2
# if gliding we know we arent on the ground
thrall.velocity.y = old_fallVel
thrall.velocity.y -= 1 * delta
thrall.velocity.y = clampf(thrall.velocity.y, termnalVel, -(termnalVel * 2))
thrall.quaternion = thrall.quaternion * ((thrall.animation_tree.get_root_motion_rotation() / delta) * 10)
thrall.move_and_slide()This package checks if we are in the air and press jump to transfer in, and if we click the crouch button or touch the ground to transfer out. We could modify it to only transfer in if we have enough height (like Breath of the Wild), by adding a raycast downward in the transfer_situation_check, and seeing if we are high enough to begin gliding.
A simple package with no enter or exit check logic. If this is set as the first package in an Actor's array, it will use this animation set as it's default.
This package implements some basic logic to control a Breath of the Wild style gliding system. If you are in the air and tap jump, you will start gliding. If you are gliding and touch the ground or crouch, you will exit this package.
This package activates if you are facing a wall and try to jump onto it. It uses a raycast to detect this, and so may be useful as an example of that.
This is a slightly outdated package meant to implement swimming. It accesses the actor's node, looking for a child called 'water_cast' which is a shape cast 3d used to detect if it is within or touching a collision shape of a particular name ("water" by default). It then switches to this package if it is within that zone. This package is outdated, and should not be used. It's referencing of a child of the actor that is not universal is bad practice, and this will be updated in the future.
This package is meant to hold the entire moveset of a weapon. It is under development but right now it switches to this package when the weapon is in hand, and leaves when the weapon is out of hand. This is the package that has the most instances in the project. with w_1H-sword_moveset.tres and w_claymore_moveset.tres being a movement pack for a one handed sword, and claymore respectively. This is an example of how multiple instances of the resource can be used.
Movement packages are a useful system, but they are pushing the animation handling tools of Godot to their limit. In Godot, animation trees can be nested and cross referenced. For example a Blend Tree can have as a node within it, a state machine. This is leveraged heavily in the existing animation trees, but some errors seem to exist in how those sub trees are initialized or started, resulting in some not playing during gameplay.
Currently there is no way for an animation tree to send a signal that it is done, or that it should switch to a different movement package. This would be useful for sheathing a sword, and switching back to the default walk package when that is done, or sheathing one weapon to draw another, instead of instantly switching to the other weapon.
Currently there is no provision for swappable sub components within a moveset. For example allowing an ash of war style system, or altering offhand attacks at runtime.