Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Submodules/GroundDetector.cs

95 lines
3.6 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
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;
}
public bool DetectGround()
{
Vector3 centerPosition = characterTransform.position - new Vector3(0, groundedOffset, 0);
Vector3 startPosition = centerPosition + new Vector3(0, groundedLength / 2, 0);
Vector3 endPosition = centerPosition - new Vector3(0, groundedLength / 2, 0);
return isOnGround = Physics.CheckCapsule(startPosition, endPosition, groundedRadius, groundLayers, QueryTriggerInteraction.Ignore);
}
public bool DetectGround(float length, float overrideRadius = -1f)
{
overrideRadius = overrideRadius < 0 ? groundedRadius : overrideRadius;
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 isOnGround = Physics.CheckCapsule(startPosition, endPosition, overrideRadius, groundLayers, QueryTriggerInteraction.Ignore);
}
/// <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;
}
}
}