public static void DrawVector(Vector3 position, Vector3 direction, float raySize, float markerSize, Color color, float duration, bool depthTest = true) { Debug.DrawRay(position, direction * raySize, color, 0, false); DebugDrawer.DrawMarker(position + direction * raySize, markerSize, color, 0, false); }
/// <summary> /// /// </summary> /// <param name="iter"></param> /// <param name="maxIter"></param> private void PushBack(int iter, int maxIter) { if (spheres != null) { _onContacted = false; _contactPoint = Vector3.zero; for (int i = 0; i < spheres.Length; i++) { CollisionSphere s = spheres[i]; Vector3 spherePosition = SpherePosition(s); float sphereRadius = s.radius; bool isConcatedSucceeded = false; if (s != null) { foreach (Collider col in Physics.OverlapSphere(spherePosition, sphereRadius)) { isConcatedSucceeded = CharacterCollisions.ClosestPointOnSurface(col, spherePosition, sphereRadius, out _contactPoint); if (isConcatedSucceeded) { DebugDrawer.DrawMarker(_contactPoint, 1, Color.red, 0); Vector3 v = _contactPoint - spherePosition; // 先保存被碰撞对象的层Id int layer = col.gameObject.layer; //通过设置临时Layer,将除当前被碰撞体以外的物体忽略掉。 col.gameObject.layer = TemporaryLayerIndex; // 从CollisionSphere的中点向接触点的方向发射一条射线,检测CollisionSphere的中点是否在被碰撞体的内部。 bool facingNormal = Physics.SphereCast(new Ray(spherePosition, v.normalized), TinyTolerance, v.magnitude + TinyTolerance, 1 << TemporaryLayerIndex); col.gameObject.layer = layer; if (facingNormal) { //CollisionSphere在被碰撞体的外部 if (Vector3.Distance(spherePosition, _contactPoint) < sphereRadius) { //CollisionSphere的半径减去向量的模得到反推的距离,然后反转得到反推的向量 v = v.normalized * (sphereRadius - v.magnitude) * -1; } else { continue; } } else { //CollisionSphere在被碰撞体的内部 v = v.normalized * (sphereRadius + v.magnitude); } transform.position += v; _onContacted = true; } } } } } if (iter < maxIter && _onContacted) { PushBack(++iter, maxIter); } }