Files
Fishing2/Assets/FImpossible Creations/Plugins - Shared/Physics/FImp_ColliderData_Terrain.cs
2025-11-10 00:08:26 +08:00

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;
}
}
}
}
}