private void CastRaysAbove() { float rayLength = State.IsGrounded?RayOffset : _newPosition.y * Time.deltaTime; rayLength += _rayBoundsRectangle.height / 2; bool hitConnected = false; int hitConnectedIndex = 0; Vector2 verticalRayCastStart = new Vector2(_rayBoundsRectangle.xMin + _newPosition.x, _rayBoundsRectangle.center.y); Vector2 verticalRayCastEnd = new Vector2(_rayBoundsRectangle.xMax + _newPosition.x, _rayBoundsRectangle.center.y); RaycastHit2D[] hitsStorage = new RaycastHit2D[NumberOfVerticalRays]; for (int i = 0; i < NumberOfVerticalRays; i++) { Vector2 rayOriginPoint = Vector2.Lerp(verticalRayCastStart, verticalRayCastEnd, (float)i / (float)(NumberOfVerticalRays - 1)); hitsStorage[i] = GameTools.GameRaycast(rayOriginPoint, Vector2.up, rayLength, PlatformMask & ~EdgeColliderPlatformMask, true, Color.green); if (hitsStorage[i]) { hitConnected = true; hitConnectedIndex = i; break; } } if (hitConnected) { _speed.y = 0; _newPosition.y = hitsStorage[hitConnectedIndex].distance - _rayBoundsRectangle.height / 2; State.IsCollidingAbove = true; } }
private void CastRaysBelow() { if (_newPosition.y < -_smallValue) { State.IsFalling = true; } else { State.IsFalling = false; } if ((Parameters.Gravity > 0) && (!State.IsFalling)) { return; } float rayLength = _rayBoundsRectangle.height / 2 + RayOffset; if (_newPosition.y < 0) { rayLength += Mathf.Abs(_newPosition.y); } Vector2 verticalRayCastFromLeft = new Vector2(_rayBoundsRectangle.xMin + _newPosition.x, _rayBoundsRectangle.center.y + RayOffset); Vector2 verticalRayCastToRight = new Vector2(_rayBoundsRectangle.xMax + _newPosition.x, _rayBoundsRectangle.center.y + RayOffset); RaycastHit2D[] hitsStorage = new RaycastHit2D[NumberOfVerticalRays]; float smallestDistance = _largeValue; int smallestDistanceIndex = 0; bool hitConnected = false; for (int i = 0; i < NumberOfVerticalRays; i++) { Vector2 rayOriginPoint = Vector2.Lerp(verticalRayCastFromLeft, verticalRayCastToRight, (float)i / (float)(NumberOfVerticalRays - 1)); if ((_newPosition.y > 0) && (!State.WasGroundedLastFrame)) { hitsStorage[i] = GameTools.GameRaycast(rayOriginPoint, -Vector2.up, rayLength, PlatformMask & ~EdgeColliderPlatformMask, true, Color.blue); } else { hitsStorage[i] = GameTools.GameRaycast(rayOriginPoint, -Vector2.up, rayLength, PlatformMask, true, Color.blue); } if ((Mathf.Abs(hitsStorage[smallestDistanceIndex].point.y - verticalRayCastFromLeft.y)) < _smallValue) { break; } if (hitsStorage[i]) { hitConnected = true; if (hitsStorage[i].distance < smallestDistance) { smallestDistanceIndex = i; smallestDistance = hitsStorage[i].distance; } } } if (hitConnected) { State.IsFalling = false; State.IsCollidingBelow = true; _newPosition.y = -Mathf.Abs(hitsStorage[smallestDistanceIndex].point.y - verticalRayCastFromLeft.y) + _rayBoundsRectangle.height / 2 + RayOffset; if (_externalForce.y > 0) { _newPosition.y += _speed.y * Time.deltaTime; State.IsCollidingBelow = false; } if (!State.WasGroundedLastFrame && _speed.y > 0) { _newPosition.y += _speed.y * Time.deltaTime; } if (Mathf.Abs(_newPosition.y) < _smallValue) { _newPosition.y = 0; } StandingOn = hitsStorage[smallestDistanceIndex].collider.gameObject; PathFollow movingPlatform = hitsStorage[smallestDistanceIndex].collider.GetComponent <PathFollow>(); if (movingPlatform != null) { _transform.Translate(movingPlatform.CurrentSpeed * Time.deltaTime); } } else { State.IsCollidingBelow = false; } }
//角色左右上下射線碰撞偵測 private void CastRaysToTheSides() { float movementDirection = 1; if ((_newPosition.x < 0) || (_externalForce.x < 0)) { movementDirection = -1; } float horizontalRayLength = Mathf.Abs(_speed.x * Time.deltaTime) + _rayBoundsRectangle.width / 2 + RayOffset; Vector2 horizontalRayCastFromBottom = new Vector2(_rayBoundsRectangle.center.x, _rayBoundsRectangle.yMin + _obstacleHeightTolerance); Vector2 horizontalRayCastToTop = new Vector2(_rayBoundsRectangle.center.x, _rayBoundsRectangle.yMax); RaycastHit2D[] hitsStorage = new RaycastHit2D[NumberOfHorizontalRays]; for (int i = 0; i < NumberOfHorizontalRays; i++) { Vector2 rayOriginPoint = Vector2.Lerp(horizontalRayCastFromBottom, horizontalRayCastToTop, (float)i / (float)(NumberOfHorizontalRays - 1)); if (State.WasGroundedLastFrame && i == 0) { hitsStorage[i] = GameTools.GameRaycast(rayOriginPoint, movementDirection * Vector2.right, horizontalRayLength, PlatformMask, true, Color.red); } else { hitsStorage[i] = GameTools.GameRaycast(rayOriginPoint, movementDirection * Vector2.right, horizontalRayLength, PlatformMask & ~EdgeColliderPlatformMask, true, Color.red); } if (hitsStorage[i].distance > 0) { float hitAngle = Mathf.Abs(Vector2.Angle(hitsStorage[i].normal, Vector2.up)); if (hitAngle > Parameters.MaximumSlopeAngle) { if (movementDirection < 0) { State.IsCollidingLeft = true; } else { State.IsCollidingRight = true; } State.SlopeAngleOK = false; if (movementDirection <= 0) { _newPosition.x = -Mathf.Abs(hitsStorage[i].point.x - horizontalRayCastFromBottom.x) + _rayBoundsRectangle.width / 2 + RayOffset; } else { _newPosition.x = Mathf.Abs(hitsStorage[i].point.x - horizontalRayCastFromBottom.x) - _rayBoundsRectangle.width / 2 - RayOffset; } _speed = new Vector2(0, _speed.y); break; } } } }