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

Need Help Cleaning Up My 2D Momentum Script

Discussion in 'Scripting' started by slaveknightgael, Nov 17, 2021.

  1. slaveknightgael

    slaveknightgael

    Joined:
    Mar 29, 2021
    Posts:
    13
    Hello there,

    I recently started working on a 2D platformer and I thought a good place to start would be creating a fully customizable system for handling movement. Although I have implemented a lot of customizable settings already, I am stuck on momentum.

    I have a state machine for my player character that shifts between Grounded, Jumping, and Falling states. After much consternation, I came up with some code in the Grounded state that *almost* does what I want it to. Two problems: One, it's extremely messy and hacky, and I'm sure there's a way simpler way to calculate this than what I'm doing. I haven't really tried to simplify it because I'm just too scared of messing up what works now.

    Second problem: as of now, my momentum decelerates at a linear rate, when instead I would like to have a multiplier variable which I could adjust. That would allow me to customize not just the rate of deceleration when momentum starts to decelerate, but also the ending rate of deceleration. Problem is, when I introduced a multiplier variable into the process, it played havoc with the way I'm setting boundaries (to make sure reaches exactly 0 at an appropriate point).

    I would really appreciate some help on this. I'm just too scared to change anything because I *finally* got it to work (almost) after too many hours of starting over and debugging again and again. I know eventually it makes more sense to do at least part of this in a method that I can then call upon (especially since I will want to reference at least the momentum deceleration process in the Falling and Jumping states) but there's got to be other ways I can simplify this even before that. Right now it's just a mess, and although it works, I know that if I work on something else for a week or so, I'm not gonna understand what the hell I was doing when I look at this script again.

    Thank you!


    Edit: Just for more context; the Move method references my collision detection just to make sure I'm not clipping through things or such. Also, in case it's not clear, I'm setting the variables in my PlayerManager script so that I can customize everything in one place easily while playtesting.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(Controller2D))]
    6. public class PlayerGroundedState : PlayerBaseState
    7. {
    8.     Controller2D playerController;
    9.     Vector3 velocity;
    10.  
    11.     float groundMaxSpeed;
    12.     float groundAcceleration;
    13.     float momentumLoss;
    14.  
    15.     float jumpChargeTimer;
    16.     float coyoteTime;
    17.     float coyoteTimeCounter;
    18.  
    19.     float moveSpeedX;
    20.     float momentum;
    21.  
    22.     public override void EnterState(PlayerManager player)
    23.     {
    24.         Debug.Log("Entered Grounded State");
    25.  
    26.         playerController = player.GetComponent<Controller2D>();
    27.         velocity.x = player.prevVelocity.x;
    28.         velocity.y = -0.0001f;
    29.  
    30.         groundMaxSpeed = player.groundMaxSpeed;
    31.         groundAcceleration = player.groundAcceleration;
    32.         momentumLoss = player.momentumLoss;
    33.  
    34.         jumpChargeTimer = player.jumpChargeTimer;
    35.         coyoteTime = player.coyoteTime;
    36.  
    37.         moveSpeedX = 0;
    38.         momentum = velocity.x;
    39.     }
    40.  
    41.  
    42.     public override void UpdateState(PlayerManager player)
    43.     {
    44.         // Horizontal Movement
    45.         float inputX = Input.GetAxisRaw("Horizontal");
    46.  
    47. // This is where all the problems start. I struggled for a while to get this mess! I know it's hacky. Ignore the weird y velocity, it has to do with my collision detection which I will fix at some point.
    48.  
    49.  
    50.         if (inputX == 0)
    51.         {
    52.             // Move Speed No Input
    53.             if (moveSpeedX > momentumLoss * 0.25f * Time.deltaTime)
    54.             {
    55.                 moveSpeedX -= momentumLoss * 0.5f * Time.deltaTime;
    56.             }
    57.             else if (moveSpeedX < -momentumLoss * 0.25f * Time.deltaTime)
    58.             {
    59.                 moveSpeedX += momentumLoss * 0.5f * Time.deltaTime;
    60.             }
    61.             else
    62.             {
    63.                 moveSpeedX = 0;
    64.             }
    65.  
    66.             // Momentum No Input
    67.             if (momentum > momentumLoss * 0.25f * Time.deltaTime)
    68.             {
    69.                 momentum -= momentumLoss * 0.5f * Time.deltaTime;
    70.             }
    71.             else if (momentum < -momentumLoss * 0.25f * Time.deltaTime)
    72.             {
    73.                 momentum += momentumLoss * 0.5f * Time.deltaTime;
    74.             }
    75.             else
    76.             {
    77.                 momentum = 0;
    78.             }
    79.         }
    80.         else if (inputX == 1)
    81.         {
    82.             // Move Speed Right
    83.             if (moveSpeedX + momentum < groundMaxSpeed)
    84.             {
    85.                 moveSpeedX += groundAcceleration * Time.deltaTime;
    86.                 momentum += groundAcceleration * Time.deltaTime;
    87.  
    88.                 // Momentum Right
    89.                 if (momentum > momentumLoss * 0.5f * Time.deltaTime)
    90.                 {
    91.                     momentum -= momentumLoss * Time.deltaTime;
    92.                 }
    93.                 else if (momentum < -momentumLoss * 0.5f * Time.deltaTime)
    94.                 {
    95.                     momentum += momentumLoss * Time.deltaTime;
    96.                 }
    97.                 else
    98.                 {
    99.                     momentum = 0;
    100.                 }
    101.             }
    102.             else
    103.             {
    104.                 moveSpeedX = groundMaxSpeed * 0.5f;
    105.                 momentum = groundMaxSpeed * 0.5f;
    106.             }
    107.         }
    108.         else if (inputX == -1)
    109.         {
    110.             // Move Speed Left
    111.             if (moveSpeedX + momentum > -groundMaxSpeed)
    112.             {
    113.                 moveSpeedX -= groundAcceleration * Time.deltaTime;
    114.                 momentum -= groundAcceleration * Time.deltaTime;
    115.  
    116.                 // Momentum Left
    117.                 if (momentum > momentumLoss * 0.5f * Time.deltaTime)
    118.                 {
    119.                     momentum -= momentumLoss * Time.deltaTime;
    120.                 }
    121.                 else if (momentum < -momentumLoss * 0.5f * Time.deltaTime)
    122.                 {
    123.                     momentum += momentumLoss * Time.deltaTime;
    124.                 }
    125.                 else
    126.                 {
    127.                     momentum = 0;
    128.                 }
    129.             }
    130.             else
    131.             {
    132.                 moveSpeedX = -groundMaxSpeed * 0.5f;
    133.                 momentum = -groundMaxSpeed * 0.5f;
    134.             }
    135.         }
    136.  
    137.         if (moveSpeedX + momentum > groundMaxSpeed)
    138.         {
    139.             velocity.x = groundMaxSpeed * (moveSpeedX / moveSpeedX);
    140.         }
    141.         else
    142.         {
    143.             velocity.x = moveSpeedX + momentum;
    144.         }
    145.  
    146.         Debug.Log("Momentum is " + momentum + ". Momentum Loss is " + momentumLoss + ". Move Speed X is " + moveSpeedX + ".");
    147.         Debug.Log("Grounded Velocity X = " + velocity.x);
    148.         playerController.Move(velocity * Time.deltaTime);
    149.  
    150.  
    151. // Everything past this point works fine, I just included the whole script for context.
    152.  
    153.         // Transition to Falling
    154.         if (playerController.collisions.below)
    155.         {
    156.             coyoteTimeCounter = coyoteTime;
    157.         }
    158.         else
    159.         {
    160.             coyoteTimeCounter -= Time.deltaTime;
    161.         }
    162.  
    163.         if (!playerController.collisions.below && coyoteTimeCounter <= 0)
    164.         {
    165.             Vector3 savedVelocity = velocity;
    166.             player.SaveVelocity(savedVelocity);
    167.             player.SwitchState(player.FallingState);
    168.         }
    169.  
    170.  
    171.         // Jump Charge Timer
    172.         jumpChargeTimer -= Time.deltaTime;
    173.  
    174.  
    175.         // Transition to Jumping
    176.         if (Input.GetKeyDown("x") && jumpChargeTimer <= 0)
    177.         {
    178.             Vector3 savedVelocity = velocity;
    179.             player.SaveVelocity(savedVelocity);
    180.             player.SwitchState(player.JumpingState);
    181.         }
    182.     }
    183. }
    184.  
     
    Shreddedcoconut likes this.
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Oh my goodness, you should not live like this!!! NOBODY should live like this.

    Look, you already have electricity, running water and probably air conditioning... Please consider using proper industrial-grade source control in order to guard and protect your hard-earned work.

    Personally I use git (completely outside of Unity) because it is free and there are tons of tutorials out there to help you set it up as well as free places to host your repo (BitBucket, Github, Gitlab, etc.).

    You can also push git repositories to other drives: thumb drives, USB drives, network drives, etc., effectively putting a complete copy of the repository there.

    As far as configuring Unity to play nice with git, keep this in mind:

    https://forum.unity.com/threads/prefab-links-keep-getting-dumped-on-git-pull.646600/#post-7142306

    Here's how I use git in one of my games, Jetpack Kurt:

    https://forum.unity.com/threads/2-steps-backwards.965048/#post-6282497

    Using fine-grained source control as you work to refine your engineering:

    https://forum.unity.com/threads/whe...grammer-example-in-text.1048739/#post-6783740

    Share/Sharing source code between projects:

    https://forum.unity.com/threads/your-techniques-to-share-code-between-projects.575959/#post-3835837

    Setting up an appropriate .gitignore file for Unity3D:

    https://forum.unity.com/threads/removing-il2cpp_cache-from-project.1084607/#post-6997067

    Generally setting Unity up (includes above .gitignore concepts):

    https://thoughtbot.com/blog/how-to-git-with-unity

    It is only simple economics that you must expend as much effort into backing it up as you feel the work is worth in the first place.

    "Use source control or you will be really sad sooner or later." - StarManta on the Unity3D forum boards
     
  3. slaveknightgael

    slaveknightgael

    Joined:
    Mar 29, 2021
    Posts:
    13

    Oh I think you misunderstood me! It's not a problem with backing it up; I just was so glad I got the code to work that I didn't want to mess around with it. No worries, I always back it up! When I said I was starting over, I just meant that I would try a different approach with how I was calculating it-- not starting the whole thing over! But thank you for the links, much appreciated =D
     
    Shreddedcoconut likes this.
  4. Shreddedcoconut

    Shreddedcoconut

    Joined:
    Jul 30, 2021
    Posts:
    61
    If the code works I don't see why you'd want to clean it up, unless you had unnecessary functions or something like that but it doesn't look like you do. I'll take another looksie, though.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    You're right, that's not the problem.

    The actual problem is if you're terrified of breaking anything you might as well just put up your hat and give up software engineering. You'll never attain success without being able to fearlessly experiment as a major part of your engineering effort.

    Source control lets you instantly try a simple thing, iterate and work on it, and at any time you want, give it all up (or just give up a few key parts of it that you don't like) and go back INSTANTLY and PRECISELY to any point in history.

    Making zip backups does not meet that criteria the way a proper source control does. It's not even a comparison.