using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using UnityEngine; namespace BITKit { public interface IClosePoint { Collider Collider { get; } bool TryGetClosePoint(out Vector3 vector3); } [System.Serializable] public class GetClosePointFromCollider : IClosePoint { public Transform root; public LayerMask layerMask; public float distance; public Collider Collider { get; set; } public bool TryGetClosePoint(out Vector3 vector3) { vector3 = default; if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask)) { var collider = raycastHit.collider; if (collider.isTrigger) return false; switch (collider) { case MeshCollider meshCollider: if (meshCollider.convex is false) return false; break; } vector3 = collider.ClosestPoint(root.position + Vector3.up); var top = collider.bounds.center + collider.bounds.extents; if (Mathf.Abs(vector3.y - top.y) > 0.16f) return false; if (UnityEngine.Physics.Linecast(root.position, vector3, out var raycastHit2, layerMask)) { if(raycastHit2.collider != collider) return false; }; foreach(var hit in UnityEngine.Physics.OverlapSphere(vector3, 0.1f, layerMask)) { if(hit!= collider) return false; } Collider = collider; return true; //return vector3.y >= collider.bounds.center.y + collider.bounds.extents.y; //return true; } return false; } } /// /// 获取碰撞点可以翻越后的点 /// [Serializable] public class GetVaultPointFromCollider : IClosePoint { public Transform root; public Transform groundReference; public LayerMask layerMask; public float maxHeight = 1.2f; public float maxVaultDistance=1; public float radius; public float distance; public Vector3 StartPosition; public Vector3 EndPosition; public Collider Collider { get; set; } private Rigidbody rigidbody; private bool isInitialized; public bool TryGetClosePoint(out Vector3 vector3) { if (isInitialized is false) { rigidbody = groundReference.GetComponent(); isInitialized = true; } if (rigidbody) { vector3 = default; if (rigidbody.velocity.GetLength() < 0.1f) return false; } var reportBuilder = new System.Text.StringBuilder(); var forward = root.forward; var sourceStartPosition = groundReference.position; sourceStartPosition.y = root.position.y; var startPosition = sourceStartPosition; var collider = UnityEngine.Physics.OverlapSphere(startPosition, radius, layerMask); reportBuilder.AppendLine($"检测到了{collider.Length}个碰撞体"); foreach (var hit in collider) { var top = hit.bounds.center + hit.bounds.extents; if(top.y{hit.name}"); if(top.y>groundReference.transform.position.y+maxHeight) { reportBuilder.AppendLine("高度超出可翻越高度"); continue; } var start = sourceStartPosition+forward*8; //start.y = hit.bounds.center.y; var ray = new Ray(start, -forward); if (hit.Raycast(ray, out var colliderHit, 8) is false) { reportBuilder.AppendLine("未检测到背面,算法错误"); Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); continue; } EndPosition = colliderHit.point + colliderHit.normal*0.4f; EndPosition.y = top.y; try { foreach (var x in UnityEngine .Physics .OverlapSphere(EndPosition, 0.1f, layerMask)) { if(Equals(x, hit)) continue; throw new OperationCanceledException($"终点有其他碰撞体{x.name}"); } } catch (OperationCanceledException e) { reportBuilder.AppendLine(e.Message); continue; } if(UnityEngine.Physics.Raycast(EndPosition,Vector3.down,out _,1.6f,layerMask) is false) { Debug.DrawRay(EndPosition, Vector3.down*1.6f, Color.red, 8); reportBuilder.AppendLine("未检测到地面,跳过"); continue; //Debug.DrawRay(EndPosition, Vector3.down, Color.red, 8); } var fixdPosition = colliderHit.point; fixdPosition.y=hit.bounds.center.y; var start2 = fixdPosition; start2.y += 0.1f; var end2 = fixdPosition; end2.y -= 0.1f; if(UnityEngine.Physics.Linecast(start2,end2,out var downHit,layerMask)) { reportBuilder.AppendLine($"检测到了障碍物{downHit.collider.name}"); //BIT4Log.Log(reportBuilder.ToString()); continue; } start = startPosition; start.y = hit.bounds.center.y; ray = new Ray(start, forward); if(hit.Raycast(ray,out colliderHit,8) is false) { reportBuilder.AppendLine("未检测到正面,算法错误"); Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); continue; } StartPosition = colliderHit.point; StartPosition.y = top.y; StartPosition += colliderHit.normal * 0.4f; var closeStart = hit.ClosestPoint(StartPosition); var closeEnd = hit.ClosestPoint(EndPosition); var lineDistance = Vector3.Distance(closeStart, closeEnd); if(lineDistance > maxVaultDistance) { reportBuilder.AppendLine($"长度{lineDistance}超出可翻越距离{maxVaultDistance}"); Debug.DrawLine(closeStart,closeEnd, Color.yellow, 4); //BIT4Log.Log(reportBuilder.ToString()); continue; } vector3 = colliderHit.point; vector3.y = top.y; vector3 += colliderHit.normal * 0.4f; reportBuilder.AppendLine(); BIT4Log.Log(reportBuilder.ToString()); return true; } reportBuilder.AppendLine($"failed"); BIT4Log.Log(reportBuilder.ToString()); vector3 = default; return false; } } }