您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
67 行
2.2 KiB
67 行
2.2 KiB
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
public class PhysicsUtils
|
|
{
|
|
public static Vector3 GetClosestPointOnCollider(Collider c, Vector3 p)
|
|
{
|
|
if (c is SphereCollider)
|
|
{
|
|
var csc = c as SphereCollider;
|
|
|
|
var scale = csc.transform.localScale;
|
|
return c.transform.position + (p - c.transform.position).normalized * csc.radius * Mathf.Max(Mathf.Abs(scale.x), Mathf.Abs(scale.y), Mathf.Abs(scale.z));
|
|
}
|
|
else if (c is BoxCollider)
|
|
{
|
|
var cbc = c as BoxCollider;
|
|
var local_p = cbc.transform.InverseTransformPoint(p);
|
|
|
|
local_p -= cbc.center;
|
|
|
|
var minsize = -0.5f * cbc.size;
|
|
var maxsize = 0.5f * cbc.size;
|
|
|
|
local_p.x = Mathf.Clamp(local_p.x, minsize.x, maxsize.x);
|
|
local_p.y = Mathf.Clamp(local_p.y, minsize.y, maxsize.y);
|
|
local_p.z = Mathf.Clamp(local_p.z, minsize.z, maxsize.z);
|
|
|
|
local_p += cbc.center;
|
|
|
|
return cbc.transform.TransformPoint(local_p);
|
|
}
|
|
else if (c is CapsuleCollider)
|
|
{
|
|
// TODO: Only supports Y axis based capsules now
|
|
var ccc = c as CapsuleCollider;
|
|
var local_p = ccc.transform.InverseTransformPoint(p);
|
|
local_p -= ccc.center;
|
|
|
|
// Clamp inside outer cylinder top/bot
|
|
local_p.y = Mathf.Clamp(local_p.y, -ccc.height * 0.5f, ccc.height * 0.5f);
|
|
|
|
// Clamp to cylinder edge
|
|
Vector2 h = new Vector2(local_p.x, local_p.z);
|
|
h = h.normalized * ccc.radius;
|
|
local_p.x = h.x;
|
|
local_p.z = h.y;
|
|
|
|
// Capsule ends
|
|
float dist_to_top = ccc.height * 0.5f - Mathf.Abs(local_p.y);
|
|
if (dist_to_top < ccc.radius)
|
|
{
|
|
float f = (ccc.radius - dist_to_top) / ccc.radius;
|
|
float scaledown = Mathf.Sqrt(1.0f - f * f);
|
|
local_p.x *= scaledown;
|
|
local_p.z *= scaledown;
|
|
}
|
|
|
|
local_p += ccc.center;
|
|
return ccc.transform.TransformPoint(local_p);
|
|
}
|
|
else
|
|
{
|
|
return c.ClosestPointOnBounds(p);
|
|
}
|
|
}
|
|
}
|