You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.4 KiB
C#
144 lines
4.4 KiB
C#
1 year ago
|
using UnityEngine;
|
||
|
|
||
|
public class Crouch : MonoBehaviour
|
||
|
{
|
||
|
public KeyCode key = KeyCode.LeftControl;
|
||
|
|
||
|
[Header("Slow Movement")]
|
||
|
[Tooltip("Movement to slow down when crouched.")]
|
||
|
public FirstPersonMovement movement;
|
||
|
[Tooltip("Movement speed when crouched.")]
|
||
|
public float movementSpeed = 2;
|
||
|
|
||
|
[Header("Low Head")]
|
||
|
[Tooltip("Head to lower when crouched.")]
|
||
|
public Transform headToLower;
|
||
|
[HideInInspector]
|
||
|
public float? defaultHeadYLocalPosition;
|
||
|
public float crouchYHeadPosition = 1;
|
||
|
|
||
|
[Tooltip("Collider to lower when crouched.")]
|
||
|
public CapsuleCollider colliderToLower;
|
||
|
[HideInInspector]
|
||
|
public float? defaultColliderHeight;
|
||
|
|
||
|
public bool IsCrouched { get; private set; }
|
||
|
public event System.Action CrouchStart, CrouchEnd;
|
||
|
|
||
|
|
||
|
void Reset()
|
||
|
{
|
||
|
// Try to get components.
|
||
|
movement = GetComponentInParent<FirstPersonMovement>();
|
||
|
headToLower = movement.GetComponentInChildren<Camera>().transform;
|
||
|
colliderToLower = movement.GetComponentInChildren<CapsuleCollider>();
|
||
|
}
|
||
|
|
||
|
void LateUpdate()
|
||
|
{
|
||
|
if (Input.GetKey(key))
|
||
|
{
|
||
|
// Enforce a low head.
|
||
|
if (headToLower)
|
||
|
{
|
||
|
// If we don't have the defaultHeadYLocalPosition, get it now.
|
||
|
if (!defaultHeadYLocalPosition.HasValue)
|
||
|
{
|
||
|
defaultHeadYLocalPosition = headToLower.localPosition.y;
|
||
|
}
|
||
|
|
||
|
// Lower the head.
|
||
|
headToLower.localPosition = new Vector3(headToLower.localPosition.x, crouchYHeadPosition, headToLower.localPosition.z);
|
||
|
}
|
||
|
|
||
|
// Enforce a low colliderToLower.
|
||
|
if (colliderToLower)
|
||
|
{
|
||
|
// If we don't have the defaultColliderHeight, get it now.
|
||
|
if (!defaultColliderHeight.HasValue)
|
||
|
{
|
||
|
defaultColliderHeight = colliderToLower.height;
|
||
|
}
|
||
|
|
||
|
// Get lowering amount.
|
||
|
float loweringAmount;
|
||
|
if(defaultHeadYLocalPosition.HasValue)
|
||
|
{
|
||
|
loweringAmount = defaultHeadYLocalPosition.Value - crouchYHeadPosition;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
loweringAmount = defaultColliderHeight.Value * .5f;
|
||
|
}
|
||
|
|
||
|
// Lower the colliderToLower.
|
||
|
colliderToLower.height = Mathf.Max(defaultColliderHeight.Value - loweringAmount, 0);
|
||
|
colliderToLower.center = Vector3.up * colliderToLower.height * .5f;
|
||
|
}
|
||
|
|
||
|
// Set IsCrouched state.
|
||
|
if (!IsCrouched)
|
||
|
{
|
||
|
IsCrouched = true;
|
||
|
SetSpeedOverrideActive(true);
|
||
|
CrouchStart?.Invoke();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (IsCrouched)
|
||
|
{
|
||
|
// Rise the head back up.
|
||
|
if (headToLower)
|
||
|
{
|
||
|
headToLower.localPosition = new Vector3(headToLower.localPosition.x, defaultHeadYLocalPosition.Value, headToLower.localPosition.z);
|
||
|
}
|
||
|
|
||
|
// Reset the colliderToLower's height.
|
||
|
if (colliderToLower)
|
||
|
{
|
||
|
colliderToLower.height = defaultColliderHeight.Value;
|
||
|
colliderToLower.center = Vector3.up * colliderToLower.height * .5f;
|
||
|
}
|
||
|
|
||
|
// Reset IsCrouched.
|
||
|
IsCrouched = false;
|
||
|
SetSpeedOverrideActive(false);
|
||
|
CrouchEnd?.Invoke();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#region Speed override.
|
||
|
void SetSpeedOverrideActive(bool state)
|
||
|
{
|
||
|
// Stop if there is no movement component.
|
||
|
if(!movement)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Update SpeedOverride.
|
||
|
if (state)
|
||
|
{
|
||
|
// Try to add the SpeedOverride to the movement component.
|
||
|
if (!movement.speedOverrides.Contains(SpeedOverride))
|
||
|
{
|
||
|
movement.speedOverrides.Add(SpeedOverride);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Try to remove the SpeedOverride from the movement component.
|
||
|
if (movement.speedOverrides.Contains(SpeedOverride))
|
||
|
{
|
||
|
movement.speedOverrides.Remove(SpeedOverride);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float SpeedOverride() => movementSpeed;
|
||
|
#endregion
|
||
|
}
|