Skip to content

Commit

Permalink
Orientation Warping Fix | Mantle System Base
Browse files Browse the repository at this point in the history
  • Loading branch information
ywmaa committed Jan 19, 2024
1 parent cf4ae30 commit c074df4
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 158 deletions.
128 changes: 67 additions & 61 deletions AMSG_Examples/Character/mixamo_character.tscn

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions AMSG_Examples/Player/Player.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -334,18 +334,18 @@ transform = Transform3D(-0.776967, -0.466155, -0.423109, -0.0355596, -0.638521,
transform = Transform3D(-0.303158, -0.739914, -0.600519, 0.0355596, -0.638519, 0.768784, -0.952277, 0.211709, 0.219883, -0.0315955, 0.104958, -0.310727)

[node name="LeftFootAttachment" parent="Armature/Skeleton3D/PoseWarping" index="2"]
transform = Transform3D(-0.776963, -0.466153, -0.423106, -0.0355594, -0.638517, 0.768778, -0.628532, 0.612361, 0.479531, 0.0833106, 0.111479, 0.361883)
transform = Transform3D(-0.776963, -0.466153, -0.423106, -0.0355594, -0.638517, 0.768778, -0.628532, 0.612361, 0.479531, 0.0840908, 0.111218, 0.361871)
external_skeleton = NodePath("/root/@EditorNode@17140/@Panel@13/@VBoxContainer@14/@HSplitContainer@17/@HSplitContainer@25/@HSplitContainer@33/@VBoxContainer@34/@VSplitContainer@36/@VSplitContainer@62/@VBoxContainer@63/@PanelContainer@110/MainScreen/@CanvasItemEditor@9462/@VSplitContainer@9281/@HSplitContainer@9283/@HSplitContainer@9285/@Control@9286/@SubViewportContainer@9287/@SubViewport@9288/Character/Armature/Skeleton3D")

[node name="RightFootAttachment" parent="Armature/Skeleton3D/PoseWarping" index="3"]
transform = Transform3D(-0.303158, -0.739914, -0.600519, 0.0355596, -0.638519, 0.768784, -0.952277, 0.211709, 0.219883, -0.0316372, 0.109252, -0.307104)
transform = Transform3D(-0.303158, -0.739914, -0.600519, 0.0355596, -0.638519, 0.768784, -0.952277, 0.211709, 0.219883, -0.0313653, 0.102962, -0.312327)
external_skeleton = NodePath("/root/@EditorNode@17140/@Panel@13/@VBoxContainer@14/@HSplitContainer@17/@HSplitContainer@25/@HSplitContainer@33/@VBoxContainer@34/@VSplitContainer@36/@VSplitContainer@62/@VBoxContainer@63/@PanelContainer@110/MainScreen/@CanvasItemEditor@9462/@VSplitContainer@9281/@HSplitContainer@9283/@HSplitContainer@9285/@Control@9286/@SubViewportContainer@9287/@SubViewport@9288/Character/Armature/Skeleton3D")

[node name="LeftLegRayCast" parent="Armature/Skeleton3D/PoseWarping" index="4"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0833106, 0.361479, 0.361883)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0840908, 0.361218, 0.361871)

[node name="RightLegRayCast" parent="Armature/Skeleton3D/PoseWarping" index="5"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0316372, 0.359252, -0.307104)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0313653, 0.352962, -0.312327)

[node name="flashlight" parent="Armature" index="1" instance=ExtResource("5_euvsl")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1.12407, 0.156779)
Expand Down
114 changes: 33 additions & 81 deletions addons/AMSG/Components/CharacterMovementComponent.gd
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class_name CharacterMovementComponent
@export var character_node : PhysicsBody3D
## Refrence to a [RayCast3D] that should detect if character is on ground
@export var ground_check : RayCast3D
@export var mantle_component : MantleComponent



Expand Down Expand Up @@ -248,6 +249,7 @@ func update_character_movement():
match rotation_mode:
Global.rotation_mode.velocity_direction:
tilt = false
pose_warping.orientation_warping_enable = false
match stance:
Global.stance.standing:
current_movement_data = velocity_direction_standing_data
Expand All @@ -257,6 +259,7 @@ func update_character_movement():

Global.rotation_mode.looking_direction:
tilt = true
pose_warping.orientation_warping_enable = true
match stance:
Global.stance.standing:
current_movement_data = looking_direction_standing_data
Expand All @@ -265,6 +268,7 @@ func update_character_movement():


