Skip to content

Instantly share code, notes, and snippets.

@JonathanPalmerGD
Last active February 8, 2017 21:49
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