Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Unity Character Controller Problems

Discussion in 'Scripting' started by 420BlazeIt, Dec 5, 2016.

  1. 420BlazeIt

    420BlazeIt

    Joined:
    Aug 14, 2014
    Posts:
    102
    Hi guys I'm working on a 3D FPS game and I've encountered 2 problems.

    1. Character controller sinks when on edges due to the capsule shape
    Can be seen in this video:


    2. Walking down ramps is bumpy
    Can be seen in this video:


    You can fix the edge sinking by ray casting down from the front, back, left and right sides of the circumference of the character controller and using that as a ground check. (If no rays hit => start falling). I got this to work and it works quite well until you add the fix for bumpy slopes.

    You can fix bumpy slopes by doing playerVelocity.y -= stickToGroundForce. But this adds edge sinking again... It's like both fixes cancel each other out. Please no answers like "switch to rigidbody". I want to fix the problem not just switch to Rigidbody.

    Can anyone help please?
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    To fix the bumpy downhill, instead of always adding a force or velocity forwards relative to the player, try to add the force perpendicular to the ground normal. That way you're not moving forwards then falling again and again, you're moving diagonally along the surface.
     
  3. 420BlazeIt

    420BlazeIt

    Joined:
    Aug 14, 2014
    Posts:
    102
    I know what you mean but how do you write that in code? I have tried
    Code (CSharp):
    1. Vector3 temp = Vector3.Cross(groundPlane.normal, playerVelocity);
    2. playerVelocity = Vector3.Cross(temp, groundPlane.normal);
    but that just made walking up the ramp slower and walking down it still caused bumping
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    I was imagining that wherever you're applying forward motion, ie (transform.right * speed * Time.deltaTime), instead of using transform.right, you would use a vector parallel to the ground.

    pseudocode:
    Code (CSharp):
    1. Vector2 vector2 = ground.normal;
    2. // facing right
    3. Vector2 perpendicularClockwise = new Vector2(-vector2.Y, vector2.X);
    4. // facing left
    5. Vector2 perpendicularCounterClockwise = new Vector2(vector2.Y, -vector2.X);
    6.  
    7. Vector2 playerVelocity = perpendicularVector * speed * Time.deltaTime;
    8.  
    Perhaps you can use Vector3.ProjectOnPlane to project the X velocity onto the ground plane:
    https://docs.unity3d.com/ScriptReference/Vector3.ProjectOnPlane.html
     
    Last edited: Dec 5, 2016
  5. 420BlazeIt

    420BlazeIt

    Joined:
    Aug 14, 2014
    Posts:
    102
    This code seems to be written for a 2d game? My game is actually 3d :) I just found those videos had the same problem as me and showed it clearly. How would you write it for a 3d game? Thanks for the replies.
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    You're right, but that should still work if you don't use the Z axis at all. The Vector2 represents forward and up, regardless of which axes you actually use.

    Try using the function "Vector3.ProjectOnPlane" to project your character's velocity onto the ground plane for forward forces.

    I haven't tested any of this so I'm just trying to give you some ideas that I would try:
    Code (CSharp):
    1. Vector3 forwardVelocity = Input.GetAxis("Horizontal") * transform.right * speed * Time.deltaTime;
    2. forwardVelocity = Vector3.ProjectOnPlane(forwardVelocity, groundPlane.normal);
    3.  
    4. transform.position += forwardVelocity;
     
    Last edited: Dec 5, 2016