/// <summary> /// /// </summary> /// <param name="sphere"></param> /// <returns></returns> private Vector3 SpherePosition(CollisionSphere sphere) { Vector3 ret = transform.position; ret.y += sphere.offset; return(ret); }
private void Awake() { TemporaryLayerIndex = LayerMask.NameToLayer(TemporaryLayer); currentGround = new GroundCollider(Walkable, this, triggerInteraction, Tolerance, TinyTolerance); foreach (CollisionSphere sphere in spheres) { sphere.AttachController(this); if (sphere.isFeet) { feet = sphere; } if (sphere.isHead) { head = sphere; } } if (feet == null) { Debug.LogError("[SuperCharacterController] Feet not found on controller"); } if (head == null) { Debug.LogError("[SuperCharacterController] Head not found on controller"); } if (cameraController != null) { cameraController.focus = transform; cameraController.actMotionController = this; } _lastMoveDirection = Vector3.forward; }
/// <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); } }