Essentially what I’d like is to
(1). Have my controller slide down slopes say slopeX > 45
(2). Stop my controller from bouncing when moving down a non steep slope say slopeX < 45
(the current hypothesis and starting point is
if(objectHitAngle > player.slopeLimit)
{
isSliding = true;
//from here do what? and where?
//You will see a quick not so great solution starter Vector3.OrthoNormalize(ref groundObjectNormal, ref movement);
}
I have reviewed several tutorials on character controllers and I have managed to make a decent one. What is being a HUGE pain is slopes and all of the solutions I have found are infinitely confusing for me. Many of them seem great but I just cannot understand them. I will provide my code and all the comments I have made to manage it and understand it.
Really quick to summarize, all movement is based on input axis. The character has a constant force applied so it stays grounded. When falling and !isGrounded, the falling speed multiplies or increases. When isGrounded, the falling force resets to a constant value to ensure I may jump. Additive force will cause too much force where you may not even jump. (Reason for reset)
void Awake()
{
player = GetComponent<CharacterController>();
anim = transform.Find("Character").GetComponent<Animator>();
}
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update ()
{
playerControl();
updateMovementAnimation();
fightTransition();
}
void playerControl()
{
//Assigning values to a float based on Input
moveFB = Input.GetAxis("Vertical") * speed;
moveLR = Input.GetAxis("Horizontal") * speed;
//Sprint
if(Input.GetButton("Fire3"))
{
isSprinting = true;
moveFB = moveFB * sprintMultiplier;
moveLR = moveLR * sprintMultiplier;
anim.SetBool("isSprinting", true);
}
else
{
isSprinting = false;
anim.SetBool("isSprinting", false);
}
//place values in a vector 3 called movement
Vector3 movement = new Vector3(moveLR, verticalVelocity, moveFB);
//Add forward physics to transform, commented out for now to minimize other errors
//transform.Translate(moveLR * Time.deltaTime, 0, moveFB * Time.deltaTime);
//Keeps the movement overall speed at a 1:1 ratio. So double key press won't multiply speed
if (player.isGrounded) //if theres no check, the player will continue falling at same speed
{
//clamps values to avoid any movement is doubled if traveling in two+ directions
if (isSprinting) { movement = Vector3.ClampMagnitude(movement, speed * sprintMultiplier); }
else { movement = Vector3.ClampMagnitude(movement, speed); }
}
//Debug.Log(movement); THIS OUtPUTS PROPERLY RIGHT HERE
if (isSliding)
{
//made small progress, doesnt quite work yet
Vector3.OrthoNormalize(ref groundObjectNormal, ref movement);
}
//movement is frame independent
movement *= Time.deltaTime;
//When rotated by mouse, it rotates local but moves forward on world, so here you align the rotation to world By using movement = transform.rotation * movement; or below local to global
movement = transform.TransformDirection(movement);
//Move is called and requires a Vector 3. Assign Vector 3 to move and make it frame independent
player.Move(movement);
if (player.isGrounded)
{
anim.SetBool("isGrounded", true);
if (Input.GetButtonDown("Jump") )
{
isJumping = true;
verticalVelocity += jumpDistance;
anim.SetBool("Jump", true);
}
}
//------------------------------------------****MOUSE****-------------------------------------------------//
mouseRotX = Input.GetAxis("Mouse X") * mouseSensitivityX;
mouseRotY -= Input.GetAxis("Mouse Y") * mouseSensitivityY;
mouseRotY = Mathf.Clamp(mouseRotY, -mouseYCap, mouseYCap);
//rotate the player LR by mouse movement;
transform.Rotate(0, mouseRotX, 0);
//rotates the camera up and down, if you mix with x, the entire player is rotated 360, no buno
playerCam.transform.localRotation = Quaternion.Euler(mouseRotY, 0, 0); //switch mouseRotY to negative for invert
}
//**JUMP PHYSICS & isGrounded
private void FixedUpdate()//runs every other frame instead of every frame
{
//player is constantly falling, on one its a constant speed, on the other its additive speed
if (player.isGrounded)
{
if (isJumping)
{
//this was not allowing jump and overwriting
isJumping = false;
return;
}
else
{
//Constamt Same Fall Force
//reset gravity so the collision detection works. If set vertVelocity to 0 unity ignores collision detection
anim.SetBool("Jump", false);
verticalVelocity = Physics.gravity.y * Time.deltaTime; //Gravity pulls you down faster and faster based on how much time has gone by. BUILT IN!
}
}
else
{
//add fall force over time
anim.SetBool("isGrounded", false);
verticalVelocity += Physics.gravity.y * Time.deltaTime;
}
if(objectHitAngle > player.slopeLimit)
{
isSliding = true;
}
else { isSliding = false; }
}