315 lines
12 KiB
C#
315 lines
12 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
namespace BITKit
|
|
{
|
|
public interface IClosePoint
|
|
{
|
|
Vector3 CurrentPoint { get; }
|
|
Collider Collider { get; }
|
|
bool TryGetClosePoint(out Vector3 vector3);
|
|
}
|
|
[Serializable]
|
|
public class GetClosePointFromCollider : IClosePoint
|
|
{
|
|
[SerializeField] private string name;
|
|
[SerializeField] private Transform transform;
|
|
[SerializeField] private Vector3 offset = Vector3.one;
|
|
[SerializeField] private LayerMask layerMask;
|
|
[SerializeField] private float distance;
|
|
[SerializeField] private float minHeight=0.32f;
|
|
[SerializeField] private float maxHeight = 1f;
|
|
public Vector3 CurrentPoint { get; set; }
|
|
public Collider Collider { get; set; }
|
|
private Collider[] _colliders=new Collider[8];
|
|
private Collider[] _mainCollider=new Collider[8];
|
|
public bool TryGetClosePoint(out Vector3 vector3)
|
|
{
|
|
vector3 = default;
|
|
StringBuilder reportBuilder = new();
|
|
reportBuilder.AppendLine($"检测任务:{name}");
|
|
var position = transform.position + transform.rotation * offset;
|
|
var detectedLength = Physics.OverlapSphereNonAlloc(position, distance, _mainCollider, layerMask);
|
|
reportBuilder.AppendLine($"检测到了{detectedLength}个碰撞体");
|
|
for (var i = 0; i <detectedLength ; i++)
|
|
{
|
|
reportBuilder.AppendLine($"----------------------------检测到了碰撞体{_mainCollider[i].name}");
|
|
var collider = _mainCollider[i];
|
|
if (collider.isTrigger)
|
|
{
|
|
reportBuilder?.AppendLine("碰撞体是触发器");
|
|
continue;
|
|
}
|
|
switch (collider)
|
|
{
|
|
case MeshCollider meshCollider:
|
|
if (meshCollider.convex is false)
|
|
{
|
|
reportBuilder?.AppendLine("MeshCollider未勾选Convex");
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
var bounds = collider.bounds;
|
|
vector3 = collider.ClosestPoint(transform.position + Vector3.up*64);
|
|
var top = bounds.center.y + bounds.extents.y;
|
|
Debug.DrawLine(transform.position,transform.position + Vector3.up * top,Color.blue,8f);
|
|
if (transform.position.y + minHeight > top)
|
|
{
|
|
reportBuilder?.AppendLine("高度不足");
|
|
continue;
|
|
}
|
|
|
|
var nextPos = position;
|
|
nextPos.y = collider.bounds.center.y;
|
|
if (collider.Raycast(new Ray(nextPos, transform.forward), out _, distance) is false)
|
|
{
|
|
reportBuilder?.AppendLine("未检测到前方");
|
|
continue;
|
|
}
|
|
var height = Mathf.Abs(top - transform.position.y);
|
|
if (height > maxHeight)
|
|
{
|
|
reportBuilder?.AppendLine($"高度差距过大:{height}");
|
|
continue;
|
|
}
|
|
if (Physics.Linecast(transform.position, vector3, out var raycastHit2, layerMask))
|
|
{
|
|
if (raycastHit2.collider != collider)
|
|
{
|
|
reportBuilder?.AppendLine($"检测到了其他碰撞体:{raycastHit2.transform.name}");
|
|
continue;
|
|
}
|
|
};
|
|
|
|
var length = Physics.OverlapSphereNonAlloc(vector3, 0.01f, _colliders, layerMask);
|
|
switch (length)
|
|
{
|
|
case 1:
|
|
if (_colliders[0] != collider)
|
|
{
|
|
reportBuilder.AppendLine($"检测到了其他碰撞体{_colliders[0].name}");
|
|
continue;
|
|
}
|
|
break;
|
|
case > 1:
|
|
reportBuilder.AppendLine("检测到了更多碰撞体");
|
|
for (var ii = 0; ii < length; ii++)
|
|
{
|
|
//Debug.DrawLine(vector3, _colliders[ii].ClosestPoint(vector3), Color.red, 8);
|
|
reportBuilder.AppendLine($"\t{_colliders[ii].name}");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
Collider = collider;
|
|
|
|
vector3.y = top;
|
|
CurrentPoint = vector3;
|
|
|
|
|
|
|
|
reportBuilder.AppendLine("<color=green>成功</color>");
|
|
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
|
|
return true;
|
|
}
|
|
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 获取碰撞点可以翻越后的点
|
|
/// </summary>
|
|
[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 Vector3 CurrentPoint { get; set; }
|
|
public Collider Collider { get; set; }
|
|
private Rigidbody rigidbody;
|
|
|
|
private bool isInitialized;
|
|
|
|
public bool TryGetClosePoint(out Vector3 vector3)
|
|
{
|
|
if (isInitialized is false)
|
|
{
|
|
rigidbody = groundReference.GetComponent<Rigidbody>();
|
|
isInitialized = true;
|
|
}
|
|
if (rigidbody)
|
|
{
|
|
vector3 = default;
|
|
if (rigidbody.velocity.GetLength() < 0.1f) return false;
|
|
}
|
|
|
|
//var reportBuilder = new System.Text.StringBuilder();
|
|
StringBuilder reportBuilder=null;
|
|
|
|
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<sourceStartPosition.y)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
reportBuilder?.AppendLine();
|
|
reportBuilder?.AppendLine($">{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<GetVaultPointFromCollider>(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<GetVaultPointFromCollider>(reportBuilder.ToString());
|
|
continue;
|
|
}
|
|
|
|
if(Physics.Linecast(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f,out var _hit,layerMask))
|
|
{
|
|
|
|
//Debug.DrawLine(closeStart+Vector3.up*0.1f,_hit.point, Color.red, 4);
|
|
reportBuilder?.AppendLine("检测到了障碍物");
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
//Debug.DrawLine(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f, Color.green, 4);
|
|
}
|
|
|
|
vector3 = colliderHit.point;
|
|
|
|
|
|
vector3.y = top.y;
|
|
|
|
vector3 += colliderHit.normal * 0.4f;
|
|
|
|
reportBuilder?.AppendLine();
|
|
|
|
if(reportBuilder is not null)
|
|
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
|
|
|
CurrentPoint = vector3;
|
|
Collider = hit;
|
|
return true;
|
|
}
|
|
|
|
reportBuilder?.AppendLine($"failed");
|
|
|
|
if(reportBuilder is not null)
|
|
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
|
|
|
|
vector3 = default;
|
|
return false;
|
|
}
|
|
}
|
|
} |