Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Submodules/GroundDetector.cs
SoulliesOfficial 50ee502684 完善
2026-02-13 09:22:11 -05:00

113 lines
4.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
public class GroundDetector
{
[ShowInInspector]
private CharacterBase character;
[ShowInInspector]
private Transform characterTransform;
public bool isOnGround;
public float groundedLength;
public float groundedRadius;
public float groundedOffset;
public LayerMask groundLayers;
public GroundDetector()
{
}
public GroundDetector(CharacterBase character, float groundedLength, float groundedRadius, float groundedOffset, LayerMask groundLayers)
{
this.character = character;
this.characterTransform = character.transform;
this.groundedLength = groundedLength;
this.groundedRadius = groundedRadius;
this.groundedOffset = groundedOffset;
this.groundLayers = groundLayers;
}
private bool CheckOnGround(float length, float radius = -1f)
{
radius = radius < 0 ? groundedRadius : radius;
Vector3 centerPosition = characterTransform.position - new Vector3(0, groundedOffset, 0);
Vector3 startPosition = centerPosition + new Vector3(0, length / 2, 0);
Vector3 endPosition = centerPosition - new Vector3(0, length / 2, 0);
return Physics.CheckCapsule(startPosition, endPosition, radius, groundLayers, QueryTriggerInteraction.Ignore);
}
public bool DetectGround()
{
float predictDistance = -character.movementSc.finalMovementVelocity.y;
float adjustedGroundedLength = groundedLength + Mathf.Max(0, predictDistance);
return isOnGround = CheckOnGround(adjustedGroundedLength);
}
public bool DetectGround(float multiplier, float offset = 0f)
{
float predictDistance = -character.movementSc.finalMovementVelocity.y;
float adjustedGroundedLength = (groundedLength + Mathf.Max(0, predictDistance)) * multiplier;
return CheckOnGround(adjustedGroundedLength + offset);
}
public bool DetectGroundByFixedLength(float fixedLength, bool withPrediction = false, float overrideRadius = -1f)
{
float adjustedGroundedLength = fixedLength;
if (withPrediction)
{
float predictDistance = -character.movementSc.finalMovementVelocity.y;
adjustedGroundedLength = fixedLength + Mathf.Max(0, predictDistance);
}
return CheckOnGround(adjustedGroundedLength, overrideRadius);
}
/// <summary>
/// 获取一个实体到地面的距离如果返回Infinity则说明实体的下方没有地面
/// </summary>
/// <returns>实体到地面的距离</returns>
public float GetDistanceToGround()
{
Vector3 rayOrigin = characterTransform.position - new Vector3(0, groundedOffset, 0);
Ray ray = new Ray(rayOrigin, Vector3.down);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, groundLayers))
{
return hit.distance;
}
return Mathf.Infinity;
}
/// <summary>
/// 忽略空中高度获取一个实体在地面上的位置如果返回false则说明实体的下方没有地面
/// </summary>
/// <param name="groundPosition">返回地面位置</param>
/// <returns>实体下方是否有地面</returns>
public bool GetGroundPosition(out Vector3 groundPosition)
{
if (isOnGround)
{
groundPosition = characterTransform.position;
return true;
}
Vector3 rayOrigin = characterTransform.position - new Vector3(0, groundedOffset, 0);
Ray ray = new Ray(rayOrigin, Vector3.down);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, groundLayers))
{
groundPosition = hit.point;
return true;
}
groundPosition = characterTransform.position;
return false;
}
}
}