private void DrawWavesOnHit(ICollection <ForceFieldEffectInstanceNode> effects, Vector3 hitPosition, bool playSound) { foreach (ForceFieldEffectInstanceNode node in effects) { ForceFieldEffect component = node.effectInstance.GameObject.GetComponent <ForceFieldEffect>(); MeshCollider outerMeshCollider = component.outerMeshCollider; if (Vector3.Distance(hitPosition, outerMeshCollider.ClosestPointOnBounds(hitPosition)) < 0.1f) { component.DrawWave(hitPosition, playSound); } } }
public static void PushOutFromMesh(MeshCollider mesh, Collision collision, float pointRadius, ref Vector3 point) { Vector3 closest; float plus = 0f; closest = mesh.ClosestPointOnBounds(point); plus = (closest - mesh.transform.position).magnitude; bool inside = false; float insideMul = 1f; if (closest == point) { inside = true; insideMul = 7f; closest = mesh.transform.position; } Vector3 targeting = closest - point; Vector3 rayDirection = targeting.normalized; Vector3 rayOrigin = point - rayDirection * (pointRadius * 2f + mesh.bounds.extents.magnitude); float rayDistance = targeting.magnitude + pointRadius * 2f + plus + mesh.bounds.extents.magnitude; if ((point - closest).magnitude < pointRadius * insideMul) { Vector3 collisionPoint; if (!inside) { collisionPoint = collision.contacts[0].point; } else { Ray ray = new Ray(rayOrigin, rayDirection); RaycastHit hit; if (mesh.Raycast(ray, out hit, rayDistance)) { collisionPoint = hit.point; } else { collisionPoint = collision.contacts[0].point; } } float hitToPointDist = (point - collisionPoint).magnitude; if (hitToPointDist < pointRadius * insideMul) { Vector3 toNormal = collisionPoint - point; Vector3 pushNormal; if (inside) { pushNormal = toNormal + toNormal.normalized * pointRadius; } else { pushNormal = toNormal - toNormal.normalized * pointRadius; } float dot = Vector3.Dot((collisionPoint - point).normalized, rayDirection); if (inside && dot > 0f) { pushNormal = toNormal - toNormal.normalized * pointRadius; } point = point + pushNormal; } } }
void FeedBack() { if (boundSpheres != null) { // 遍历自身所有碰撞球,若与外物有碰撞,则计算“力”反馈后的位置 for (int i = 0; i < boundSpheres.Length; ++i) { BoundSphere sphere = boundSpheres[i]; if (sphere == null) { continue; } foreach (Collider collider in Physics.OverlapSphere(OffsetPosition(sphere.offset), sphere.radius, _collidable)) { Vector3 position = OffsetPosition(sphere.offset); Vector3 contactPoint = Vector3.zero; if (collider.gameObject == _target.gameObject) { continue; // 排除自身 } if (collider.isTrigger) { continue; } if (collider is BoxCollider) { contactPoint = TransformTools.Instance.ClosestPoint((BoxCollider)collider, position); } else if (collider is SphereCollider) { contactPoint = TransformTools.Instance.ClosestPoint((SphereCollider)collider, position); } else if (collider is MeshCollider) { TriangleTreeMgr ttm = collider.GetComponent <TriangleTreeMgr>(); if (ttm == null) { ttm = collider.gameObject.AddComponent <TriangleTreeMgr>(); } if (ttm != null) { contactPoint = ttm.ClosestPointOn(position, sphere.radius, displayDebugInfo, displayExtendedDebugInfo); } else { // Make last ditch try for convex colliders MeshCollider mc = (MeshCollider)collider; if (mc.convex) { contactPoint = mc.ClosestPointOnBounds(position); } else { continue; } } } else if (collider is CapsuleCollider) { contactPoint = TransformTools.Instance.ClosestPoint((CapsuleCollider)collider, position); } else if (collider is TerrainCollider) { // 无须处理,地面和foot的碰撞检测在其它模块 } else if (collider is WheelCollider) { Debug.LogWarning("[Moter] WheelColliders not supported"); } else { continue; } if (contactPoint != Vector3.zero) { // If the sphere is feet // We have a ground and we're touching // And the sphere position is above the contact position // We should ignore it if (sphere.isFeet && IsOnGround && position.y > contactPoint.y) { continue; } // If this is the head sphere // And we're jumping // And we hit the "top" of the sphere, abort jumping if (sphere.isHead && IsJumping && contactPoint.y > (position.y + sphere.radius * 0.25f)) { JumpDone(null); } // Vector from contact point to position Vector3 v = position - contactPoint; // Draw debug line if (displayDebugInfo) { Debug.DrawLine(position, contactPoint, Color.red); } // Display extend debug info if (displayExtendedDebugInfo) { Debug.Log("[Moter] Contact point " + contactPoint); } // Move object away from collision _target.position += Vector3.ClampMagnitude(v, Mathf.Clamp(sphere.radius - v.magnitude, 0, sphere.radius)); } } } } }
void PushBack() { if (spheres != null) { for (int i = 0; i < spheres.Length; ++i) { CollisionSphere s = spheres[i]; if (s != null) { foreach (Collider collider in Physics.OverlapSphere(OffsetPosition(s.Offset), bodyRadius, walkable)) { Vector3 position = OffsetPosition(s.Offset); Vector3 contactPoint = Vector3.zero; if (collider is BoxCollider) { contactPoint = RPGCollisions.ClosestPointOn((BoxCollider)collider, position); } else if (collider is SphereCollider) { contactPoint = RPGCollisions.ClosestPointOn((SphereCollider)collider, position); } else if (collider is MeshCollider) { RPGMesh rpgMesh = collider.GetComponent <RPGMesh>(); if (rpgMesh != null) { contactPoint = rpgMesh.ClosestPointOn(position, bodyRadius, displayDebugInfo, displayExtendedDebugInfo); } else { // Make last ditch try for convex colliders MeshCollider mc = (MeshCollider)collider; if (mc.convex) { contactPoint = mc.ClosestPointOnBounds(position); } else { continue; } } } else if (collider is CapsuleCollider) { Debug.LogWarning("[RPGMotor] CapsuleCollider not supported"); } else if (collider is TerrainCollider) { } else if (collider is WheelCollider) { Debug.LogWarning("[RPGMotor] WheelColliders not supported"); } else { continue; } if (contactPoint != Vector3.zero) { // If the sphere is feet // We have a ground and we're touching // And the sphere position is above the contact position // We should ignore it if (s.IsFeet && HasGround && CurrentGround.IsTouching && position.y > contactPoint.y) { continue; } // If this is the head sphere // And we're jumping // And we hit the "top" of the sphere, abort jumping if (s.IsHead && IsJumping && contactPoint.y > (position.y + bodyRadius * 0.25f)) { JumpDone(null); } // Vector from contact point to position Vector3 v = position - contactPoint; // Draw debug line if (displayDebugInfo) { Debug.DrawLine(position, contactPoint, Color.red); } // Display extend debug info if (displayExtendedDebugInfo) { Debug.Log("[RPGMotor] Contact point " + contactPoint); } // Move object away from collision target.position += Vector3.ClampMagnitude(v, Mathf.Clamp(bodyRadius - v.magnitude, 0, bodyRadius)); } } } } } }
void PushBack() { if (spheres != null) { for (int i = 0; i < spheres.Length; ++i) { CollisionSphere s = spheres[i]; if (s != null) { foreach (Collider collider in Physics.OverlapSphere(OffsetPosition(s.Offset), bodyRadius, walkable)) { Vector3 position = OffsetPosition(s.Offset); Vector3 contactPoint = Vector3.zero; if (collider is BoxCollider) { contactPoint = RPGCollisions.ClosestPointOn((BoxCollider)collider, position); } else if (collider is SphereCollider) { contactPoint = RPGCollisions.ClosestPointOn((SphereCollider)collider, position); } else if (collider is MeshCollider) { RPGMesh rpgMesh = collider.GetComponent <RPGMesh>(); if (rpgMesh != null) { contactPoint = rpgMesh.ClosestPointOn(position, bodyRadius, displayDebugInfo, displayExtendedDebugInfo); } else { MeshCollider mc = (MeshCollider)collider; if (mc.convex) { contactPoint = mc.ClosestPointOnBounds(position); } else { continue; } } } else if (collider is CapsuleCollider) { } else if (collider is TerrainCollider) { } else if (collider is WheelCollider) { Debug.LogWarning("[RPGMotor] WheelColliders not supported"); } else { continue; } if (contactPoint != Vector3.zero) { //如果这个sphere是脚 //我们接触一个地面 //并且球的位置在接触位置之上 //我们应该忽略它 if (s.IsFeet && HasGround && CurrentGround.IsTouching && position.y > contactPoint.y) { continue; } //如果这个球是头 //并且跳跃 //并且撞到了头,就终止跳跃 if (s.IsHead && IsJumping && contactPoint.y > (position.y + bodyRadius * 0.25f)) { JumpDone(null); } Vector3 v = position - contactPoint; if (displayDebugInfo) { Debug.DrawLine(position, contactPoint, Color.red); } if (displayExtendedDebugInfo) { //Debug.Log("[RPGMotor] Contact point " + contactPoint); } target.position += Vector3.ClampMagnitude(v, Mathf.Clamp(bodyRadius - v.magnitude, 0, bodyRadius)); } } } } } }
/// <summary> /// 获取MeshCollider上距离target最近的点(不能用!没效果) /// </summary> public Vector3 ClosestPoint(MeshCollider collider, Vector3 target) { return(collider.ClosestPointOnBounds(target)); // (不能用!没效果) }