Search Unity

how do i implement slope physics?

Discussion in 'Scripting' started by Glowball123, Feb 19, 2021.

  1. Glowball123

    Glowball123

    Joined:
    Mar 10, 2016
    Posts:
    78
    i want to implement slope physics into my 3d game so that my character moves slower when moving uphill and faster when moving downhill like in a sonic game. how do i go about doing this?
     
  2. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    You could try tracking the transform.position.y value every frame, and adjust speed as the change in y goes positive or negative, with appropriate scaling so it does everything automatically. Have a public float scalar (a value you multiply speed by) so you can test in play mode. If you can also set the overall speed, then the *actual* speed would be (speed * scalar) and would be a separate variable from speed. This is a good way to go about it because it allows the most flexibility---you can always just hard-code the main speed and set the scalar to 1 to get back to the "plain" mode.

    You also might need to manage other cases like jumping or climbing ("manage" might mean just don't track it). Those actions could have custom speeds in them already anyway.
     
  3. Glowball123

    Glowball123

    Joined:
    Mar 10, 2016
    Posts:
    78
  4. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    That's essentially the same thing---you're determining the angle each frame based on the delta y. There's no need to try and anticipate the angle of an entire slope (and in fact it would be difficult to account for all possibilities). Just see what's happening right then and adjust. You can also test only every N frames or N milliseconds (using a counter or a time function) if the changes are too rapid, or Lerp to the new speed, etc.
    BTW I was making edits to my original answer when you posted, so take another look ;)
     
  5. Glowball123

    Glowball123

    Joined:
    Mar 10, 2016
    Posts:
    78
    there are 2 things that are getting in the way for me. 1st thing is, when reading the sonic retro article what is "slope" supposed to be in this line of code?
    gsp -= slope*sin(ang);
    it doesnt really properly explain it, or atleast it doesnt make sense to me.
    and 2nd how would i go about getting the angle of the surface below the player in 3d so that i can use it in that line of code?
     
  6. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    You can get angles with Atan2 if you know delta x and y, check the docs.

    In 3D, this "delta x" would be the total change in position in X and Z, not just X (assuming your Y is vertical in your game world, that is, the player jumps in Y). So each time you measure delta y, measure the others, and you can determine the angle.

    But again, I don't think you need the angle per se. Just check how much the y changes over a frame (or several frames), then change your speed scale factor. Playtest until it feels right and you're done.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    You can raycast down at the ground under the player.

    The raycasting method can give you a RaycastHit object that contains the normal of the contact point.

    The angle of the surface would then be the arctangent of the vertical vs the horizontal parts of the normal. (I think I computed that right... :) )
     
  8. Glowball123

    Glowball123

    Joined:
    Mar 10, 2016
    Posts:
    78
    but arctangent takes in 2 floats and returns a float. dont i need something that returns atleast 2 floats for the horizontal and vertical movement when going up the slope?
     
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    Oh I got you... what I suggested above is just pure angular slope as a single angle.

    You would just need individual values in each cardinal X/Z direction to correctly affect your intended motion.

    So the slowing effect on X would be equal to -X and same with Z = -Z

    A normal vector sticking straight up is (0,1,0) so X and Z are both zero on the flat, so no bias to your motion.

    This is all with X,Y,Z directly out of that normal vector.

    You can then decide how you want to scale that to get the behavior you want. I would just make an AnimationCurve so you can tweak how it feels easily in the editor, and use that curve to look up how much to add/remove from motion.
     
    seejayjames likes this.
  10. Glowball123

    Glowball123

    Joined:
    Mar 10, 2016
    Posts:
    78
    Vector3 move = movementDir - new Vector3(normal.x,0,normal.z) * speed;

    like this?
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    That would give you a simple linear mapping, scaled only by that final term you are calling "speed".

    I would rename that speed value to be something like "EffectOfSlopeOnSpeed"