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); } /// /// 获取一个实体到地面的距离,如果返回Infinity则说明实体的下方没有地面 /// /// 实体到地面的距离 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; } /// /// 忽略空中高度,获取一个实体在地面上的位置,如果返回false则说明实体的下方没有地面 /// /// 返回地面位置 /// 实体下方是否有地面 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; } } }