Last active
February 8, 2017 21:49
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void CheckCurrentSegment(ParticleSystem startZone, ParticleSystem endZone) | |
{ | |
//We have a start and end position - A and B. | |
A = startZone.transform.position; | |
B = endZone.transform.position; | |
//We have a Vector3 named AB which represents the line from A to B. | |
//D will represent the closest point to the player that lies along the line AB. | |
D = Vector3.zero; | |
foreach (Player player in GameManager.Instance.players) | |
{ | |
//C represents the player's position | |
C = player.transform.position; | |
//Define A to B by subtracting A's worldspace coord from B. | |
AB = B - A; | |
//Here is where we find the progressive travel down the line AB where D will fall. | |
float t = Vector3.Dot(C - A, AB) / Vector3.Dot(AB, AB); | |
//Create D by taking the percentage travel multiplied by the line (so 50% travel on a 8 unit vector is a 4 unit vector) | |
//Add that vector to A and we have the location of D in worldspace. | |
D = A + t * AB; | |
//We don't need to create these vectors but I've done so for readability. | |
//Find the distance from the player to the various points. | |
Vector3 playerToD = player.transform.position - D; | |
Vector3 playerToA = player.transform.position - A; | |
Vector3 playerToB = player.transform.position - B; | |
//If the distance from the player to D is less than the radius of the current, we assume the player is within the current | |
if (playerToD.sqrMagnitude < currentRadius * currentRadius) | |
{ | |
//The point D could potentially be outside of the two points | |
//The point D can be outside of the line if this situation occurs: | |
// | |
// C | |
// | | |
// | | |
// D A--------B | |
bool betweenPoints = false; | |
bool nearANode = false; | |
bool nearBNode = false; | |
bool overInputThreshhold = false; | |
//T can potentially be negative or greater than one | |
if (t > 0 && t < 1f) | |
{ | |
//So we evaluate being between the points to handle the different cases accordingly. | |
betweenPoints = true; | |
} | |
//If we're close to either end point, we want to know this. | |
if (playerToA.sqrMagnitude < currentRadius * currentRadius) | |
{ | |
nearANode = true; | |
} | |
if (playerToA.sqrMagnitude < currentRadius * currentRadius) | |
{ | |
nearBNode = true; | |
} | |
//This is how the player escapes the air current. | |
//One part listening to the player input | |
float reverseInputAmt = 1 - Mathf.Clamp(player.controller.inputAmt, 0, 1); | |
//Another part recognizing if the player has been recently affected by a | |
// strong force that should knock them from the current | |
if (reverseInputAmt < .5f || player.controller.forceAmt > 2) | |
{ | |
overInputThreshhold = true; | |
} | |
if (!overInputThreshhold) | |
{ | |
//This makes the outer edges of the current not as potent. | |
float distanceFallOffMultiplier = Mathf.Clamp(1 - (playerToD.magnitude / currentRadius), 0.5f, 1.0f); | |
//Debug.Log("D Falloff: " + distanceFallOffMultiplier + "\n"); | |
//If the player is between the nodes or near a node | |
//Set their velocity equal to zero | |
//Disregard gravity | |
//Apply a force that pushes them towards the next node & to the center. | |
//The force applied is semi-negated if they are being affected by other sources. | |
//This isn't the greatest if check but it gets the job done. | |
//Other components going on: The near node cases of A and B, B | |
// The near node cases of A and B are different from between. B doesn't push player to the center, so if they walk near the exit, force is in the direction of the current and doesn't push the player to the middle. | |
// The distance fall off multiplier is clamped to half as powerful, so the current applies effect | |
if (betweenPoints) | |
{ | |
player.controller.mRigidBody.velocity = Vector3.zero; | |
player.controller.mRigidBody.useGravity = false; | |
player.controller.ApplyConstantForce(distanceFallOffMultiplier * reverseInputAmt * AB.normalized * pushSpeed + -playerToD * pushSpeed / 5, true, true); | |
//Tracking if the player is in a current is gameplay relevant - say a player did bonus damage in a current, etc. | |
player.controller.InCurrent = true; | |
} | |
else if (nearANode) | |
{ | |
player.controller.mRigidBody.velocity = Vector3.zero; | |
player.controller.mRigidBody.useGravity = false; | |
player.controller.ApplyConstantForce(distanceFallOffMultiplier * reverseInputAmt * AB.normalized * pushSpeed + -playerToD * pushSpeed / 5, true, true); | |
//Tracking if the player is in a current is gameplay relevant - say a player did bonus damage in a current, etc. | |
player.controller.InCurrent = true; | |
} | |
else if (nearBNode) | |
{ | |
player.controller.mRigidBody.velocity = Vector3.zero; | |
player.controller.mRigidBody.useGravity = false; | |
player.controller.ApplyConstantForce(distanceFallOffMultiplier * reverseInputAmt * AB.normalized * pushSpeed, true, true); | |
//Tracking if the player is in a current is gameplay relevant - say a player did bonus damage in a current, etc. | |
player.controller.InCurrent = true; | |
} | |
} | |
} | |
else | |
{ | |
player.controller.mRigidBody.useGravity = true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment