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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Getting a projectile to fire in the direction of the gun barrel

Discussion in 'Scripting' started by boylesg, Mar 25, 2016.

  1. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Unity.jpg It has been asked a million times and I have followed some examples but they simply don't work.

    I have a sphere at the start of the gun barrel and a sphere at the end of the barrel.
    public GameObject m_gmobjBarrelEnd;
    public GameObject m_gmobjBarrelStart; (the white bit in the above image is this sphere)

    It should be an easy matter to find the correct direction of the barrel but apparently not.

    So can some one please tell me how to do it because it is totally eluding me.

    This is the code I have:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Crosshair: MonoBehaviour
    5. {
    6.     public Camera m_camobjCamera;
    7.     public GameObject m_gmobjBarrelEnd;
    8.     public GameObject m_gmobjBarrelStart;
    9.     public GameObject m_gmobjMARMO3;
    10.     public GameObject m_particlesMuzzleFlash;
    11.     public GameObject m_prefabBullet;
    12.  
    13.     private float m_fRecoilAngle = 8.0f;
    14.  
    15.     // Use this for initialization
    16.     void Start()
    17.     {
    18.         m_gmobjBarrelEnd.transform.rotation = m_camobjCamera.transform.rotation;
    19.     }
    20.  
    21.     bool mouseMoved()
    22.     {
    23.         return (Input.GetAxis("Mouse X") != 0) && (Input.GetAxis("Mouse Y") != 0);
    24.     }
    25.  
    26.     void doRotate(float fRotAroundX, float fRotAroundY)
    27.     {
    28.         float fGunAngleToHoriz = 0.0f;
    29.  
    30.         if ((m_camobjCamera.gameObject.transform.eulerAngles.x >= 0) && (m_camobjCamera.gameObject.transform.eulerAngles.x <= 90))
    31.             fGunAngleToHoriz = -m_camobjCamera.gameObject.transform.eulerAngles.x;
    32.         else if ((m_camobjCamera.gameObject.transform.eulerAngles.x >= 270) && (m_camobjCamera.gameObject.transform.eulerAngles.x <= 360))
    33.             fGunAngleToHoriz = 360 - m_camobjCamera.gameObject.transform.eulerAngles.x;
    34.  
    35.         if (((fGunAngleToHoriz + fRotAroundX) >= -20.0f) && ((fGunAngleToHoriz + fRotAroundX) <= 40.0f))
    36.         {
    37.             m_camobjCamera.gameObject.transform.Rotate (new Vector3 (-fRotAroundX, fRotAroundY, 0));
    38.             m_camobjCamera.gameObject.transform.Rotate(new Vector3 (0.0f, 0.0f, -m_camobjCamera.gameObject.transform.eulerAngles.z));
    39.             m_gmobjBarrelEnd.transform.rotation = m_camobjCamera.transform.rotation;
    40.         }
    41.     }
    42.  
    43.     void doUnRecoilGun()
    44.     {
    45.         m_camobjCamera.gameObject.transform.Rotate (new Vector3 (m_fRecoilAngle, 0.0f, 0.0f));
    46.     }
    47.  
    48.     void doFireGun()
    49.     {
    50.         if (Input.GetKeyDown ("space"))
    51.         {
    52.             const float fRecoilAngle = 5.0f;
    53.             m_camobjCamera.gameObject.transform.Rotate (new Vector3 (-m_fRecoilAngle, 0.0f, 0.0f));
    54.             Vector3 vectBarrelEndPos = m_gmobjBarrelEnd.transform.position,
    55.             vectBarrelStartPos = m_gmobjBarrelStart.transform.position;
    56.             Quaternion quartBarrelDirection = Quaternion.LookRotation((vectBarrelEndPos - vectBarrelStartPos).normalized);
    57.             vectBarrelEndPos.y -= 0.6f;
    58.             Object objMuzzleFlash = Instantiate(m_particlesMuzzleFlash, vectBarrelEndPos, m_gmobjBarrelEnd.transform.rotation);
    59.             AudioSource audiosrcBang = GetComponent<AudioSource>();
    60.             audiosrcBang.Play();
    61.  
    62.             GameObject gmobjBullet = Instantiate(m_prefabBullet, vectBarrelEndPos, quartBarrelDirection) as GameObject;
    63.             gmobjBullet.transform.rotation = quartBarrelDirection;
    64.             Bullet bullet = gmobjBullet.GetComponent<Bullet>();
    65.             bullet.Fire(m_gmobjBarrelEnd);
    66.  
    67.             Invoke("doUnRecoilGun", 0.05f);
    68.         }
    69.     }
    70.  
    71.     void doMoveGun()
    72.     {
    73.         const float fSpeed = 8.0f;
    74.         float fRotAroundX = 0.0f,
    75.         fRotAroundY = 0.0f;
    76.  
    77.         if (Input.GetKey("left"))
    78.             fRotAroundY = -fSpeed;
    79.         else if (Input.GetKey("right"))
    80.             fRotAroundY = fSpeed;
    81.  
    82.         if (Input.GetKey("up"))
    83.             fRotAroundX = fSpeed;
    84.         else if (Input.GetKey("down"))
    85.             fRotAroundX = -fSpeed;
    86.  
    87.         if ((fRotAroundX != 0.0f) || (fRotAroundY != 0.0f))
    88.         {
    89.             doRotate(fRotAroundX, fRotAroundY);
    90.         }
    91.     }
    92.  
    93.     // Update is called once per frame
    94.     void Update()
    95.     {
    96.         doMoveGun();
    97.         doFireGun();
    98.     }
    99. }
    100.  
     
    Last edited: Mar 25, 2016
  2. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    You can use just one GameObject:
    First make it a child of your gun and position it where you want the projectile to appear, then give it the same rotation of the barrel (so that the Z axis is pointing the direction of shooting).
    Now the empty object you created will always point at the direction you want, in your script you can create a reference to it:
    Code (CSharp):
    1. public Transform shootPos;
    Then when instantiating the projectile you can use its position and rotation:
    Code (CSharp):
    1. Instantiate(bullet, shootPos.position, shootPos.rotation);
     
    ShadowKitten101 likes this.
  3. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I have tried that as well and it does not work either.Apart from the fact that I can spin my gun 360 degrees around the y axis to shoot in any direction.

    Regardless of what I do with respect to trying to set angles the projectiles are coming out roughly towards the centre of the screen (in the screen capture now above) and then arching over - I have a low muzzle velocity at present so I can see which direction they they are going in.

    Is it something to do with the hierarchy of my gun related gameobjects? I.E. Angles related to child objects don't mean the same thing as global world angles? There is clearly some major gap in my knowledge as to how angles work in unity.
     
    Last edited: Mar 25, 2016
  4. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    Objects that are child of any other object have a global position AND a local position. The global position is the real world position of the object while the local position is relative to its parent (same for rotation).

    So if the parent moves or rotates all child objects will follow its movement so that the local position stays the same, for example:
    We have a cube that has a rotation of 90 degrees on the X axis,
    a sphere that is child of the cube, also has a rotation of 90 degrees on the X axis,
    the GLOBAL position of the sphere will be 180 degrees because its parent has rotated by 90 and the sphere itself is rotated by 90, if we consider the local position of the sphere, it stays 90 no matter what is the rotation of the parent.

    This is also important in scripts:
    Code (CSharp):
    1. // global
    2. someTransform.position
    3. someTransform.rotation
    4.  
    5. // local
    6. someTransform.localPosition
    7. someTransform.localRotation
    From what I understand you set up the object correctly but got confused with the axes. I assume your projectiles consider the Z axis as forward but I can see on the screenshot that the X axis is lined up with the barrel, you should line up the Z axis with the barrel
     
  5. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    This is so f'ing frustrating.

    It simply does not matter how I align the little sphere sitting in the end of the barrel of my gun - Z axis aligned with the barrel or X axis aligned with the barrel or any other random rotation.

    The spawned projectile come out of the barrel aligned with the camera I think.

    So what is that I have to do to my script below or my shotgun construct to get those bloody projectiles to go in the direction that I am expecting them to go in!!!!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Crosshair: MonoBehaviour
    5. {
    6.     public Camera m_camobjCamera;
    7.     public GameObject m_gmobjBarrelEnd;
    8.     public GameObject m_gmobjBarrelStart;
    9.     public GameObject m_gmobjMARMO3;
    10.     public GameObject m_particlesMuzzleFlash;
    11.     public GameObject m_prefabBullet;
    12.  
    13.     private float m_fRecoilAngle = 8.0f;
    14.  
    15.     // Use this for initialization
    16.     void Start()
    17.     {
    18.         m_gmobjBarrelEnd.transform.rotation = m_camobjCamera.transform.rotation;
    19.     }
    20.    
    21.     bool mouseMoved()
    22.     {
    23.         return (Input.GetAxis("Mouse X") != 0) && (Input.GetAxis("Mouse Y") != 0);
    24.     }
    25.  
    26.     void doRotate(float fRotAroundX, float fRotAroundY)
    27.     {
    28.         float fGunAngleToHoriz = 0.0f;
    29.  
    30.         if ((m_camobjCamera.gameObject.transform.eulerAngles.x >= 0) && (m_camobjCamera.gameObject.transform.eulerAngles.x <= 90))
    31.             fGunAngleToHoriz = -m_camobjCamera.gameObject.transform.eulerAngles.x;
    32.         else if ((m_camobjCamera.gameObject.transform.eulerAngles.x >= 270) && (m_camobjCamera.gameObject.transform.eulerAngles.x <= 360))
    33.             fGunAngleToHoriz = 360 - m_camobjCamera.gameObject.transform.eulerAngles.x;
    34.  
    35.         if (((fGunAngleToHoriz + fRotAroundX) >= -20.0f) && ((fGunAngleToHoriz + fRotAroundX) <= 40.0f))
    36.         {
    37.             m_camobjCamera.gameObject.transform.Rotate (new Vector3 (-fRotAroundX, fRotAroundY, 0));
    38.             m_camobjCamera.gameObject.transform.Rotate(new Vector3 (0.0f, 0.0f, -m_camobjCamera.gameObject.transform.eulerAngles.z));
    39.             m_gmobjBarrelEnd.transform.rotation = m_camobjCamera.transform.rotation;
    40.         }
    41.     }
    42.  
    43.     void doUnRecoilGun()
    44.     {
    45.         m_camobjCamera.gameObject.transform.Rotate (new Vector3 (m_fRecoilAngle, 0.0f, 0.0f));
    46.     }
    47.  
    48.     void doFireGun()
    49.     {
    50.         if (Input.GetKeyDown ("space"))
    51.         {
    52.             m_camobjCamera.gameObject.transform.Rotate (new Vector3 (-m_fRecoilAngle, 0.0f, 0.0f));
    53.  
    54.             Object objMuzzleFlash = Instantiate(m_particlesMuzzleFlash, m_gmobjBarrelEnd.transform.position, m_gmobjBarrelEnd.transform.rotation);
    55.  
    56.             AudioSource audiosrcBang = GetComponent<AudioSource>();
    57.             audiosrcBang.Play();
    58.  
    59.             GameObject gmobjBullet = Instantiate(m_prefabBullet, m_gmobjBarrelEnd.transform.position, m_prefabBullet.transform.rotation) as GameObject;
    60.             Bullet bullet = gmobjBullet.GetComponent<Bullet>();
    61.  
    62.             bullet.Fire(bullet.transform.forward);
    63.  
    64.             Invoke("doUnRecoilGun", 0.05f);
    65.         }
    66.     }
    67.  
    68.     void doMoveGun()
    69.     {
    70.         const float fSpeed = 8.0f;
    71.         float fRotAroundX = 0.0f,
    72.         fRotAroundY = 0.0f;
    73.  
    74.         if (Input.GetKey("left"))
    75.             fRotAroundY = -fSpeed;
    76.         else if (Input.GetKey("right"))
    77.             fRotAroundY = fSpeed;
    78.  
    79.         if (Input.GetKey("up"))
    80.             fRotAroundX = fSpeed;
    81.         else if (Input.GetKey("down"))
    82.             fRotAroundX = -fSpeed;
    83.  
    84.         if ((fRotAroundX != 0.0f) || (fRotAroundY != 0.0f))
    85.         {
    86.             doRotate(fRotAroundX, fRotAroundY);
    87.         }
    88.     }
    89.  
    90.     // Update is called once per frame
    91.     void Update()
    92.     {
    93.         doMoveGun();
    94.         doFireGun();
    95.     }
    96. }
    97.  
     
  6. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I figured out something. The angle that my spawned projectile is coming out of the gun barrel is determined by the angles in the bullet prefab I am using - if I change them in the editor then I can change the trajectory of the projectile.

    In my script I can change the trajectory by rotating my bullet prefab with transform.Rotate(...).
    However that results in the bullet trajectory spinning around in a circle on successive spawned bullets.
    How do you set an absolute rotation rather than incrementing the rotation?

    There does not seem to be any way to change the rotation of a spawned bullet once it is created - why?


    Instantiate(m_prefabBullet,m_gmobjBarrelEnd.transform.position,m_prefabBullet.transform.rotation)

    And what is the point of the 3rd parameter in the above function - it seems to have no effect on my spawned bullet.
    Only the rotation in m_prefabBullet matters.
     
  7. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Angles in unity are almost impossible to comprehend!

    I changed my fire function to this
    Code (CSharp):
    1.     void doFireGun()
    2.     {
    3.         if (Input.GetKeyDown ("space"))
    4.         {
    5.             m_camobjCamera.gameObject.transform.Rotate(new Vector3 (-m_fRecoilAngle, 0.0f, 0.0f));
    6.  
    7.             Object objMuzzleFlash = Instantiate(m_particlesMuzzleFlash, m_gmobjBarrelEnd.transform.position, m_gmobjBarrelEnd.transform.rotation);
    8.  
    9.             AudioSource audiosrcBang = GetComponent<AudioSource>();
    10.             audiosrcBang.Play();
    11.  
    12.             Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.x);
    13.             Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.y);
    14.             Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.z);
    15.  
    16.             GameObject gmobjBullet = Instantiate(m_prefabBullet, m_gmobjBarrelEnd.transform.position, m_prefabBullet.transform.rotation) as GameObject;
    17.             gmobjBullet.transform.eulerAngles = new Vector3 (m_gmobjBarrelEnd.transform.eulerAngles.x, m_gmobjBarrelEnd.transform.eulerAngles.y, m_gmobjBarrelEnd.transform.eulerAngles.z);
    18.             Bullet bullet = gmobjBullet.GetComponent<Bullet>();
    19.  
    20.             bullet.Fire(bullet.transform.forward);
    21.  
    22.             Invoke("doUnRecoilGun", 0.05f);
    23.         }
    24.     }
    25.  
    I changed the angles of the little sphere in the end of my gun barrel to the same angles as the gun barrel itself - 6, 76, 0.7 (with the hope that transform.forward on the spawned bullet will be pointing in the right direction)

    Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.x);
    Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.y);
    Debug.Log (m_gmobjBarrelEnd.transform.eulerAngles.z);

    When I output them in my script suddenly they are 352, 353, 352

    Where have those values come from????

    Back in the editor the values are still 6, 76, 0.7.

    So what the buggery is Unity doing here that I am not getting, and why?
     
  8. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    The rotation you see in the editor is the local rotation while eulerAngles is the global rotation and not local so it will be different if your camera is rotated. If you debug localEulerAngles it should be the ones you see in the editor.

    Well you set the third parameter to be the rotation of the actual prefab so it wont't change unless you do it manually.

    The simplest way to do this is the way I showed you in the first post but I don't understand what exactly is not working with that solution.. Also you should post the bullet script
     
  9. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    Just change this line:

    You were setting the instantiate rotation to the prefabs rotation! Orientate the instantiated object to the barrel ends rotation.

    Oh and make sure you have the blue arrow on the end of the barrel facing in the direction you want the bullet to fire AND make sure you have the blue arrow on the bullet prefab facing the correct way forward too.

    And don't pass your .fire function anything you don't need to. just move the bullet in its .forward direction.
     
  10. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Then what does localEulerAngles mean then? Relative to what?
    eulerAngles must be relative to the world origin (0,0,0)

    And it sure does not help my confusion that terrains are not centered on world 0,0,0 like all other game objects are - I had to center my camera on the terrain and no doubt that is fu#$ing the angles up some how.
     
  11. arkon

    arkon

    Joined:
    Jun 27, 2011
    Posts:
    1,122
    the terrain and camera will have no effect on the orientation of something you instantiate. What you are trying to do is very trivial and is a one liner to accomplish. Wampir888 Gave the answer in the second post.
    localEulerAngles are relative to whatever it is parented to. if it's not parented then it's not really local but global and relative to the 3 axis gizmo you see in the top right of every window. Hope this helps.

    Can't believe I'm defending Unity but the terrain anchor makes sense as you usually tile them and it's easier the way it is because if it was in the center you would then be adding and subtracting half terrain tile when placing them.
     
  12. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    Adding and subtracting half a terrain???

    As far as I can see the world is infinite in all directions so why on earth would you need to add half a terrain if the first terrain tile is centered on 0,0,0.

    It is not like your are tiling a room with fixed immutable walls on four sides.
     
  13. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    The terrain that is generated is not centered but that is not a problem and it does not affect angles in any way. But You can center the terrain manually, if you have a terrain that is 300x300 you can set the x and z to be half of the size so -150, -150 (note the minus) and "visually" it will be centered on the world zero.
     
  14. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    OK the terrain I created had its top left corner (I think) at 0,0 as you look at the screen.
    I then moved my camera + shotgun construct to 250, 250 at the centre of my terrain.
    That should make an angle of roughly 45 degrees (or 315) with 0,0,0 on the z and x axes.
    So I still have no clue where the global angle 352, 353, 352 is coming from.
    What is that angle relative to???? From my point of view it appears to be a bug in the software.
     
    Last edited: Mar 26, 2016
  15. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    The global angle you get is not relative to anything because its global. It just means that that is the real rotation in that moment.
    Have you rotated the camera or gun? If you rotate the camera or gun you will se that the debug angle will change
     
  16. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    And another thing that is not made clear in any of the online doco, related to angles, that I have read thus far is this.....

    Where is 0 degrees and which way (clockwise or anticlockwise) are positive angles or angles less that 180 (however you want to look at it).

    With rotation around the Y axis, is 0 degrees on the -'ve z axis, +'ve z axis, -'ve x axis or +'ve x axis.
     
  17. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I aint no maths guru but ALL angles are relative to something - you need 3 points in space to make an angle with any axis.

    The world origin 0,0,0 is clearly one, the position of my game object in the world graph system is the 2nd point.

    But what is the third point that causes eulerAngles to return the 352, 353, 352 that I am observing in my debug script???

    With my understanding of maths I would have assumed this regarding eulerAngles.

    If my gameobject position was 1,1,1 then to get eulerAngles.x then the 3 points would be 0,0,0 / 1,1,1 and 0,1,1.....with 0,1,1 being determined by 'drawing' a perpendicular line from my point in world space to the X axis. This is how it works in regular maths!

    So what maths is unity using to generate an angle of 352 degrees????
     
    Last edited: Mar 26, 2016
  18. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    In this case the world origin has nothing to do with it, If you took world origin into account that would make no sense because if you moved the object the angles would change and mess up your rotation.

    The rotation is around the origin of the object itself

    Even if the position changes the rotations stays around the center point of the object
     
  19. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I don't understand how is that global rotation? That looks more like local rotation to me.
    If I am setting localEulerAngles (as you have described above) in the unity editor then my original question still stands.
    Where have 352,353,352 come from in eulerAngles?
     
  20. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    So the angles in the editor are relative to the coordinate of my gameobject in world space.
    What are 'global' angles relative to?

    And some one mentioned the angles a non child gameobject not really being local. What does that mean exactly?
    Either angles are global and relative to world 0,0,0 or local and relative to the coordinate of the game object.

    We are not talking quantum mechanics here where things can be in two places at once or two things at once.

    This whole unity angle thing seems to be very ill-defined.

    Or 'global' is a very poor description of what eulerAngles actually represent.
     
  21. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    The global rotation is relative to the world origin, not the position but its rotation and the world rotation is always 0,0,0.
    The inspector shows the local values but if a gameobject is not child of anything the local and global rotations are the same.
    While if a gameobject is a child of another the inspector will show you the position and rotation relative to its parent object, so its origin is not any more the world origin but the parent center point.
    But the child object still has a global representation relative to the world origin..

    The fact that you get these values from eulerAngles is becuse you probably rotated the camera or the gun
     
  22. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    OK so that makes some sense......but as to why you would need to know the delta between world rotation at 0,0,0 and rotation around point x,y,z is some what beyond me at this point. It would have not remotely occurred to me that this is what global rotation means.

    What happens if you create an empty container game object with localEulerAngles 0,0,0?

    And then you rotate a child object that belongs to the above container.

    The x,y,z position of the child object is still relative to the world origin isn't it?

    So then if you rotate your child object around point x,y,z.

    How does localEulerAngles relate to the 0,0,0 localEulerAngles of the empty container gameobject?
     
  23. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    OK.....

    If I rotate a child object by 30 degrees around Y and I rotate my parent object around Y by 30 degrees then logic would dictate that eulerAngles.y of my child object would be 60 degrees (30 + 30).

    And localeulerAngles.y of my child object would be 30 degrees.

    If I rotate a child object by -30/330 degrees around Y and I rotate my parent object around Y by 30 degrees then logic would dictate that eulerAngles.y of my child object would be 0/360 degrees (30 + 330 / 30 - 30).

    And localeulerAngles.y of my child object would be -30/330 degrees.

    Is that how it is supposed to work?

    Because when you rotate an object in the editor it looks as though you are rotating it such that eulerAngles and localEulerAngles would mean the same thing. There appears to be no reference to the parent object as far as the rotation handles/gizmos go
     
  24. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    My gun and bullet is still up the $hit!

    In unity editor I made the rotation of the sphere in the end of my gun barrel the same as the rotation of my gun barrel and I am outputing there values as such:

    Debug.Log(m_gmobjBarrelEnd.transform.localEulerAngles.x);
    Debug.Log(m_gmobjBarrelEnd.transform.localEulerAngles.y);
    Debug.Log(m_gmobjBarrelEnd.transform.localEulerAngles.z);

    As soon as I hit play unity resets those angles to 0 and my bullets still fly off in the wrong direction.

    I see 0,0,0 in the unity editor for the angles of my barrel end marker and I see 0,0,0 as a result of the above output statements.

    When I stop the player the angles revert back to what I set them at!

    So why is unity changing my angle values to 0 when it plays?


    The barrel end marker is still unusable for the purpose of setting the direction of my bullets!

    So if firing bullets in the right direction is such a trivial problem in unity then can some one PLEASE tell me how the $uck you do it!
     
  25. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    This seems to be correct

    I don't understand what exactly do you mean?
     
  26. OrbitSoft

    OrbitSoft

    Joined:
    Sep 21, 2013
    Posts:
    54
    In the first post in the start function you are resetting the m_gmobjBarrelEnd rotation to the camera's rotation
     
  27. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I mean that if I rotate the parent object and the child object by opposite angles then they should cancel each other out and there is no net rotation on the child object relative to the rotation at the world origin with is 0 degrees on all axes.
     
  28. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    I have figured one bit out at least..... in order to get the bullets to fire broadly forward of the gun no matter which way it is pointed around 360 degrees then I have to do this:

    gmobjBullet.transform.eulerAngles=newVector3(0,transform.parent.gameObject.transform.eulerAngles.y,0);

    transform.parent.gameObject.transform.eulerAngles.y is the eulerAngle = localEulerAngle of the camera that is the parent of my whole shotgun construct.

    And I had to remove the collider component from the sphere at the end of my gun barrel to prevent collisions with the spawned bullets.

    So I am one step closer to making this ruddy thing work properly.
     
  29. boylesg

    boylesg

    Joined:
    Feb 18, 2016
    Posts:
    275
    The whole problem with this global versus local rotation is that, to me, global rotation was a proxy for compass heading and elevation relative to the world origin.
     
  30. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    So I sat down and decided to make a world with a simple FPS controller and rewrote the crosshair class. Not only to help you but also cause I never done FPS before and was a little curious myself. After a couple minutes of looking things up, I was able to get it working just fine. I'll show my code in a little bit

    first off...
    Looking at the gun model you shown in the first post, is the Gun's Z axis (blue arrow) matching the gun's forward direction? if you imported the gun from a modeling application there is a possibility that the gun was exported with its x-axis (or possibly y-axis but i doubt it) as the gun's forward direction. this might be the source of your woes. Unity wants Z to be forward, while most modeling apps use X as forward (no worries these applications should be able to re-export z as the forward). worst case you can correct this in the gun's import settings, but its best that its fixed straight from the modeling application.

    Alright lets start with the gameObjects I used...
    I started with a empty GameObject and renamed it to Player_Root. added components CharacterController, and two custom scripts FPS Controller and Crosshair. I parented the main camera to the the Player_Root.I reset it's transform then raised the camera up one unit to represent the head, then on the camera I added a cube, resized and repositioned it to represent a gun and renamed the cube to "GunModel",On the GunModel I added an empty gameobject, positioned it right in front of the gun and renamed the gamobject to "Barrel". so far the hierarchy looks like this:
    Code (CSharp):
    1. Player_Root
    2.     Main Camera
    3.         GunModel
    4.             Barrel
    next I made sure I had the Inputs set up. I used Mouse X, Mouse Y, Horizontal, Vertical, and Submit. all of these are used in the scripts. they are preset by default so unless you've changed something you should be ready. My input sensitivities are different (cause I lazily made the scene in an existing project) so you might want to tweak with your settings to to get the right feel for the game.

    next I wrote the FPS controller script:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class FPSController : MonoBehaviour {
    5.  
    6.     public float turnSpeed = 1.0f;
    7.     public float moveSpeed = 200.0f;
    8.     public new Transform camera;
    9.  
    10.  
    11.     private CharacterController controller;
    12.     private float verticalLook = 0;
    13.     private Vector3 movement = Vector3.zero;
    14.     private float fallspeed = 0;
    15.     private float gravity = 0.25f;
    16.  
    17.  
    18.     void Awake()
    19.     {
    20.         controller = GetComponent<CharacterController>();
    21.         Cursor.visible = false;
    22.     }
    23.  
    24.     void Update()
    25.     {
    26.         //rotate entire root on y axis
    27.         transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * turnSpeed);
    28.  
    29.         //rotate x axis on the camera, clamp to prevent flipping upsidedown
    30.         verticalLook = Mathf.Clamp( verticalLook + Input.GetAxis("Mouse Y") * turnSpeed,-80,80);
    31.         camera.localEulerAngles = Vector3.left * verticalLook;
    32.  
    33.         if(controller.isGrounded)
    34.         {
    35.             fallspeed = 0;
    36.         }
    37.         else
    38.         {
    39.             fallspeed -= gravity * Time.deltaTime;
    40.         }
    41.  
    42.         movement.x = Input.GetAxisRaw("Horizontal");
    43.         movement.z = Input.GetAxisRaw("Vertical");
    44.  
    45.         movement = transform.TransformDirection(movement);
    46.         movement *= (moveSpeed * Time.deltaTime);
    47.         movement.y = fallspeed;
    48.  
    49.         controller.Move(movement);
    50.     }
    51. }
    Attached the Main Camera to the camera field in the inspector

    finally the crosshair script (which honestly should be named Recoiler)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Crosshair : MonoBehaviour
    5. {
    6.     public Transform barrel;
    7.     public Transform gunModel;
    8.     public GameObject muzzleFlash;
    9.     public GameObject bullet;
    10.  
    11.     [Header("Shooting Settings")]
    12.     [Range(0.2f,20)]
    13.     public float roundsPerSecond = 10;
    14.  
    15.     [Header("Recoil Settings")]
    16.     public float strongRecoilResetRate = 10f;
    17.     public float weakRecoilResetRate = 5f;
    18.  
    19.     public Vector3 recoilPositionOffset = new Vector3 (0,0.05f,0.1f);
    20.     public Vector3 recoilAngleOffset = new Vector3 (-15.0f,05f,0f);
    21.     public bool randomizeRecoilSpread = true;
    22.  
    23.  
    24.     private AudioSource audiosrcBang;
    25.     private Vector3 homePosition;
    26.     private Quaternion homeRotation;
    27.     private Coroutine recoilHandle;
    28.  
    29.     IEnumerator Start()
    30.     {
    31.         homePosition = gunModel.localPosition;
    32.         homeRotation = gunModel.localRotation;
    33.         audiosrcBang = GetComponent<AudioSource>();
    34.      
    35.         while(true)
    36.         {
    37.             if (Input.GetButton ("Submit"))
    38.             {
    39.                 //Instantiate(muzzleFlash, barrel.position, barrel.rotation);
    40.                 Instantiate(bullet, barrel.position, barrel.rotation);
    41.              
    42.                 //audiosrcBang.Play();
    43.  
    44.                 if(recoilHandle!= null)
    45.                 {
    46.                     StopCoroutine(recoilHandle);
    47.                 }
    48.                 recoilHandle = StartCoroutine(ApplyRecoil());
    49.  
    50.                 yield return new WaitForSeconds(1/roundsPerSecond);
    51.             }
    52.             else
    53.             {
    54.                 yield return null;
    55.             }
    56.         }
    57.     }
    58.  
    59.     IEnumerator ApplyRecoil()
    60.     {
    61.         Vector3 currentPositionOffset = recoilPositionOffset;
    62.         Vector3 currentRotationOffset = recoilAngleOffset;
    63.  
    64.         if(randomizeRecoilSpread)
    65.         {
    66.             currentPositionOffset = Vector3.Scale(currentPositionOffset, RandomVectorUniform());
    67.             currentRotationOffset = Vector3.Scale(currentRotationOffset, RandomVectorUniform());
    68.         }
    69.  
    70.         //jerk weapon away instantly in single frame
    71.         gunModel.localPosition = gunModel.localPosition + currentPositionOffset;
    72.         gunModel.localEulerAngles = gunModel.localEulerAngles + currentRotationOffset;
    73.         yield return null;
    74.  
    75.         //smoothly animate gun back to home rotation
    76.         while(gunModel.localRotation != homeRotation
    77.            || gunModel.localPosition != homePosition)
    78.         {
    79.             //coarse adjustment
    80.             gunModel.localPosition = Vector3.Lerp(gunModel.localPosition,homePosition,strongRecoilResetRate*Time.deltaTime);
    81.             gunModel.localRotation = Quaternion.Lerp(gunModel.localRotation,homeRotation,strongRecoilResetRate*Time.deltaTime);
    82.  
    83.             //fine adjustment
    84.             gunModel.localPosition = Vector3.MoveTowards(gunModel.localPosition,homePosition,weakRecoilResetRate*Time.deltaTime);
    85.             gunModel.localRotation = Quaternion.RotateTowards(gunModel.localRotation,homeRotation,weakRecoilResetRate*Time.deltaTime);
    86.  
    87.             yield return null;
    88.         }
    89.     }
    90.  
    91.     Vector3 RandomVectorUniform ()
    92.     {
    93.         return new Vector3(Random.Range(0f,1f),Random.Range(0f,1f),Random.Range(0f,1f));
    94.     }
    95.  
    96.  
    97. }
    98.  
    as you can see after I got it working I began to play with it more and add some new features, like smoothing animation of the recoil back to home, recoils both in position and rotation, the recoil offset can be slightly randomized, some control for how fast you want to reset from the recoil, and finally a rate of fire setting. I didn't want to worry about particles or sounds in mine so those lines are commented out.

    lastly the bullet that is spawned is just a simple sphere with a Bullet script and a rigidbody
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4.  
    5. [RequireComponent(typeof(Rigidbody))]
    6. public class Bullet : MonoBehaviour
    7. {
    8.     public float bulletForce = 10000;
    9.  
    10.     void Start ()
    11.     {
    12.         GetComponent<Rigidbody>().AddForce(transform.forward*bulletForce);
    13.      
    14.         Destroy(gameObject,3);
    15.     }
    16.  
    17.     void OnCollisionEnter(Collision collision)
    18.     {
    19.         Destroy(gameObject);
    20.     }
    21. }
    22.  
     
    EthanRushbrook2 and Phoenix3666 like this.
  31. ShadowKitten101

    ShadowKitten101

    Joined:
    Jan 18, 2021
    Posts:
    1
    Thank you so much for this! I've been stuck on this problem for ages.