Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added player height control to support mounting climbed objects and crouching #146

Merged
merged 1 commit into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions addons/godot-xr-tools/VERSIONS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 2.5.0
- Added advanced player height control
- Modified climbing to collapse player to a sphere to allow mounting climbed objects
- Added crouch movement provider

# 2.4.1
- Fixed grab distance
- Fixed snap-zone instance drop and free issue
Expand Down
54 changes: 49 additions & 5 deletions addons/godot-xr-tools/assets/PlayerBody.gd
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export var player_radius := 0.4 setget set_player_radius
## Player head height (distance between between camera and top of head)
export var player_head_height := 0.1

## Minimum player height
export var player_height_min := 1.0

## Maximum player height
export var player_height_max := 2.2

## Eyes forward offset from center of body in player_radius units
export (float, 0.0, 1.0) var eye_forward_offset := 0.66

Expand Down Expand Up @@ -78,12 +84,22 @@ var ground_physics: GroundPhysicsSettings = null
## Ground control velocity - modified by MovementProvider nodes
var ground_control_velocity := Vector2.ZERO

## Player height offset (for height calibration)
var player_height_offset := 0.0


# Movement providers
var _movement_providers := Array()

# Jump cool-down counter
var _jump_cooldown := 0

## Player height overrides
var _player_height_overrides := { }

# Player height override (enabled when non-negative)
var _player_height_override := -1.0


## ARVROrigin node
onready var origin_node := ARVRHelpers.get_arvr_origin(self)
Expand Down Expand Up @@ -248,12 +264,32 @@ func request_jump(var skip_jump_velocity := false):
func move_and_slide(var velocity: Vector3) -> Vector3:
return kinematic_node.move_and_slide(velocity, Vector3.UP, false, 4, 0.785398, push_rigid_bodies)

# Set or clear a named height override
func override_player_height(key, value: float = -1.0):
# Clear or set the override
if value < 0.0:
_player_height_overrides.erase(key)
else:
_player_height_overrides[key] = value

# Set or clear the override value
var override = _player_height_overrides.values().min()
_player_height_override = override if override != null else -1.0

# This method updates the body to match the player position
func _update_body_under_camera():
# Calculate the player height based on the origin and camera position
var player_height := camera_node.transform.origin.y + player_head_height
if player_height < player_radius:
player_height = player_radius
# Calculate the player height based on the camera position in the origin and the calibration
var player_height := clamp(
camera_node.transform.origin.y + player_head_height + player_height_offset,
player_height_min,
player_height_max)

# Allow forced overriding of height
if _player_height_override >= 0.0:
player_height = _player_height_override

# Ensure player height makes mathematical sense
player_height = max(player_height, player_radius * 2.0)

# Adjust the collision shape to match the player geometry
_collision_node.shape.radius = player_radius
Expand All @@ -264,7 +300,7 @@ func _update_body_under_camera():
var curr_transform := kinematic_node.global_transform
var camera_transform := camera_node.global_transform
curr_transform.origin = camera_transform.origin
curr_transform.origin.y = origin_node.global_transform.origin.y
curr_transform.origin.y += player_head_height - player_height

# The camera/eyes are towards the front of the body, so move the body back slightly
var forward_dir := -camera_transform.basis.z * HORIZONTAL
Expand Down Expand Up @@ -374,6 +410,14 @@ func _get_configuration_warning():
if player_radius <= 0:
return "Player radius must be configured"

# Verify the player height minimum is valid
if player_height_min < player_radius * 2.0:
return "Player height minimum smaller than 2x radius"

# Verify the player height maximum is valid
if player_height_max < player_height_min:
return "Player height maximum cannot be smaller than minimum"

# Verify eye-forward does not allow near-clip-plane look through
var eyes_to_collider = (1.0 - eye_forward_offset) * player_radius
if eyes_to_collider < test_camera_node.near:
Expand Down
2 changes: 2 additions & 0 deletions addons/godot-xr-tools/functions/Function_Climb_movement.gd
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ func _set_climbing(active: bool, player_body: PlayerBody) -> void:
if is_active:
_distances.clear()
_deltas.clear()
player_body.override_player_height(self, 0.0)
emit_signal("player_climb_start")
else:
var velocity := _average_velocity()
var dir_forward = -(player_body.camera_node.global_transform.basis.z * HORIZONTAL).normalized()
player_body.velocity = (velocity * fling_multiplier) + (dir_forward * forward_push)
player_body.override_player_height(self)
emit_signal("player_climb_end")


Expand Down
81 changes: 81 additions & 0 deletions addons/godot-xr-tools/functions/Function_Crouch_movement.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
tool
class_name Function_CrouchMovement
extends MovementProvider

##
## Movement Provider for Crouching
##
## @desc:
## This script works with the PlayerBody attached to the players ARVROrigin.
##
## When the player presses the selected button, the height is overridden
## to the crouch height
##


# enum our buttons, should find a way to put this more central
enum Buttons {
VR_BUTTON_BY = 1,
VR_GRIP = 2,
VR_BUTTON_3 = 3,
VR_BUTTON_4 = 4,
VR_BUTTON_5 = 5,
VR_BUTTON_6 = 6,
VR_BUTTON_AX = 7,
VR_BUTTON_8 = 8,
VR_BUTTON_9 = 9,
VR_BUTTON_10 = 10,
VR_BUTTON_11 = 11,
VR_BUTTON_12 = 12,
VR_BUTTON_13 = 13,
VR_PAD = 14,
VR_TRIGGER = 15
}


## Movement provider order
export var order := 10

## Crouch height
export var crouch_height := 1.0

## Crouch button
export (Buttons) var crouch_button: int = Buttons.VR_PAD


## Crouching flag
var _crouching := false


# Controller node
onready var _controller : ARVRController = get_parent()


# Perform jump movement
func physics_movement(delta: float, player_body: PlayerBody, _disabled: bool):
# Skip if the controller isn't active
if !_controller.get_is_active():
return

# Check for crouching change
var crouching := _controller.is_button_pressed(crouch_button) != 0
if crouching == _crouching:
return

# Update crouching state
_crouching = crouching
if crouching:
player_body.override_player_height(self, crouch_height)
else:
player_body.override_player_height(self)


# This method verifies the MovementProvider has a valid configuration.
func _get_configuration_warning():
# Check the controller node
var test_controller = get_parent()
if !test_controller or !test_controller is ARVRController:
return "Unable to find ARVR Controller node"

# Call base class
return ._get_configuration_warning()
6 changes: 6 additions & 0 deletions addons/godot-xr-tools/functions/Function_Crouch_movement.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]

[ext_resource path="res://addons/godot-xr-tools/functions/Function_Crouch_movement.gd" type="Script" id=1]

[node name="Function_Crouch_movement" type="Node" groups=["movement_providers"]]
script = ExtResource( 1 )