top of page

Coding Sample: Slope-Based Penguin Sliding

 

/*

 *  ENGINE: UNITY3D

 * LANGUAGE: C#

 * Character Controller -- Sliding Code Snippet

 * Code used in Penguin Playground Student Project.

 

 * All content © 2014 DigiPen (USA) Corporation, all rights reserved.

 

 * AUTHOR:

 * Nathaniel Marshall

 */

 

 

/*

 * This function manages and calculates the forces acting upon the Player,

 * through both Player Input and Gravity/Sloped Ground interactions.

 * When Sliding, the Player moves Automatically forward.

 * 

 * PARAMETERS:

 * Vector3 inputAxis -- a Vector3 based on the Keyboard/Gamepad Input of the Player.

 * Vector3 camForward -- the Forward vector of the main camera, used in rotating inputAxis.

 * Vector3 camRight -- the Right-hand vector of the main camera, used in rotating inputAxis.

 * Vector3 heroVelocity -- the current Velocity of the player, PLUS modifications made by previous Functions

 * 

 *

 * RETURN VALUE:

 * Vector3 forceOutput -- the force to be applied to the Player's Physics

 *

 */

 

private Vector3 Move_Sliding(Vector3 inputAxis, Vector3 camForward, Vector3 camRight, Vector3 heroVelocity)

    {

/*

* SCRIPT VARIABLES DEFINED OUTSIDE FUNCTION:

* float slide_Modifier_Hill -- ratio that the Hills affect Player Movement

* float speed_Slide_MAX -- the Maximum speed of the Player when Sliding.

* float slide_Modifier_Acceleration -- a multiplier added to the input to 

increase Player Velocity when sliding.

*

*GLOBAL FUNCTIONS USED

*HelperFuncs.DrawRay(Vector3 startPosition, Vector3 endPositionReletive,

         Color debugLineColor, float debugLineTimer)

*if the DebugMode bool is true, HelperFuncs.DrawRay() automatically draws a Debug.Ray()

*with endPositionReletive being Reletive to the startPosition.

*/

        

/*******************LOCAL VARIABLES******************/

 

//defining a blank Vector3 to be added/subtracted to as we calculate

//***forceOutput is what is ultimately returned.***

             Vector3 forceOutput = Vector3.zero;

 

//defining a Target Maximum Speed that is to change depending on Input.

float Target_MaxSpeed = speed_Slide_MAX;

 

//the Input relative to the camera. 

Vector3 slideDir;

 

//defining a Quat to rotate the Input based on the Player's Normal to the ground.

Quaternion groundInfluence = Quaternion.FromToRotation(Vector3.up, myNormal);

 

//calculating the difference between the Player's normal and straight up

//to be used in determining how Steep a Slope is.

Vector3 slopeDifference = myNormal - Vector3.up;

 

//used to calculate the slope of the Input after being rotated perpendicular to ground.

float slideAngle;

//calculate the slope of our velocity as an Angle.

float velocityAngle = Mathf.Atan2(rigidbody.velocity.z, rigidbody.velocity.x);

 

/****************************************************/

 

//calling a check to calculate if any special Forces are being applied

//based on the Terrain.

//Is TRUE if such forces exist

             if (ground.ReturnForcedDirection() != Vector3.zero)

 {

//if no/little forward input has been made, modify the input

//so that there is. This makes the player Slide Forward

//and bypasses the next If() check below.

            if (inputAxis.z <= .5f)

            {

             inputAxis.z = .5f;

            }

}

 

//Rotating the inputAxis so we move relative to the Camera.

 slideDir = (inputAxis.x * camRight + inputAxis.z * camForward);

 

//**NOTE: SPECIAL FORCES OVERRIDES FOLLOWING IF CHECK**//

//if no Input is made...

              if(inputAxis.magnitude <= .25f) 

 {

//..set the direction we're sliding in based on velocity

            slideDir = heroVelocity.normalized;

//and lower the Maximum Speed Cap. This makes the player go slower if they're

//not pressing a direction

            Target_MaxSpeed = 20;

 }

 

//draw a Debug ray based on Position and the Input Direction before Slope is accounted for.

             HelperFuncs.DrawRay(transform.position + new Vector3(0, 2, 0), slideDir, Color.green, 0.001f);

        

//rotate the slideDirection to account for the Slope of the Ground.

slideDir = groundInfluence * slideDir;

 

//draw a Debug ray from the Player's position straight up 3 units

HelperFuncs.DrawRay(transform.position, new Vector3(0,3,0), Color.black);

 

//from the top of the previous ray, draw another Debug ray displaying the influence

//of the Slope of the Ground.

HelperFuncs.DrawRay(transform.position + new Vector3(0, 3, 0), slideDir*3, Color.magenta);

 

//calculate the slope of our slideDirection (rotated Input) as an Angle.

slideAngle = Mathf.Atan2(slideDir.z, slideDir.x);

//calculate the slope of our velocity as an Angle.

velocityAngle = Mathf.Atan2(rigidbody.velocity.z, rigidbody.velocity.x);

 

//recalculating slideDirection as a Lerp step between current velocity direction

//and slideDirection (rotatedInput) based on the acceleration of Sliding.

slideDir = Vector3.Lerp(rigidbody.velocity.normalized, slideDir, slide_Modifier_Acceleration);

 

//draw a Debug ray from Player's position to the Player's Normal.

HelperFuncs.DrawRay(transform.position, myNormal * 5, Color.grey, 0.01f);

 

//check if we're below the MaximumSpeed

if(rigidbody.velocity.magnitude <= Target_MaxSpeed)

{

      forceOutput =  slideDir * slide_Modifier_Acceleration;

}

//else, check if the player is going in the exact opposite of the Slope of the ground.

//I.E., going straight up a very steep slope.

else if (Mathf.Abs(slideAngle - velocityAngle) > Mathf.PI/180)

{

//setting forceOutput to the opposite direction

//this prevents players from going up Steep Slopes

forceOutput = (slideDir - transform.forward) * slide_Modifier_Acceleration;

}

 

//Anything over .1f is considered and defined as a hill that affects Player Movement.

             if (slopeDifference.magnitude > .1f)

            {

//draw a Debug ray based on an offsetted Position and the slopeDifference

//this creates a triangle between the Vector3.Up and myNormal debugDraws.

//set behind the If check to avoid it being unnecessarily drawn when there is no Slope.

HelperFuncs.DrawRay(transform.position + new Vector3(0, 5, 0), slopeDifference * 5, Color.cyan, 0.001f);

 

//if originally had no Input, use the slopeDifference and slide_Modifier_Hillifier as acceleration

//as the Input to use.

            if (inputAxis.magnitude == 0)

            {

                forceOutput = slopeDifference * slide_Modifier_Hill;

            }

 

//Modify the forceOutput to take account of the slope.

//NOTE: This includes if no Input was made, doubling the effect of the hill.

            forceOutput += slopeDifference * slide_Modifier_Hill;

}

 

//draw a Debug ray to show the final forceOutput of this function.

HelperFuncs.DrawRay(transform.position, forceOutput * 2, Color.red, 0.01f);

 

//forceOutput is incorporated into the Physics at the end of the move_DirectedUpdate()

//after other forces are applied to it (Gravity, etc.)

return forceOutput;

    }

bottom of page