Skip to content

Commit

Permalink
Added advanced player height control
Browse files Browse the repository at this point in the history
Modified climbing to collapse player to a sphere to allow mounting climbed objects
Added crouch movement provider
  • Loading branch information
Malcolmnixon committed Jun 15, 2022
1 parent 8b360e3 commit 9160743
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 5 deletions.
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("climb", 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("climb")
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 )

0 comments on commit 9160743

Please sign in to comment.