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 Assitance with making weapon stay put when input returns to zero

Discussion in '2D' started by MarkElement, Sep 5, 2023.

  1. MarkElement

    MarkElement

    Joined:
    Jan 2, 2023
    Posts:
    12
    I'm still working on perfecting the aiming system in my game, whilst learning unity at the same time. I'm SO close to getting it to be how i want it, the last remaining issue i have is when the player stops aiming, the weapon returns to a default state. I have an idea why this is happening but i'm really struggling to understand how i can resolve the issue.


    My player has a weapon slot, designed like this because it will allow me to swap out weapons and still have the same aiming system.

    The weapon slot is attached to the player, it's update method looks like this:


    Code (CSharp):
    1.     private void Update()
    2.     {
    3.         // Get the player position:
    4.         playerPosition = playerRigidBody.transform.position;
    5.  
    6.         // Get the player Rotation:
    7.         playerRotation = playerRigidBody.transform.rotation;
    8.  
    9.         // Attach the weapon to the player:
    10.         weaponSlot.transform.position = new Vector3(playerPosition.x + weaponDistanceFromPlayer, playerPosition.y, playerPosition.z); // playerPosition;
    11.  
    12.         // Get the players aim direction
    13.         aimDirection = playerAim.ReadValue<Vector2>();
    14.  
    15.         AimWeapon();
    16.     }
    The above makes it so the weaponSlot attaches to the player and follows at all times, take note of line 10 above, i'm fairly certain this is whats causing my issue.

    AimWeapon looks like this:

    Code (CSharp):
    1.  if (aimDirection.y != 0 || aimDirection.x != 0)
    2. {
    3.      // Flip the weapon into the direction it's aiming
    4.      if (WeaponIsFacingRight())
    5.      {
    6.          weaponSprite.flipX = true;
    7.          weaponSprite.flipY = false;
    8.      }
    9.      else
    10.      {
    11.          weaponSprite.flipX = true;
    12.          weaponSprite.flipY = true;
    13.      }
    14.  
    15.  
    16.      // Get the x and y aim direction, times by the tick rate and player move speed
    17.      float x = aimDirection.x * Time.deltaTime * moveSpeed;
    18.      float y = aimDirection.y * Time.deltaTime * moveSpeed;
    19.  
    20.      //convert the input into an angle in radians, and convert that into degrees
    21.      rads = Mathf.Atan2(y, x);
    22.  
    23.      float degrees = rads * Mathf.Rad2Deg;
    24.  
    25.      float weaponPositionX = Mathf.Cos(rads) + playerPosition.x * weaponDistanceFromPlayer;
    26.      float weaponPositionY = Mathf.Sin(rads) + playerPosition.y * weaponDistanceFromPlayer;
    27.  
    28.      // Transform the weapon
    29.      weaponSlot.transform.position = new Vector3(weaponPositionX, weaponPositionY, playerPosition.z); // playerPosition;
    30.      weaponSlot.transform.localEulerAngles = new Vector3(0, 0, degrees);
    31. }

    With regards to line 10 in Update(). this is important since without it, if the player moves, the weapon is left in place but at the same time, when the player stops aiming, this line is resetting the weapon back to the location specified on line 10.

    I've attempted solving this by creating a
    Vector3 lastKnownAimingDirection
    and setting it to the direction of aim set inside AimWeapon() but this didn't solve the issue.


    Here's a video showing the issue i'm trying to solve



    As you can see, when i input aim the weapon acts correctly, but if i stop aiming, it flicks / returns back to it's original position on the right side of the player.


    Any ideas / suggestions / recommendations on how to solve this are very much appreciated,

    Thanks
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,560
    You're most likely correct in this: as the x/y goes towards zero, one probably hits zero before the other, and the angle is incorrect.

    You want to ONLY run the "aiming angle" code if the combined magnitude is above a certain small amount, such as above 0.1f or something.

    Code (csharp):
    1. if (aimDirection.magnitude > 0.1f)
    2. {
    3.   // etc.
    4. }
     
  3. MarkElement

    MarkElement

    Joined:
    Jan 2, 2023
    Posts:
    12

    Thanks for the reply, i had already tried this with no success. However since posting i solved the issue.

    The problem was as i stated, Update() was basically "resetting" the weapon location to the default position every tick. Only when the player gave input to trigger the aim method did the weapon realign to the correct position, then once this input returned to zero the original positional code took over resulting in the weapon resetting to "default" position.

    There were two factors at fault here:

    1. weaponPositionX/Y were being initialised every tick ONLY when the player was aiming (line 17 & 18 inside AimWeapon() above). This was fixed by moving the declaration to the top, or outside of the method.

    2. weaponPositionX/Y's values were being set ONLY when the player was aiming. This was fixed by moving the setting of these values outside of the if statement inside but still inside of AimWeapon() (for tidyness) and additionally, using these as the location of the weapon inside Update().

    So line 10 in Update() becomes:
    weaponSlot.transform.position = new Vector3(weaponPositionX, weaponPositionY, playerPosition.z);


    Where weaponPositionX/Y's values are updated every tick.
     
    Kurt-Dekker likes this.