Global.rotation_mode.aiming:
pose_warping.orientation_warping_enable = true
match stance:
Global.stance.standing:
current_movement_data = aim_standing_data
Expand Down Expand Up @@ -299,77 +303,6 @@ func _process(delta):
calc_animation_data()
pose_warping.character_velocity = actual_velocity

#func stride_warping(target:Node3D, floor_normal:Vector3, skeleton_ref:Skeleton3D, hips_name:String, Foot:String, Thigh:String):
##add_sibling(test_sphere)
##add_sibling(test_sphere1)
#
##skeleton_ref.clear_bones_local_pose_override()
#var distance_in_each_frame = (actual_velocity*Vector3(1,0,1)).rotated(Vector3.UP,skeleton_ref.global_transform.basis.get_euler().y).length()
#var hips = skeleton_ref.find_bone(hips_name)
#var hips_transform = skeleton_ref.get_bone_pose(hips)
#
#var hips_distance_to_ground
#var stride_scale : float = 1.0
##Get Bones
#var bone = skeleton_ref.find_bone(Foot)
#var bone_transform = skeleton_ref.get_bone_global_pose_no_override(bone)
#
#var thigh_bone = skeleton_ref.find_bone(Thigh)
#var thigh_transform = skeleton_ref.get_bone_global_pose_no_override(thigh_bone)
#var thigh_angle = thigh_transform.basis.get_euler().x
#
##Calculate
#var stride_direction : Vector3 = Vector3.FORWARD # important to use in orientation warping
#var stride_warping_plane_origin = Plane(floor_normal, bone_transform.origin).intersects_ray(thigh_transform.origin,Vector3.DOWN)
## print(stride_warping_plane_origin)
#if stride_warping_plane_origin == null:
#return #Failed to get a plane origin/ we are probably in air
#
#var scale_origin = Plane(stride_direction,stride_warping_plane_origin).project(bone_transform.origin)
#var anim_speed = pow(hips_transform.origin.distance_to(bone_transform.origin),2) - pow(hips_transform.origin.y,2)
#anim_speed = sqrt(abs(anim_speed))
#stride_scale = clampf(distance_in_each_frame/4/anim_speed,0.0,2.0)
#var foot_warped_location : Vector3 = scale_origin + (bone_transform.origin - scale_origin) * stride_scale
## Apply
#if stride_scale > 0.1:
#target.position = lerp(target.position, foot_warped_location.rotated(Vector3.UP,mesh_ref.rotation.y), 1)
##test
##test_sphere.position = foot_warped_location.rotated(Vector3.UP,movement_direction)
#
#
#var updated_raycast_pos : Array[bool]
#func foot_look_at_y(from:Vector3, to:Vector3, up_ref:Vector3 = Vector3.UP) -> Basis:
#var forward = (to - from).normalized()
#var right = up_ref.normalized().cross(forward).normalized()
#forward = right.cross(up_ref).normalized()
#return Basis(right, up_ref, forward)
#func slope_warping(target:Node3D, raycast:RayCast3D, touch_raycast:RayCast3D, no_raycast_pos, leg_number:int):
#if updated_raycast_pos.size() < leg_number+1:
#updated_raycast_pos.resize(leg_number+1)
#
#if slope_warping_feet_locking_enable:
#if touch_raycast.is_colliding():
#if updated_raycast_pos[leg_number] == false:
#raycast.global_position = no_raycast_pos.global_position + Vector3(0.0,0.25,0.0)
#updated_raycast_pos[leg_number] = true
#else:
#updated_raycast_pos[leg_number] = false
## Update position to not let the leg yeet towards the old far location
#raycast.global_position = no_raycast_pos.global_position + Vector3(0.0,0.25,0.0)
#else:
#raycast.global_position = no_raycast_pos.global_position + Vector3(0.0,0.25,0.0)
#
#if raycast.is_colliding() and touch_raycast.is_colliding(): #if raycast is on ground
#var hit_point = raycast.get_collision_point() + Vector3.UP*slope_warping_foot_height_offset #gets Y position of where the ground is.
#target.global_transform.origin = hit_point #sets the target to the y position of the hitpoint
##if raycast.get_collision_normal() != Vector3.UP:
#var relative_normal = hit_point * raycast.get_collision_normal()
#target.look_at(relative_normal, Vector3.UP)
#target.global_transform = _basis_from_normal(target.global_transform, raycast.get_collision_normal())
#target.rotation += Vector3(-35, 0, 180)
#target.global_basis = foot_look_at_y(Vector3.ZERO, skeleton_ref.global_transform.basis.z, raycast.get_collision_normal()).rotated(Vector3.RIGHT, PI)#.rotated(raycast.get_collision_normal(), mesh_ref.rotation.y+PI/2)
#else:
#target.global_transform.origin = no_raycast_pos.global_transform.origin #if the raycast not colliding, the player is in the air and so the target position is set to the no_raycast_pos

