/// <summary> /// Whether the controller is on the surface given the terrain cast results. This doesn't affect /// the controller's physics, but rather will not invoke surface events if false. /// </summary> /// <param name="hit">The terrain cast results.</param> /// <returns></returns> public bool IsOnSurface(TerrainCastHit hit) { if (SurfaceRules.Count == 0) { return(DefaultSurfaceRule(hit)); } for (var i = 0; i < SurfaceRules.Count; ++i) { if (!SurfaceRules[i](hit)) { return(false); } } if (Parents.Count == 0) { return(true); } for (var i = 0; i < Parents.Count; ++i) { var parent = Parents[i]; if (!ReceivesEvents(parent, transform)) { return(false); } } return(true); }
public override void OnPlatformEnter(TerrainCastHit hit) { // Must be hit from the air if (hit.Controller == null || hit.Controller.Grounded) { return; } // Must be hit from the player's bottom side if (hit.Side != ControllerSide.Bottom || hit.Controller.RelativeVelocity.y > 0.0f) { return; } // Player must be in a roll if (!hit.Controller.IsPerforming <Roll>()) { return; } hit.Controller.IgnoreThisCollision(); hit.Controller.RelativeVelocity = new Vector2(hit.Controller.RelativeVelocity.x, BounceSpeed); ActivateObject(hit.Controller); Destroy(gameObject); }
// Removes the anchor associated with the hit.Source public override void OnSurfaceExit(TerrainCastHit hit) { if (!_anchors.ContainsKey(hit.Controller)) { return; } var anchor = _anchors[hit.Controller]; var velocity = (Vector2)anchor.DeltaPosition / Time.fixedDeltaTime; if (hit.Controller.Grounded) { if (TransferMomentumGround) { hit.Controller.PushOnGround(velocity); } } else { hit.Controller.Velocity += new Vector2( TransferMomentumX ? velocity.x : 0.0f, TransferMomentumY ? velocity.y : 0.0f); } _anchors.Remove(hit.Controller); Destroy(anchor.gameObject); }
public override void OnPlatformStay(TerrainCastHit hit) { if (!ObjectTrigger.Activated) { OnPlatformEnter(hit); } }
public override void OnPlatformEnter(TerrainCastHit hit) { if (hit.Controller == null || !hit.Controller.Grounded) { return; } if (hit.Side == ControllerSide.Bottom || hit.Side == ControllerSide.Top) { return; } var moveManager = hit.Controller.GetComponent <MoveManager>(); if (moveManager == null || moveManager.IsActive <Roll>() || Mathf.Abs(hit.Controller.GroundVelocity) < MinGroundSpeed) { return; } hit.Controller.IgnoreThisCollision(); ActivateObject(hit.Controller); Destroy(gameObject); if (FreezeTime <= 0.0f) { return; } hit.Controller.Interrupt(FreezeTime); }
public override void OnPlatformExit(TerrainCastHit hit) { if (!WhenColliding) { return; } DeactivateObject(hit.Controller); }
// Restores old physics values. public override void OnSurfaceExit(TerrainCastHit hit) { var groundControl = hit.Controller.GetComponent <MoveManager>().Get <GroundControl>(); groundControl.Acceleration /= Friction; groundControl.Deceleration /= Friction; hit.Controller.GroundFriction /= Friction; }
public override void OnSurfaceEnter(TerrainCastHit hit) { if (!RestoreOnExit) { return; } _oldGravities[hit.Controller.GetInstanceID()] = hit.Controller.GravityDirection; }
public override void OnSurfaceExit(TerrainCastHit hit) { if (!WhenOnSurface) { return; } DeactivateObject(hit.Controller); }
public override void OnSurfaceStay(TerrainCastHit hit) { var controller = hit.Controller; if (hit.Controller == null) { return; } var oldVelocity = controller.GroundVelocity; if (AccelerateBothWays) { if (AccountForFriction) { controller.GroundVelocity += (controller.GroundFriction + Acceleration) * Mathf.Sign(controller.GroundVelocity) * Time.fixedDeltaTime; } else { controller.GroundVelocity += Acceleration * Mathf.Sign(controller.GroundVelocity) * Time.fixedDeltaTime; } var absTargetVg = Mathf.Abs(TargetVelocity); if (Mathf.Abs(oldVelocity) < absTargetVg && Mathf.Abs(controller.GroundVelocity) > absTargetVg) { controller.GroundVelocity = TargetVelocity * Mathf.Sign(controller.GroundVelocity); } } else { if (AccountForFriction) { controller.GroundVelocity += (Acceleration + controller.GroundFriction * Mathf.Sign(Acceleration)) * Time.fixedDeltaTime; } else { controller.GroundVelocity += Acceleration * Time.fixedDeltaTime; } if (TargetVelocity > 0.0f) { if (oldVelocity < TargetVelocity && controller.GroundVelocity > TargetVelocity) { controller.GroundVelocity = TargetVelocity; } } else { if (oldVelocity > TargetVelocity && controller.GroundVelocity < TargetVelocity) { controller.GroundVelocity = TargetVelocity; } } } }
/// <summary> /// Lets the trigger know about a controller standing on its surface. /// </summary> /// <param name="hit">The collision data.</param> public void NotifySurfaceCollision(TerrainCastHit hit, bool bubble) { if (!IsOnSurface(hit)) { return; } for (var i = 0; i < SurfaceCollisions.Count; ++i) { var collision = SurfaceCollisions[i]; if (collision.Controller != hit.Controller) { continue; } for (i = 0; i < _notifiedSurfaceCollisions.Count; ++i) { var notifiedCollision = _notifiedSurfaceCollisions[i]; if (notifiedCollision.Controller == hit.Controller) { goto bubble; } } _notifiedSurfaceCollisions.Add(hit); goto bubble; } if (SurfaceEnterSound != null) { SoundManager.Instance.PlayClipAtPoint(SurfaceEnterSound, transform.position); } SurfaceCollisions.Add(hit); _notifiedSurfaceCollisions.Add(hit); OnSurfaceEnter.Invoke(hit); if (SurfaceCollisions.Count == 1 && !enabled) { enabled = true; } bubble: if (!bubble) { return; } for (var i = 0; i < Parents.Count; ++i) { var parent = Parents[i]; if (!ReceivesEvents(parent, transform)) { return; } parent.NotifySurfaceCollision(hit, false); } }
public override bool IsSolid(TerrainCastHit hit) { if (hit.Controller == null) { return(true); } return(base.IsSolid(hit) && (!RequireGroundEntry || (RequireGroundEntry && hit.Controller.Grounded && !DMath.Equalsf(hit.Hit.fraction)))); }
// The platform can be collided with if the player is checking its bottom side and // the result of the check did not stop where it started. public override bool IsSolid(TerrainCastHit hit) { // Check must be coming from player's bottom side and be close to the top // of the platform return(base.IsSolid(hit) && hit.Hit.fraction > 0.0f && (TopSolid && (hit.Side & ControllerSide.Bottom) > 0) || (BottomSolid && (hit.Side & ControllerSide.Top) > 0) || (LeftSolid && (hit.Side & ControllerSide.Right) > 0) || (RightSolid && (hit.Side & ControllerSide.Left) > 0)); }
public override void OnSurfaceExit(TerrainCastHit hit) { if (!RestoreOnExit) { return; } var instanceID = hit.Controller.GetInstanceID(); hit.Controller.GravityDirection = _oldGravities[instanceID]; _oldGravities.Remove(instanceID); }
private MovingPlatformAnchor CreateAnchor(TerrainCastHit hit) { var anchor = new GameObject().AddComponent <MovingPlatformAnchor>(); anchor.LinkController(hit.Controller); anchor.name = hit.Controller.name + "'s Moving Platform Anchor"; anchor.transform.SetParent(hit.Hit.transform); // We will update the anchor manually and lazily anchor.enabled = false; return(anchor); }
// The water is a surface if the player is upright, on top of it, grounded, not already submerged, // and running quickly enough. public override bool IsSolid(TerrainCastHit hit) { if (hit.Controller == null) { return(false); } return(base.IsSolid(hit) && (hit.Side & ControllerSide.Bottom) > 0 && hit.Hit.fraction > 0.0f && hit.Controller.Grounded && Mathf.Abs(hit.Controller.GroundVelocity) >= MinFloatSpeed); }
public override void OnPlatformStay(TerrainCastHit hit) { if (hit.Controller == null) { return; } if (CheckCrush(hit.Controller)) { TriggerObject(hit.Controller); } }
public override void OnSurfaceExit(TerrainCastHit hit) { var instanceID = hit.Controller.GetInstanceID(); if (!_originalSlopeGravities.ContainsKey(instanceID)) { return; } hit.Controller.SlopeGravity = _originalSlopeGravities[instanceID]; _originalSlopeGravities.Remove(instanceID); }
// Check if a controller leaves the platform public override void OnSurfaceExit(TerrainCastHit hit) { if (!_colliding) { return; } _colliding = false; if (Return) { DelayReturn(); } }
public override void OnPlatformEnter(TerrainCastHit hit) { var hitSide = TerrainUtility.NormalToControllerSide(hit.NormalAngle * Mathf.Rad2Deg - transform.eulerAngles.z); if ((BouncySides & hitSide) == 0) { return; } if (LockControl) { hit.Controller.GetComponent <MoveManager>().Get <GroundControl>().Lock(LockDuration); } if (!KeepOnGround) { hit.Controller.Detach(); var moveManager = hit.Controller.GetComponent <MoveManager>(); if (moveManager != null) { moveManager.End <Roll>(); moveManager.Perform <AirControl>(true); } hit.Controller.IgnoreThisCollision(); } if (AccurateBounce) { hit.Controller.Velocity = new Vector2(hit.Controller.Velocity.x * Mathf.Abs(Mathf.Sin(hit.NormalAngle)), hit.Controller.Velocity.y * Mathf.Abs(Mathf.Cos(hit.NormalAngle))); hit.Controller.Velocity += DMath.AngleToVector(hit.NormalAngle) * Power; } else { hit.Controller.Velocity = DMath.AngleToVector(hit.NormalAngle) * Power; } if (hit.Controller.Animator != null) { var logWarnings = hit.Controller.Animator.logWarnings; hit.Controller.Animator.logWarnings = false; if (!string.IsNullOrEmpty(HitTrigger)) { hit.Controller.Animator.SetTrigger(HitTrigger); } hit.Controller.Animator.logWarnings = logWarnings; } TriggerObject(hit.Controller); }
public override void OnSurfaceEnter(TerrainCastHit hit) { if (!WhenOnSurface) { return; } if (!Check(hit)) { return; } ActivateObject(hit.Controller); }
public override void OnPlatformEnter(TerrainCastHit hit) { if (!WhenColliding) { return; } if (!Check(hit)) { return; } ActivateObject(hit.Controller); }
// Updates the anchor associated with the hit.Source public override void OnSurfaceStay(TerrainCastHit hit) { if (!_anchors.ContainsKey(hit.Controller)) { return; } var anchor = _anchors[hit.Controller]; if (anchor.transform.parent != hit.Hit.transform) { anchor.transform.SetParent(hit.Hit.transform); } anchor.TranslateController(); }
// Translate the controller by the amount defined in Velocity and the direction defined by its // surface angle. public override void OnSurfaceStay(TerrainCastHit hit) { var controller = hit.Controller; if (hit.Controller == null) { return; } controller.transform.Translate(DMath.AngleToVector(controller.SurfaceAngle * Mathf.Deg2Rad) * Velocity * Time.fixedDeltaTime); _lastSurfaceAngle = controller.SurfaceAngle; }
public override void OnPlatformEnter(TerrainCastHit hit) { if (hit.Controller == null) { return; } hit.Controller.Detach(); hit.Controller.IgnoreThisCollision(); hit.Controller.RelativeVelocity = new Vector2(hit.Controller.RelativeVelocity.x, Velocity); GetComponent <Collider2D>().enabled = false; ActivateObject(hit.Controller); }
public override void OnPlatformStay(TerrainCastHit hit) { if (!WhenColliding) { return; } if (Check(hit)) { ActivateObject(hit.Controller); return; } DeactivateObject(hit.Controller); }
public override void OnSurfaceStay(TerrainCastHit hit) { if (!WhenOnSurface) { return; } if (Check(hit)) { ActivateObject(hit.Controller); return; } DeactivateObject(hit.Controller); }
public void OnCollide(TerrainCastHit hit) { // Bounce only if it's the controller's bottom colliding with the floor if ((hit.Side & ControllerSide.Bottom) == 0) { return; } // Normally we can't use a double jump again until we attach to the floor, so make // it available manually Used = false; // Set bounce velocity based on surface normal and jump input if (Input.GetButton(InputName)) { Controller.Velocity = Vector2.Reflect(Controller.Velocity, hit.Hit.normal).normalized * (Controller.Inside <Water>() ? UnderwaterBounceSpeed : BounceSpeed); } else { Controller.Velocity = Vector2.Reflect(Controller.Velocity, hit.Hit.normal).normalized * (Controller.Inside <Water>() ? UnderwaterBounceReleaseSpeed : BounceReleaseSpeed); // If the jump input is no longer held down end the move immediately End(); } // Prevent controller from landing on the surface it just hit Controller.IgnoreThisCollision(); Controller.OnCollide.RemoveListener(OnCollide); if (BounceSound != null) { // Interrupt the diving sound if (_diveAudioSource.clip == DiveSound) { _diveAudioSource.Stop(); } SoundManager.Instance.PlayClipAtPoint(BounceSound, transform.position); } Bouncing = true; if (Animator != null && BounceTriggerHash != 0) { Animator.SetTrigger(BounceTriggerHash); } }
public override bool IsSolid(TerrainCastHit hit) { if (hit == null || hit.Controller == null) { return(false); } // Similar to a ledge - only solid to the controller's bottom sensors return(hit.Side == ControllerSide.Bottom && hit.Hit.fraction > 0.0f && hit.Controller.Grounded && // Use stay speed if controller is already standing on it, entry speed otherwise (hit.Controller.StandingOn(transform) ? Mathf.Abs(hit.Controller.GroundVelocity) > MinStaySpeed : Mathf.Abs(hit.Controller.GroundVelocity) > MinEntrySpeed)); }
private bool SurfaceCollisionsRemover(TerrainCastHit hit) { for (var i = 0; i < _notifiedSurfaceCollisions.Count; ++i) { if (_notifiedSurfaceCollisions[i].Controller == hit.Controller) { return(false); } } if (SurfaceExitSound != null) { SoundManager.Instance.PlayClipAtPoint(SurfaceExitSound, transform.position); } OnSurfaceExit.Invoke(hit); return(true); }