/** * // Find out our Y-position on the slope we're currently using * float CalculateAltitude(float progress) * { * return ground.self.position.y + ground.verticalOffset * ground.self.localScale.y + ground.yScale * ground.slopeCurve.Evaluate(progress) * ground.self.localScale.y; * } * * // Called at each grounded movement * bool UpdateSlope() * { * float progress = (self.position.x - ground.xMin) / (ground.xMax - ground.xMin); * progress = Mathf.Clamp01(progress); * float yNeeded = CalculateAltitude(progress); * * // Manually set our Y-coordinate if we're grounded * if(bottom < yNeeded) * { * self.position = new Vector3(self.position.x, yNeeded + bottomDelta, self.position.z); * * if(!collisionFlags.down) * { * if (onCollisionEnter != null) onCollisionEnter(new RaycastHitPlus()); * if (onVerticalCollisionEnter != null) onVerticalCollisionEnter(new RaycastHitPlus()); * } * * collisionFlags.down = true; * } * if(self.position.y == yNeeded + bottomDelta) collisionFlags.down = true; * * return bottom <= yNeeded; * } * * // Get the angle of the current slope based on the altitude "just behind us" and "just in front of us". * float FindAngle() * { * if(!ground || ignoreSlopeZones) return 0; * * float result = 0; * * float prevProgress = (self.position.x - stepSize - ground.xMin) / (ground.xMax - ground.xMin); * prevProgress = Mathf.Clamp01(prevProgress); * float yPrev = CalculateAltitude(prevProgress); * * float nextProgress = (self.position.x + stepSize - ground.xMin) / (ground.xMax - ground.xMin); * nextProgress = Mathf.Clamp01(nextProgress); * float yNext = CalculateAltitude(nextProgress); * * Vector2 before = new Vector2(self.position.x - stepSize, yPrev); * Vector2 after = new Vector2(self.position.x + stepSize, yNext); * Vector2 curSlope = after-before; * * // If we're descending, let's say the angle equals zero (unless we want a slight acceleration, which is rarely the case) * if (Mathf.Sign(curSlope.y) != Mathf.Sign(graphics.localScale.x)) result = 0; * // When ascending, we must get the angle anyway. * else result = Vector2.Angle(Vector2.right, curSlope); * * return result; * } * * // Called when we might hit a ceiling. Same logic as UpdateSlope(). * bool UpdateCeiling() * { * float progress = (self.position.x - ceiling.xMin) / (ceiling.xMax - ceiling.xMin); * progress = Mathf.Clamp01(progress); * * float yNeeded = (ceiling.self.position.y + ceiling.verticalOffset - ceiling.zoneHeight) + ceiling.yScale * ceiling.ceilingCurve.Evaluate(progress); * * if (top > yNeeded) * { * self.position = new Vector3(self.position.x, yNeeded + topDelta, self.position.z); * * if(!collisionFlags.up) * { * if (onCollisionEnter != null) onCollisionEnter(new RaycastHitPlus()); * if (onVerticalCollisionEnter != null) onVerticalCollisionEnter(new RaycastHitPlus()); * } * * collisionFlags.up = true; * } * if (self.position.y == yNeeded + topDelta) collisionFlags.up = true; * * return top >= yNeeded; * } * /**/ #endregion #region Movement private void MoveHorizontally(ref Vector3 deltaMovement) { float length = Mathf.Abs(deltaMovement.x) + skinWidth; bool isGoingRight = deltaMovement.x > 0; RayDirection dir = isGoingRight ? RayDirection.Right : RayDirection.Left; RaycastHitPlus result = raycaster.CastRays(dir, length); if (result.box != null) { // stop the horizontal movement as we bumped into something deltaMovement.x = 0; // flip the collision flags if (isGoingRight) { collisionFlags.right = true; } else { collisionFlags.left = true; } // And finally, call events if (onCollisionEnter != null) { onCollisionEnter(result); } if (onHorizontalCollisionEnter != null) { onHorizontalCollisionEnter(result); } } }
// Could be used for scale and rotation : cast rays in 4 directions simultaneously public RaycastHitPlus CastRaysEverywhere(float length) { RefreshRayOrigins(); RaycastHitPlus result = CastRays(RayDirection.Left, length, true); if (result.box != null) { return(result); } result = CastRays(RayDirection.Right, length, true); if (result.box != null) { return(result); } result = CastRays(RayDirection.Up, length, true); if (result.box != null) { return(result); } result = CastRays(RayDirection.Down, length, true); return(result); }
CharacterController2D FindGround() { RaycastHitPlus hit = raycaster.CastRays(RayDirection.Down, 5 * skinWidth, true); if (hit.box == null) { return(null); } return(hit.box.GetComponent <CharacterController2D>()); }
private void MoveVertically(ref Vector3 deltaMovement) { //if (disableVerticalPhysics) return; bool isGoingUp = deltaMovement.y > 0; float length = Mathf.Abs(deltaMovement.y) + skinWidth; RayDirection dir = isGoingUp ? RayDirection.Up : RayDirection.Down; RaycastHitPlus result = raycaster.CastRays(dir, length, false); if (result.box) { // set our new deltaMovement and recalculate the rayDistance taking it into account deltaMovement.y = result.hit.point.y - result.ray.y; // remember to remove the skinWidth from our deltaMovement if (isGoingUp) { deltaMovement.y -= skinWidth; collisionFlags.up = true; } else { deltaMovement.y += skinWidth; collisionFlags.down = true; } // Watch out, the global event could be called twice (one for horizontal movement, one for vertical movement). if (onCollisionEnter != null) { onCollisionEnter(result); } if (onVerticalCollisionEnter != null) { onVerticalCollisionEnter(result); } } }