105 lines
4.1 KiB
C#
105 lines
4.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
namespace BITKit
|
|
{
|
|
public class LineObstacleProvider : PathProvider
|
|
{
|
|
public LayerMask layerMask;
|
|
public int distance;
|
|
public float tolerance = 0.32f;
|
|
public int accuracy;
|
|
|
|
protected Vector3 startPos;
|
|
protected Vector3 endPos;
|
|
protected Vector3 currentPos;
|
|
public override bool IsValid(ref Vector3 startPos)
|
|
{
|
|
if (TryGetObstacle(out var raycastHit))
|
|
{
|
|
if (TryGetCrossLocation(out var location))
|
|
{
|
|
this.startPos = startPos;
|
|
endPos = location;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
void OnDrawGizmos()
|
|
{
|
|
Gizmos.DrawWireSphere(currentPos, 0.1f);
|
|
Gizmos.DrawWireSphere(endPos, 0.1f);
|
|
}
|
|
public override Vector3 Evaluate(float time)
|
|
{
|
|
currentPos = Vector3.Lerp(startPos, endPos, time);
|
|
return currentPos;
|
|
}
|
|
public bool TryGetObstacle(out RaycastHit raycastHit)
|
|
{
|
|
var originPos = transform.position;
|
|
var endPos = originPos + distance * transform.forward;
|
|
|
|
raycastHit = default;
|
|
for (int i = 0; i < accuracy; i++)
|
|
{
|
|
var weight = i / (float)accuracy;
|
|
var tolerance = this.tolerance * Vector3.up;
|
|
var vectorUp = Vector3.Lerp(-tolerance, tolerance, weight);
|
|
if (Physics.Linecast(originPos, endPos + vectorUp, out raycastHit, layerMask))
|
|
{
|
|
Debug.DrawLine(originPos, endPos, Color.yellow, 2);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
public bool TryGetCrossLocation(out Location location, float radius = 0.2f, float height = 1f)
|
|
{
|
|
location = default;
|
|
if (TryGetObstacle(out var raycastHit))
|
|
{
|
|
var rotation = Quaternion.LookRotation(-raycastHit.normal, Vector3.up);
|
|
var edgePoint = raycastHit.point;
|
|
for (int i = 0; i < accuracy; i++)
|
|
{
|
|
var weight = i / (float)accuracy;
|
|
var vectorUp = Vector3.Lerp(Vector3.zero, Vector3.up * 0.32f, weight);
|
|
var originPos = raycastHit.point + vectorUp - transform.forward * 0.1f;
|
|
var endPos = originPos + transform.forward;
|
|
if (Physics.Linecast(originPos, endPos, out var raycast, layerMask))
|
|
{
|
|
edgePoint = raycast.point;
|
|
Debug.DrawLine(originPos, edgePoint, Color.red, i);
|
|
}
|
|
else
|
|
{
|
|
Debug.DrawLine(originPos, endPos, Color.green, i);
|
|
edgePoint.y = originPos.y;
|
|
var startPos = edgePoint + transform.forward * radius;
|
|
if (Physics.Raycast(startPos, Vector3.down, out raycast, layerMask))
|
|
{
|
|
var point0 = raycast.point;
|
|
point0.y += radius + 0.01f;
|
|
var point1 = point0 + Vector3.up * height;
|
|
point1.y -= radius;
|
|
var colliders = Physics.OverlapCapsule(point0, point1, radius, layerMask);
|
|
if (colliders.Length is 0)
|
|
{
|
|
location = new Location()
|
|
{
|
|
position = raycast.point,
|
|
rotation = rotation
|
|
};
|
|
return true;
|
|
}
|
|
Debug.DrawLine(startPos, raycast.point, Color.cyan, 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
} |