Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved Unity Vector3 does not add correct amount

Discussion in 'Scripting' started by MinhocaNice, Jun 6, 2022.

  1. MinhocaNice

    MinhocaNice

    Joined:
    May 3, 2020
    Posts:
    249
    I have this script for adding a random spread to the gun's accuracy each time it fires in my FPS game:

    Code (CSharp):
    1.                 Vector3 BulletPath = transform.forward;
    2.                 print(BulletPath);
    3.  
    4.                 if (CurrentSpread > 0f)
    5.                 {
    6.                     BulletPath.x += Random.Range(-CurrentSpread, CurrentSpread);
    7.                     BulletPath.y += Random.Range(-CurrentSpread, CurrentSpread);
    8.                     BulletPath.z += Random.Range(-CurrentSpread, CurrentSpread);
    9.                     print(BulletPath);
    10.                 }
    The script works just fine for hitscan weapons, but I struggle to make it work for projectile based weapons (such as crossbows and rocket launchers), and because of that I placed the
    print
    commands and made a special hitscan weapon just to test the spread. Upon doing so, I noticed something very odd: The change in the
    BulletPath
    's vector3 values is extremely small, most of the time only a few decimals lower or higher. This is really odd because I used a float value for
    CurrentSpread
    that is 100 on the test weapon, meaning that by pure chance it's pretty much impossible for me to get an increase in only a few decimals in 5 out of 5 shots. I used 2 different weapons for this and they both returned this same behavior, and even more odd is that in-game they worked as intended, shooting with extremely low accuracy even though the
    BulletPath
    vector barely changed.

    What is going on here? I know that the
    transform.forward
    is normalized so it only has a magnitude of 1, but shouldn't it still get float values that range from -101 to 101 since that is added after the normalization?
     
  2. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,614
    I'd print CurrentSpread as well, to make sure those values are in fact what you think they are.
     
    MinhocaNice likes this.
  3. MinhocaNice

    MinhocaNice

    Joined:
    May 3, 2020
    Posts:
    249
    Sorry the late reply, I guess I can try that.
     
  4. MinhocaNice

    MinhocaNice

    Joined:
    May 3, 2020
    Posts:
    249
    Here is what I tried:

    Code (CSharp):
    1.                 Vector3 BulletPath = transform.forward;
    2.                 print("BulletPathInitial:" + BulletPath);
    3.                 print("CurrentSpreadInitial:" + CurrentSpread);
    4.  
    5.                 if (CurrentSpread > 0f)
    6.                 {
    7.                     float CurrentSpreadRandomizedX = Random.Range(-CurrentSpread, CurrentSpread);
    8.                     BulletPath.x += CurrentSpreadRandomizedX;
    9.                     print("CurrentSpreadRandomizedX:" + CurrentSpreadRandomizedX);
    10.  
    11.                     float CurrentSpreadRandomizedY = Random.Range(-CurrentSpread, CurrentSpread);
    12.                     BulletPath.y += CurrentSpreadRandomizedY;
    13.                     print("CurrentSpreadRandomizedY:" + CurrentSpreadRandomizedY);
    14.  
    15.                     float CurrentSpreadRandomizedZ = Random.Range(-CurrentSpread, CurrentSpread);
    16.                     BulletPath.z += CurrentSpreadRandomizedZ;
    17.                     print("CurrentSpreadRandomizedZ:" + CurrentSpreadRandomizedZ);
    18.  
    19.                     print("BulletPathFinal:" + BulletPath);
    20.                 }
    Here is the result on console:


    BulletPathInitial:(0.2, 0.1, -1.0)
    CurrentSpreadInitial:0,2
    CurrentSpreadRandomizedX:-0,026527
    CurrentSpreadRandomizedY:0,02924216
    CurrentSpreadRandomizedZ:0,1357439
    BulletPathFinal:(0.1, 0.1, -0.8)


    I realised the issue with the spread being small: I forgot that
    CurrentSpread
    is actually the spread of the weapon at the state of the player (standing, walking, airborne, etc) divided by 1000f, hence why it's so small. My bad.

    Code (CSharp):
    1.                 if (!NoSpread)
    2.                 {
    3.                     switch (Player.PlayerMovementStatus)
    4.                     {
    5.                         case PlayerStats.PlayerState.Standing:
    6.                             CurrentSpread = StandingSpread / 1000f;
    7.                             break;
    8.  
    9.                         case PlayerStats.PlayerState.Walking:
    10.                             CurrentSpread = WalkingSpread / 1000f;
    11.                             break;
    12.  
    13.                         case PlayerStats.PlayerState.Crouching:
    14.                             CurrentSpread = CrouchingSpread / 1000f;
    15.                             break;
    16.  
    17.                         case PlayerStats.PlayerState.Sprinting:
    18.                             CurrentSpread = AerialSpread / 1000f;
    19.                             break;
    20.  
    21.                         case PlayerStats.PlayerState.Falling:
    22.                             CurrentSpread = AerialSpread / 1000f;
    23.                             break;
    24.  
    25.                         case PlayerStats.PlayerState.Jumping:
    26.                             CurrentSpread = AerialSpread / 1000f;
    27.                             break;
    28.                     }
    29.                 }
    30.                 else
    31.                 {
    32.                     CurrentSpread = 0f;
    33.                 }
    I still don't know why it isn't working for projectiles, I know that it has something to do with converting a local vector3 into a global one, but I don't understand why it works fine for the hitscan ones but not projectile ones. I will make another thread for that however since it's a different issue.
     
  5. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    just a observation but why are you calculating 3 random ranges for a, Vector3 instead of just using Random.insideUnitSphere

    you can multiply it by your current speed
    Code (CSharp):
    1. BulletPath += Random.insideUnitSphere * CurrentSpread;
    this will get a bit more of a correct value too, since its within a max radius not within a max cube of a area.
     
    MinhocaNice and angrypenguin like this.
  6. MinhocaNice

    MinhocaNice

    Joined:
    May 3, 2020
    Posts:
    249
    Oh thanks! I didn't know that function existed.

    I also noticed there is a function called Random.insideUnitCircle. I wonder if the circle is better for reproducing gun spread than a sphere, though if I am getting this correctly the sphere makes so the bullets are more likely to hit the center; There is more volume on the center so there are more points that can be randomly be chosen, and since there is no way to draw a sphere on the wall the bullet will simply pass through that point in space and hit the wall behind. A circle doesn't have that and bullets can lead anywhere on the circle if their Z value is always the same.

    I am not sure what option works best, but I want to make sure I am getting the understanding correctly: Should a spherical distribution make bullets more likely to hit the center than a circular distribution?
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,912
    This might help. It calculates a point on a spherical cone with a certain spread angle around the main direction.