95 lines
3.6 KiB
C#
95 lines
3.6 KiB
C#
using UnityEngine;
|
|
|
|
namespace FIMSpace
|
|
{
|
|
public class FImp_ColliderData_Terrain : FImp_ColliderData_Base
|
|
{
|
|
public TerrainCollider TerrCollider { get; private set; }
|
|
public Terrain TerrainComponent { get; private set; }
|
|
|
|
public FImp_ColliderData_Terrain(TerrainCollider collider)
|
|
{
|
|
Collider = collider;
|
|
Transform = collider.transform;
|
|
TerrCollider = collider;
|
|
ColliderType = EFColliderType.Terrain;
|
|
TerrainComponent = collider.GetComponent<Terrain>();
|
|
}
|
|
|
|
public override bool PushIfInside(ref Vector3 segmentPosition, float segmentRadius, Vector3 segmentOffset)
|
|
{
|
|
// Checking if segment is inside box shape of terrain
|
|
if (segmentPosition.x + segmentRadius < TerrainComponent.GetPosition().x - segmentRadius || segmentPosition.x > TerrainComponent.GetPosition().x + TerrainComponent.terrainData.size.x ||
|
|
segmentPosition.z + segmentRadius < TerrainComponent.GetPosition().z - segmentRadius || segmentPosition.z > TerrainComponent.GetPosition().z + TerrainComponent.terrainData.size.z)
|
|
return false;
|
|
|
|
Vector3 offsettedPosition = segmentPosition + segmentOffset;
|
|
Vector3 terrPoint = offsettedPosition;
|
|
terrPoint.y = TerrCollider.transform.position.y + TerrainComponent.SampleHeight(offsettedPosition);
|
|
|
|
|
|
float hitToPointDist = (offsettedPosition - terrPoint).magnitude;
|
|
float underMul = 1f;
|
|
|
|
if (offsettedPosition.y < terrPoint.y)
|
|
{
|
|
underMul = 4f;
|
|
}
|
|
else
|
|
if (offsettedPosition.y + segmentRadius * 2f < terrPoint.y)
|
|
{
|
|
underMul = 8f;
|
|
}
|
|
|
|
if (hitToPointDist < segmentRadius * underMul)
|
|
{
|
|
Vector3 toNormal = terrPoint - offsettedPosition;
|
|
|
|
Vector3 pushNormal;
|
|
if (underMul > 1f) pushNormal = toNormal + toNormal.normalized * segmentRadius; else pushNormal = toNormal - toNormal.normalized * segmentRadius;
|
|
segmentPosition = segmentPosition + pushNormal;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void PushOutFromTerrain(TerrainCollider terrainCollider, float segmentRadius, ref Vector3 point)
|
|
{
|
|
Terrain terrain = terrainCollider.GetComponent<Terrain>();
|
|
|
|
Vector3 rayOrigin = point;
|
|
rayOrigin.y = terrainCollider.transform.position.y + terrain.SampleHeight(point) + segmentRadius;
|
|
|
|
Ray ray = new Ray(rayOrigin, Vector3.down);
|
|
|
|
RaycastHit hit;
|
|
if (terrainCollider.Raycast(ray, out hit, segmentRadius * 2f))
|
|
{
|
|
float hitToPointDist = (point - hit.point).magnitude;
|
|
|
|
float underMul = 1f;
|
|
if (hit.point.y > point.y + segmentRadius * 0.9f)
|
|
{
|
|
underMul = 8f;
|
|
}
|
|
else
|
|
if (hit.point.y > point.y)
|
|
{
|
|
underMul = 4f;
|
|
}
|
|
|
|
if (hitToPointDist < segmentRadius * underMul)
|
|
{
|
|
Vector3 toNormal = hit.point - point;
|
|
Vector3 pushNormal;
|
|
|
|
if (underMul > 1f) pushNormal = toNormal + toNormal.normalized * segmentRadius; else pushNormal = toNormal - toNormal.normalized * segmentRadius;
|
|
point = point + pushNormal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|