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

139 lines
5.2 KiB
C#

using UnityEngine;
namespace FIMSpace
{
public class FImp_ColliderData_Sphere : FImp_ColliderData_Base
{
public SphereCollider Sphere { get; private set; }
public CircleCollider2D Sphere2D { get; private set; }
private float SphereRadius;
public FImp_ColliderData_Sphere(SphereCollider collider)
{
Is2D = false;
Transform = collider.transform;
Collider = collider;
Sphere = collider;
ColliderType = EFColliderType.Sphere;
RefreshColliderData();
}
public FImp_ColliderData_Sphere(CircleCollider2D collider)
{
Is2D = true;
Transform = collider.transform;
Collider2D = collider;
Sphere2D = collider;
ColliderType = EFColliderType.Sphere;
RefreshColliderData();
}
public override void RefreshColliderData()
{
if (IsStatic) return; // No need to refresh collider data if it is static
if (Sphere2D == null)
{
SphereRadius = CalculateTrueRadiusOfSphereCollider(Sphere.transform, Sphere.radius);
base.RefreshColliderData();
}
else
{
SphereRadius = CalculateTrueRadiusOfSphereCollider(Sphere2D.transform, Sphere2D.radius);
base.RefreshColliderData();
}
}
public override bool PushIfInside(ref Vector3 point, float pointRadius, Vector3 pointOffset)
{
if ( Is2D == false)
return PushOutFromSphereCollider(Sphere, pointRadius, ref point, SphereRadius, pointOffset);
else
return PushOutFromSphereCollider(Sphere2D, pointRadius, ref point, SphereRadius, pointOffset);
}
public static bool PushOutFromSphereCollider(SphereCollider sphere, float segmentColliderRadius, ref Vector3 segmentPos, Vector3 segmentOffset)
{
return PushOutFromSphereCollider(sphere, segmentColliderRadius, ref segmentPos, CalculateTrueRadiusOfSphereCollider(sphere), segmentOffset);
}
public static bool PushOutFromSphereCollider(SphereCollider sphere, float segmentColliderRadius, ref Vector3 segmentPos, float collidingSphereRadius, Vector3 segmentOffset)
{
Vector3 sphereCenter = sphere.transform.position + sphere.transform.TransformVector(sphere.center);
float radius = collidingSphereRadius + segmentColliderRadius;
Vector3 pushNormal = (segmentPos + segmentOffset) - sphereCenter;
float squaredPushMagn = pushNormal.sqrMagnitude;
if (squaredPushMagn > 0 && squaredPushMagn < radius * radius)
{
segmentPos = sphereCenter - segmentOffset + pushNormal * (radius / Mathf.Sqrt(squaredPushMagn));
return true;
}
return false;
}
public static bool PushOutFromSphereCollider(CircleCollider2D sphere, float segmentColliderRadius, ref Vector3 segmentPos, float collidingSphereRadius, Vector3 segmentOffset)
{
Vector3 sphereCenter = sphere.transform.position + sphere.transform.TransformVector(sphere.offset);
sphereCenter.z = 0f;
float radius = collidingSphereRadius + segmentColliderRadius;
Vector3 pos2D = segmentPos; pos2D.z = 0f;
Vector3 pushNormal = (pos2D + segmentOffset) - sphereCenter;
float squaredPushMagn = pushNormal.sqrMagnitude;
if (squaredPushMagn > 0 && squaredPushMagn < radius * radius)
{
segmentPos = sphereCenter - segmentOffset + pushNormal * (radius / Mathf.Sqrt(squaredPushMagn));
return true;
}
return false;
}
#region Sphere Calculation Helpers
/// <summary>
/// Calculating radius of sphere collider including sphere collider's transform scalling
/// </summary>
public static float CalculateTrueRadiusOfSphereCollider(SphereCollider sphere)
{
return CalculateTrueRadiusOfSphereCollider(sphere.transform, sphere.radius);
}
public static float CalculateTrueRadiusOfSphereCollider(CircleCollider2D sphere)
{
return CalculateTrueRadiusOfSphereCollider(sphere.transform, sphere.radius);
}
/// <summary>
/// Calculating radius of sphere collider including sphere collider's transform scalling
/// </summary>
public static float CalculateTrueRadiusOfSphereCollider(Transform transform, float componentRadius)
{
float radius = componentRadius;
if (transform.lossyScale.x > transform.lossyScale.y)
{
if (transform.lossyScale.x > transform.lossyScale.z) radius *= transform.lossyScale.x;
else
radius *= transform.lossyScale.z;
}
else
{
if (transform.lossyScale.y > transform.lossyScale.z) radius *= transform.lossyScale.y;
else
radius *= transform.lossyScale.z;
}
return radius;
}
#endregion
}
}