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

Question Platformer Character Turning Around - Rotating 180 on the y-axis VS Flipping the X on the Sprite

Discussion in '2D' started by bwaite87, Jan 13, 2023.

  1. bwaite87

    bwaite87

    Joined:
    Nov 23, 2017
    Posts:
    17
    Going back to the basics to get all my movement as buttery smooth as possible.
    And noticed there's an issue with my character turning around.

    I've never liked flipping platformer characters by flipping the scale to -1 on the X, or flipping the X on the sprite renderer... really only because I like the player's transform.right to always be in the direction the player is facing, saves me a lot of headaches...

    But there's a slight "jerky" movement for 1 frame when the player turns. It's not every time, though it's most times. This is using transform.Rotate(0, 180f, 0) to rotate the player AND ensure the transform.right is correct.

    In comparison, it's completely smooth using the FlipX option on the spriteRenderer, but that doesn't change the transform.right, so I'll have to re-work a LOT of stuff if I do this...I'll use that if I have to, but I'm wondering if there's a way to get the smoothness I'm looking for while also keeping the transform.Rotate method in place (or some other method I haven't thought of yet.)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    I like smooth turns too... my preferred method is to flip between 0 and 180 but to tween the value smoothly.

    Here's a simple 2.5D world example:



    This is the specific code:

    https://bitbucket.org/kurtdekker/pr...ons/Assets/Demo25DMovement/Level2DFollower.cs

    around about line 97, the UpdateVisualsFacing() method.

    The generalized version is:

    Smoothing movement between any two particular values:

    https://forum.unity.com/threads/beginner-need-help-with-smoothdamp.988959/#post-6430100

    You have currentQuantity and desiredQuantity.
    - only set desiredQuantity
    - the code always moves currentQuantity towards desiredQuantity
    - read currentQuantity for the smoothed value

    Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

    The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4
     
  3. bwaite87

    bwaite87

    Joined:
    Nov 23, 2017
    Posts:
    17
    I think maybe I could have explained better. Your code is nice, but it makes my player turn around in a Paper-Mario style fashion, I'd like the player to turn around instantly, but doing so almost seems to be affecting the velocity of the player or something (only when he's in the air interestingly)...I though it was my camera follow, but even without the camera follow the player still is a bit jerky when you flip the Y rotation by 180f.

    My player is moving by applying forces in FixedUpdate, so I don't think there should be a conflict There. ..Thanks for your help though!
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Sounds like maybe you're flipping the entire structure.

    I only flip the visual part.

    Debug it and find out why the velocity is changing.

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    When in doubt, print it out!(tm)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
  5. bwaite87

    bwaite87

    Joined:
    Nov 23, 2017
    Posts:
    17
    Solved it.
    Since I'm using a RB for gravity in my platformer, this uses the physics system to make the player fall. But since I was turning my player by directly changing his transform.right instead of "faking it" by flipping the scale on the X or using the "FlipX" option on the spriteRenderer - and calling in Update() - these were conflicting with each other for 1 frame.

    If you want to "flip" your character in the air using this method, it needs to be called from FixedUpdate, not Update. Silly me.