func _physics_process(delta):
#Debug()
Expand All @@ -382,6 +315,8 @@ func _physics_process(delta):
Global.movement_state.none:
pass
Global.movement_state.grounded:
pose_warping.stride_warping_enable = true
pose_warping.slope_warping_enable = true
#------------------ Rotate Character Mesh ------------------#
match movement_action:
Global.movement_action.none:
Expand All @@ -390,6 +325,10 @@ func _physics_process(delta):
if (is_moving and input_is_moving) or (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 0.5:
smooth_character_rotation(actual_velocity,calc_grounded_rotation_rate(),delta)
Global.rotation_mode.looking_direction:
if gait != Global.gait.sprinting:
pose_warping.orientation_warping_enable = true
else:
pose_warping.orientation_warping_enable = false
if (is_moving and input_is_moving) or (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 0.5:
smooth_character_rotation(-camera_root.HObject.transform.basis.z if gait != Global.gait.sprinting else actual_velocity,calc_grounded_rotation_rate(),delta)
rotate_in_place_check()
Expand All @@ -402,14 +341,17 @@ func _physics_process(delta):
smooth_character_rotation(input_acceleration ,2.0,delta)

Global.movement_state.in_air:
pose_warping.stride_warping_enable = false
pose_warping.slope_warping_enable = false
#------------------ Rotate Character Mesh In Air ------------------#
match rotation_mode:
Global.rotation_mode.velocity_direction:
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
Global.rotation_mode.looking_direction:
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
Global.rotation_mode.aiming:
smooth_character_rotation(-camera_root.HObject.transform.basis.z ,15.0,delta)
if mantle_component and !mantle_component.is_climbing:
match rotation_mode:
Global.rotation_mode.velocity_direction:
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
Global.rotation_mode.looking_direction:
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
Global.rotation_mode.aiming:
smooth_character_rotation(-camera_root.HObject.transform.basis.z ,15.0,delta)
#------------------ Mantle Check ------------------#
if input_is_moving == true:
mantle_check()
Expand All @@ -423,15 +365,22 @@ func _physics_process(delta):

#------------------ Gravity ------------------#
if is_flying == false and character_node is CharacterBody3D:
character_node.velocity.y = lerp(character_node.velocity.y,vertical_velocity.y - character_node.get_floor_normal().y,delta * gravity)
character_node.move_and_slide()
if mantle_component:
if !mantle_component.is_climbing:
character_node.velocity.y = lerp(character_node.velocity.y,vertical_velocity.y - character_node.get_floor_normal().y,delta * gravity)
character_node.move_and_slide()
else:
character_node.velocity.y = lerp(character_node.velocity.y,vertical_velocity.y - character_node.get_floor_normal().y,delta * gravity)
character_node.move_and_slide()

if ground_check.is_colliding() and is_flying == false:
movement_state = Global.movement_state.grounded
else:
await get_tree().create_timer(0.1).timeout #wait a moment to see if the character lands fast (this means that the character didn't fall, but stepped down a bit.)
movement_state = Global.movement_state.in_air
if character_node is CharacterBody3D:
vertical_velocity += Vector3.DOWN * gravity * delta

if character_node is CharacterBody3D and character_node.is_on_ceiling():
vertical_velocity.y = 0
#------------------ Stair climb ------------------#
Expand Down Expand Up @@ -556,6 +505,8 @@ var PrevVelocity :Vector3
## Adds input to move the character, should be called when Idle too, to execute deacceleration for CharacterBody3D or reset velocity for RigidBody3D.
## when Idle speed and direction should be passed as 0, and deacceleration passed, or leave them empty.
func add_movement_input(direction: Vector3 = Vector3.ZERO, Speed: float = 0, Acceleration: float = deacceleration if character_node is CharacterBody3D else 0) -> void:
if mantle_component and mantle_component.is_climbing:
return
var max_speed : float = Speed
input_direction = direction

Expand Down Expand Up @@ -615,7 +566,8 @@ func calc_animation_data(): # it is used to modify the animation data to get the


func mantle_check():
pass
if mantle_component:
mantle_component.detect_ledge()

func jump() -> void:
if ground_check.is_colliding() and not head_bonked:
Expand Down
65 changes: 65 additions & 0 deletions addons/AMSG/Components/MantleComponent/MantleComponent.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@tool
extends Node3D
class_name MantleComponent
@export var character_collision_shape : CollisionShape3D
@export var character_node : PhysicsBody3D
@export var animation_tree : AnimationTree
@export var mantle_anim : String = "Mantle"
#@export var character_height : float = 1.75
@onready var ledge_top_detect : RayCast3D = $LedgeTopDetect
@onready var ledge_detect : RayCast3D = $LedgeDetect
@onready var shape_cast_3d = $ShapeCast3D
@onready var ledge_ground_detect = $LedgeGroundDetect

var is_climbing : bool

func _get_configuration_warnings():
if not get_parent() is Skeleton3D:
return ["Parent Must be Skeleton3D."]

func _ready():
if not get_parent() is Skeleton3D:
assert(false, "Parent Must be Skeleton3D.")
update_configuration_warnings()
if not character_node is CharacterBody3D and not character_node is RigidBody3D:
assert(false, "Character Node Must be either CharacterBody3D or RigidBody3D, please choose the right node from the inspector.")
shape_cast_3d.shape = character_collision_shape.shape
#shape_cast_3d.position = character_collision_shape.position
shape_cast_3d.add_exception(character_node)
ledge_top_detect.add_exception(character_node)
ledge_detect.add_exception(character_node)
ledge_ground_detect.add_exception(character_node)
func _physics_process(delta):
ledge_detect.position.y = shape_cast_3d.shape.height#character_height
ledge_top_detect.position.y = shape_cast_3d.shape.height + 0.25#character_height + 0.25
ledge_ground_detect.position.y = ledge_top_detect.position.y
ledge_ground_detect.position.z = 1
ledge_detect.rotation_degrees.x = -90
ledge_top_detect.rotation_degrees.x = -90
func detect_ledge():
if is_climbing:
return
if ledge_detect.is_colliding() and ledge_ground_detect.is_colliding() and !ledge_top_detect.is_colliding():
shape_cast_3d.global_position = shape_cast_3d.shape.height/2*Vector3.UP + Vector3(0,0.1,0) + ledge_ground_detect.get_collision_point()
if !shape_cast_3d.is_colliding(): #The character can fit into the mantle location, Climb
mantle()


func mantle():
is_climbing = true
if character_node is RigidBody3D:
character_node.freeze_mode = RigidBody3D.FREEZE_MODE_STATIC
if character_node is CharacterBody3D:
character_node.velocity = Vector3.ZERO
character_node.move_and_slide()
animation_tree.active = false

var anim_player : AnimationPlayer = get_node(String(animation_tree.get_path()) + "/" + String(animation_tree.anim_player))
anim_player.connect("animation_finished", func(anim):\
character_node.global_position = shape_cast_3d.global_position;\
animation_tree.active = true;\
await get_tree().create_timer(0.1).timeout;\
is_climbing = false
)
anim_player.play(mantle_anim)

27 changes: 27 additions & 0 deletions addons/AMSG/Components/MantleComponent/MantleComponent.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[gd_scene load_steps=3 format=3 uid="uid://dpniuhmc5sj82"]

[ext_resource type="Script" path="res://addons/AMSG/Components/MantleComponent/MantleComponent.gd" id="1_ix4sf"]

[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_70w0s"]
resource_local_to_scene = true
radius = 0.375
height = 1.75

[node name="MantleComponent" type="Node3D"]
script = ExtResource("1_ix4sf")
mantle_anim = "Kick"

[node name="ShapeCast3D" type="ShapeCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
top_level = true
shape = SubResource("CapsuleShape3D_70w0s")
target_position = Vector3(0, 0, 0)

[node name="LedgeTopDetect" type="RayCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 2, 0)

[node name="LedgeDetect" type="RayCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 1.75, 0)

[node name="LedgeGroundDetect" type="RayCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1)
Loading

0 comments on commit c074df4

Please sign in to comment.