Search Unity

[CLOSED WITH FREE SCRIPTS] Need help with programming guns.

Discussion in 'Scripting' started by Lahzar, Jul 18, 2014.

  1. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    Greetings, ladies and gentlemen!

    Ive been working on a game with some friends for a bit now, but now we have encountered a problem. I am tasked with making the gun mechanics, aka. how the guns work. And after some research, I do not know what to do. I was wondering if anyone could give me an idea of what to do regarding some of these issues:

    Should you use raycasts, or rigidbodies? Should you fire from the camera, or the gun barrel? If you use raycasts, is there a way to make it go at a certain speed, or add bullet drop? If you use rigidbodies, how can you best make the bullets penetrate certain objects and loose momentum? How do you make hit objects take damage from rigidbodies, and how do you decide the damage; preset number - amount of objects penetrated? And how do you solve recoil with the builtin unity mouselook?

    I know that the awnsers to these questions are very much genre-based, and varies from game to game, but I want the pros and cons of every approach to programming guns. Can anyone help me out?
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    you should really start with a game design rather than "every way you can do general topic x"...

    what do you want your game to do?
     
  3. smitchell

    smitchell

    Joined:
    Mar 12, 2012
    Posts:
    702
    You should use ray casts most of the time. It all depends on your game, Raycasting needs to be done when your projectiles aren't actually visible so a submachine gun or something. And then rigidbodys are ok when you have a slower projectile like a RPG or something

    Yes: you could use yield WaitForSeconds(t) etc to way for it to ray cast.. And to add bullet drop you could take the ray cast hit position and drop the position slightly to fake the drop
     
  4. ChrisSch

    ChrisSch

    Joined:
    Feb 15, 2013
    Posts:
    763
    First of all, I like your question. I wonder whats the best way to do things as well a lot of times. Makes things a whole lot easier to program if you know the best way. And apologies for the long post in advance. xD

    Yup that's pretty much it. Bullets that eyes don't see are normaly raycast, and projectiles you can catch with your eye are rigidbodies with a trigger. And for the drop you can drop it slightly based on the distance of the target.

    Just want to add that if you use rigidbodies as bullets, they won't always hit. Especially if theres dozens of hundreds of flying around. And the weaker the computer the less will actually hit the target. That's why raycast is the way to go.

    Normally if its a FPS you'd fire from the camera, its easiest and guaranties hitting the center (with the precision offset you determine), and no one will be able to tell the difference, unless they stop to study your game instead of play it, but who does that in a FPS shooter? xD

    If its a third person shooter, go from the characters head, or torso, or arms pivot, because you will be rotating that to face where you point anyway, and its closest to gun in height, so why not use it. I'm making a 3rd person controller system and the ray is coming from neck atm, ill probably need to put it higher in the head later.

    EDIT: Not from neck, I have an empty game object there, pointing where the cam is pointing, so even if the bone of the character isn't rotated exactly to the center, I'm still getting a pin point precise aim.

    Rigidbodies will carry a script on them with a damageAmount variable or something, and deduce the health of the anything that enters their trigger by that amount, and destroy the projectile.

    Raycasts will be on the weapon script (even tho they come from the camera) so that's where you''ll hold the damageAmount variable. They'll deduce that from health of anything they hit.

    All that applies for objects/enemies that have a "Enemy" or "Destructible" tag or something.

    Recoil? Do you mean the weapon going up as you fire, or just general lack of precision?
    For weapon going up, with each fired bullet you'll have to make the cam move a bit up inside its script. How depends on how you programmed your camera. I've never done it before so can't tell you any details.

    For realistic "not precise to the dot" shooting, I just add a random offset within some range to the raycast, depends on the weapon, with each bullet fired.

    Here's a list of a few basic variables to get you started on having a customizable script fitting for any weapon:
    - fire rate (how fast do the bullets come out)
    - automatic (is it an automatic or not?)
    - bullet range
    - weapon damage (you can also make something like wpnDmgMin and wpnDmgMax, and every hit get a random between)
    - bullet offset (how unprecise is the weapon)
    - magazine capacity (how much can fit in curent mag)
    - bullets in magazine (how much are currently in mag)
    - spare magazine (how much spare ammo you have)

    And that's pretty much it for the basics of weapon specs vars. You'll probably end up having far more variables for various checks, like "can the weapon shoot again?" depending on fire rate, and reloading, and so on.
     
    Lahzar and Jaqal like this.
  5. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    For my shooter, I plan to raycast from the camera to determine the point the player is aiming at. Then I either use a rigidbody for stuff like rockets, or raycasts for everything else. In both cases, the projectile will come from the camera. No one will be able to tell a difference.

    If you render effects on your bullets, such as tracers, render those coming from your gun to the point of impact. Because of this, the tracers may clip through walls slightly ahead of you (which is exactly why you'd want to Raycast from the camera), but this is ok and no one will really notice. This is how almost all AAA shooters are done. Tracer visual effects don't have to match the bullet perfectly except at the point of impact.

    Hope this helps!
     
    Lahzar and ChrisSch like this.
  6. ChrisSch

    ChrisSch

    Joined:
    Feb 15, 2013
    Posts:
    763
    Yup I'm doing trace effect the same way.
     
    Lahzar likes this.
  7. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    Thank you everyone for your great responses! I still have some questions and awnsers, though;

    I know, sorry about that. But Ive been looking around the internet and found awnsers to these questions that does not fit my genre, and if someone has the same problem as me, regardless of genre, they can have a nice place to start. The game Im developing is a FPS, and I do want realisticly beheaving guns. Something like planetside 2 or battlefield 4, which has nice recoil and bulletdrop.


    I dont think I explained well enough what I meant. In real life objects travel at certain speeds, and a raycast hits instantly. Is there a way to calculate where the bullet would've been in its trajectory? I can't just get where the bullet would hit and start a timer based on distance, because then you would not be able to shoot targets moving too fast.

    And about the bullet drop; I did see something about calculated bullet trajectory, but I didn't understand anything... I did get an idea from your idea, tho. It'll be easier to explain with an example. The effective firing range on the mk 12 special purpose rifle (http://en.wikipedia.org/wiki/Mk_12_Special_Purpose_Rifle) is aprox. 500. So I was thinking for the time being: Fire a raycast 500m, then if it has not hit something yet, fire from the 500m spot, say 25% downwards for a few hundred meters, then repeat that with shorter and shorter distances. I think it would work until I understand trajectory math.



    Agree! And dont worry about long posts! Its the knowledge you share from them that matters!

    The recoil Im looking for is a mix of both. I can do the "not precise to the dot" shooting, but Im using the builting unity camera, that comes with the first/third-person controllers. I get problems when I try to rotate it externally, and Im not sure how to do it from within the mouseLook script. Need help.


    Thanks for posting, but Im not as big a noob as I might seem. I do have *some* scripting experience. :) I did make a few different gun scripts before I posted this, but Im not the best programmer in the world, so dont yell if there is something really awfully done in here. Also note that this may not be the right version of the script, since I have modified it alot recently to make improvements, but I cant do everything in single sessions. Anyways, here it is:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [AddComponentMenu("CornerStriker/Guns/Sniper")]
    6. public class Sniper : MonoBehaviour {
    7.     private string message = "ALPHA v1";
    8.     private float nextFire = 0.0f;
    9.     private float FOV = 90;
    10.     private bool canShoot = false;
    11.     private bool aiming = false;
    12.     private int ammo;
    13.     private int clip;
    14.     private Health health;
    15.     private MouseLook look;
    16.  
    17.     public GameObject[] bulletMarks;
    18.     public AudioClip[] gunShots;
    19.     public AudioClip[] outOfAmmo;
    20.     public AudioClip reloadSound;
    21.     public Texture2D scope;
    22.     public GameObject player;
    23.     public GameObject VFX;
    24.     public Transform gun;
    25.     public Camera scopeCam;
    26.     public float recoilY = 1.5f;
    27.     public float recoilX = 0.5f;
    28.     public float rateOfFire = 0.5f;
    29.     public float dmg = 33;
    30.     public int bullets = 30;
    31.     public int magazines = 4;
    32.     public int xScope = 2;
    33.  
    34.     float force = 5f;
    35.     float upSpeed = 9f;
    36.     float downSpeed = 20f;
    37.  
    38.     private Vector3 ang0;
    39.     private float targetX;
    40.     private Vector3 ang = Vector3.zero;
    41.  
    42.     void Start () {
    43.         ang0 = transform.localEulerAngles;
    44.         VFX.SetActive(false);
    45.         ammo = bullets;
    46.         clip = magazines;
    47.         canShoot = true;
    48.         health = GetComponentInParent<Health>();
    49.         look = GetComponentInParent<MouseLook>();
    50.         FOV = scopeCam.fieldOfView;
    51.     }
    52.  
    53.     IEnumerator StartReload()    {
    54.         StartCoroutine("Reload");
    55.         ammo = 0;
    56.         yield return new WaitForSeconds(1.24f);
    57.         StopCoroutine("Reload");
    58.         ammo = bullets;
    59.         message = "ALPHA v1";
    60.         canShoot = true;
    61.     }
    62.  
    63.     IEnumerator Reload()    {
    64.         while(true)    {
    65.             canShoot = false;
    66.             yield return null;
    67.         }
    68.     }
    69.  
    70.     IEnumerator FX()    {
    71.         VFX.SetActive(true);
    72.         Object flash = Instantiate(VFX, VFX.transform.position, VFX.transform.rotation);
    73.         VFX.SetActive(false);
    74.         yield return new WaitForSeconds(0.25f);
    75.         Destroy(flash);
    76.     }
    77.  
    78.     void Update() {
    79.  
    80.         //Fake recoil on gun. TODO: Replace with animation.
    81.         ang.x = Mathf.Lerp(ang.x, targetX, upSpeed * Time.deltaTime);
    82.         transform.localEulerAngles = ang0 - ang;
    83.         targetX = Mathf.Lerp(targetX, 0, downSpeed * Time.deltaTime);
    84.  
    85.         if(Input.GetButtonDown("Reload"))    {
    86.             if(canShoot == true)    {
    87.                 if(clip > 0)    {
    88.                     clip--;
    89.                     message = "RELOADING";
    90.                     StartCoroutine("StartReload");
    91.                     audio.PlayOneShot(reloadSound);
    92.                 } else {
    93.                     message = "OUT OF AMMO";
    94.                 }
    95.             }
    96.         }
    97.      
    98.         if(Input.GetButton("Fire1") && Time.time > nextFire)    {
    99.             nextFire = Time.time + rateOfFire;
    100.             ForceFire();
    101.         }
    102.      
    103.         if(Input.GetButton("Aim"))    {
    104.             scopeCam.depth = 3;
    105.             scopeCam.fieldOfView = FOV/xScope;
    106.             look.sensitivityX = 5;
    107.             look.sensitivityY = 5;
    108.             aiming = true;
    109.         } else {
    110.             scopeCam.depth = 0;
    111.             scopeCam.fieldOfView = FOV;
    112.             look.sensitivityX = 15;
    113.             look.sensitivityY = 15;
    114.             aiming = false;
    115.         }
    116.     }
    117.  
    118.     void ForceFire()    {
    119.         RaycastHit hit;
    120.      
    121.         if(ammo > 0 && canShoot == true)    {
    122.             targetX += force;
    123.  
    124.             Debug.DrawRay(gun.position, gun.forward * 500, Color.red);
    125.             if(Physics.Raycast(scopeCam.transform.position, player.transform.forward, out hit, 500.0F))    {
    126.                 hit.transform.gameObject.SendMessageUpwards("TakeDmg", dmg, SendMessageOptions.DontRequireReceiver);
    127.                 Instantiate(bulletMarks[Random.Range(0,7)], hit.point, Quaternion.FromToRotation(Vector3.back, hit.normal));
    128.                 if(hit.rigidbody != null)    {
    129.                     hit.rigidbody.AddExplosionForce(force*150, hit.point, 0.5f);
    130.                 }
    131.             }
    132.             StartCoroutine("FX");
    133.             audio.PlayOneShot(gunShots[Random.Range(0,2)]);
    134.             ammo--;
    135.         } else {
    136.             audio.PlayOneShot(outOfAmmo[Random.Range(0,2)]);
    137.         }
    138.     }
    139.  
    140.     void OnGUI()    {
    141.         if(aiming == true)    {
    142.             GUI.DrawTexture(new Rect(0,0,Screen.width,Screen.height), scope, ScaleMode.ScaleToFit);
    143.         } else {
    144.             GUI.Box(new Rect(Screen.width - 200, Screen.height - 100, 200, 200), "Mk.12 Special Purpose Rifle");
    145.             GUI.Label(new Rect(Screen.width - 100 - (150/3), Screen.height-75, 150, 20), "Ammo: " + ammo + "/" + clip);
    146.             GUI.Label(new Rect(Screen.width - 100 - (150/3), Screen.height-50, 150, 20), "Health:" + health.health + "/" + health.maxHealth);
    147.             GUI.Label(new Rect(Screen.width - 100 - (150/3), Screen.height-25, 150, 20), message);  
    148.         }
    149.     }
    150. }
    151.  
    I will rigidbody for slow moving objects, like the rpg projectile, then. Thank you.
    I think that was all the posts needed to be replied to for digging deeper. Thank you everyone for helping me out, but one last very important thing:

    I feel my scripts get very messy in the editor when I have multiple guns, so I did some research, and I found that some people make all their guns in a single script, using Object Oriented Programming. I tried my best to understand this scripting method, can someone please tell me pros and cons and where to get an easy start with this. Thank you in advance.
     
  8. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    For Raycasts and bullets, if the bullet isn't instant, then I just raycast to where the bullet should move this frame only. I raycast to the new bullet's position every frame until the raycast actually hits something, then I know that the bullet hits this frame.

    The problem with high speed rigidbodies is that the bullet can go "through" walls if it is moving so fast it never intersects the wall during a FixedUpdate(). Changing the collision detection mode can help, but really raycasting is the only way to guarantee super fast bullets don't go through things.

    Object Oriented Programming is definitely the way to go. Eg: You can write a base Gun script, then extend that script to MachineGun or ShotGun which would act differently when running their Fire() function. This way you only need to code one function instead of rewriting the entire class. It is difficult to teach Object Oriented Programming through a forum post, but I would start by making a base class, then making another class that extends that original base class.
     
    Last edited: Jul 29, 2014
    Lahzar likes this.
  9. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    Ah! Very clever! Didn't think of that. Will definently try that out! So that solves recoil and bullet speed.
    Im researching OOP, and I hope to nail that soon, so remaining problems:
    - Recoil (Rotate camera)
    - Penetrating certain objects

    Penetrating certain objects is something we have not discussed yet. What I mean is just being able to shoot trough certain objects, and have that object affect the speed and drop of the bullet (raycast). The counter-strike series has a nice system like this. I have an idea of how to do this, and I'll post more once Ive actually written a script.
     
  10. ChrisSch

    ChrisSch

    Joined:
    Feb 15, 2013
    Posts:
    763
    Hmm.. I guess for the camera you could add a bit of X (or other appropriate axis) to the eulerAngles rotation every bullet fired. Normally you should do rotations in Quaternions, but since they're a bit complicated and described as "magic" in most tutorials I read, using euler angles to perform simple rotations should be fine in most cases.

    And penetrating objects certainly is an interesting topic. xD
    Umm for starters get the hit normal on the object, then somehow (yes i know very informative), copy that to the other side, and create a new raycast there.

    Or I guess a simpler, probably more limited, way would be to have those penetrable objects on a different layer, and let the raycast pass through it (ignore the collider) but with reduced damage or whatever. If that's even possible with a raycast (to detect but not detect lol). I haven't done much layers stuff other than simply ignoring objects on some layers.

    Damn you're making me wanna create a weapons asset or something. xD
     
    Lahzar likes this.
  11. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    Haven't made much progress programming wise, but I have been busy trying to learn to texture models. I have made 6 untextured models until now, and this is my most modelled one (img below). Its an AK-12, with a recreation of the Crimson Woodlands camo from BF4, that I made in photoshop. (Using this tut:
    and colours from memory).
    This gun is the only thing Ive textured whatsoever so far, but Im trying to nail making scratches and other small details.
    AK12_camo1_prtsc.png (Sorry it takes so much space of the page, didn't crop it the right way...)

    I have tried this and it worked to some extent. The problem I had with it was with the unity builtin mouselook. (I have not made a custom mouselook because I have had no need to.) I find this hard to explain, but I'll try: When you rotate the camera itself, the limitations always stay relative to the camera rotation, but the mouse location does not. So after the camera has rotated to a certain degree, you cannot manually pull down your mouse to counter the recoil, because the mouse has reached the min Y value, so your mouse just stops, and its like you shoot without moving the mouse. Its a very bad explanation, I know. But I cannot make a video about it or post the script, because I deleted it.

    I relieased that it could sound wrong, so I try to say "shoot trough objects" now xP Im trying to finish up what Im currently doing in the script and with texturing before I expand on the script.
     
  12. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
  13. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    Bump. (Does this even work here?)

    After days and weeks of nothing, I am reviving this thread. I must start of with apologizing for the lack of response, but as most of us know: school started recently. And Im velly velly young ( ;( sadface).

    First of: @novashot
    Thank you very very much for this. It was nice to look trough, but Im not really happy with just getting a script online, I really want to do it myself. However, looking over your scripts gave me some needed confirmation of a few things on how to do stuff. Thank you. Also a nice tips for you would be to use regions in your code, since reading your multi-hundreds of lines of code scripts was very hard :S

    Second:
    I have basically finished a working gun script, and I will post it once its actually done. I have not added the recoil yet, but I have found out that all you need to do is change the mouselook script to have offsetX & Y values where the script gets the mouse input. Then change the offsets from the main gun script everytime you fire. I have added a few other things aswell, like: the realistic notonthedot shooting that @ChrisSch was talking about. I have also added a very basic hitmarker. I am currently trying to tweak @Garth Smith's bullet system to work with deltaTime/FPS (googling it ASAP), and add shooting trough shiz (which I cannot imagine will be very hard when I think about it). Im using linecasting ATM to check for collisions, but I have heard bad things about it, so might change to normal raycasting.

    Third(ly?) and finally:
    I need help with OOP. I cant find a good place to start. I set up a class for a gun, but I cant seem to change any variables around between classes. Is that even how you do it. HELP PLEASE! D:

    PS: I have more things I am about 97.34% sure of how to implement, but I dont have alot of free time when in school. I also just write this post as fast as I can, so I can get the most out of my free time. Hope you understand. -Lahzar
     
  14. Lahzar

    Lahzar

    Joined:
    May 6, 2013
    Posts:
    87
    I think its time to close this thread now. Got alot anwsered. I still dont know anything about OOP. I ended up with 2 scripts. I will publish the unpolished versions for free right here, while I keep my tweaked ones :) You're welcome. Unpolished but AAA quality :)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. //MADE BY IMRE ANGELO @ http://forum.unity3d.com/threads/need-help-with-programming-guns.257663/
    5.  
    6. [AddComponentMenu("Evil/Weapons/Bullit_1.0/Master")]
    7. public class WeaponMaster : MonoBehaviour {
    8.     public LayerMask masksToRay = 1 << 10;
    9.     public Rigidbody projectile;
    10.     public Transform barrel;
    11.     public Camera mainCam;
    12.     public float force = 10f;
    13.  
    14.     #region audio
    15.     public AudioClip[] gunShot;
    16.     #endregion audio
    17.  
    18.     #region ammo
    19.     public int maxAmmo = 30;
    20.     public int startMags = 4;
    21.     public int ammo;
    22.     public int magazines;
    23.     #endregion ammo
    24.  
    25.     #region recoilVar
    26.     private float spread = 0;
    27.     public float spreadMax = 7.5f;
    28.     public float sprSpeed = 0.5f;
    29.     public float recoilX = 12;
    30.     public float recoilY = 5;
    31.     #endregion recoilVar
    32.  
    33.     #region varBurst
    34.     public float burstRate = 0.09f;
    35.     public bool burstFire = false;
    36.     #endregion varBurst
    37.  
    38.     #region canFire
    39.     public float rateOfFire = 0.11f;
    40.     public float reloadT = 1.24f;
    41.  
    42.     private float nextFire = 0.0f;
    43.     private bool canShoot = true;
    44.     #endregion canFire
    45.  
    46.     #region swapWep
    47.     public static int curWep = 0;
    48.     #endregion swapWep
    49.  
    50.     #region aimWep
    51.     private float camFOV;
    52.     #endregion aimWep
    53.  
    54.     public MouseLook look;
    55.  
    56.     void Start()    {
    57.         look = transform.parent.GetComponent<MouseLook>();
    58.         ammo = maxAmmo;
    59.         magazines = startMags;
    60.         camFOV = mainCam.fieldOfView;
    61.     }
    62.  
    63.     IEnumerator Reload()    {
    64.         magazines--;
    65.     //    animation.CrossFade("FullReload");
    66.         yield return new WaitForSeconds(reloadT);
    67.         ammo = maxAmmo;
    68.     }
    69.  
    70.     IEnumerator SemiReload()    {
    71.         magazines--;
    72.     //    animation.CrossFade("SemiReload");
    73.         yield return new WaitForSeconds(reloadT-(reloadT/3));
    74.         ammo = maxAmmo;
    75.     }
    76.  
    77.     void Update()    {
    78.         #region fire
    79.         if(Input.GetMouseButton(0) && Time.time > nextFire && canShoot && ammo > 0)    {
    80.             nextFire = Time.time + rateOfFire;
    81.             Fire();
    82.         }
    83.         #endregion fire
    84.  
    85.         #region swapWeapon
    86.         if(Input.GetAxis("Mouse ScrollWheel") < 0)
    87.             curWep--;
    88.    
    89.         if(Input.GetAxis("Mouse ScrollWheel") > 0)
    90.             curWep++;
    91.  
    92.         if(curWep < 0)
    93.             curWep = 1;
    94.    
    95.         if(curWep > 1)
    96.             curWep = 0;
    97.         #endregion swapWeapon
    98.  
    99.         #region reload
    100.         if(Input.GetButtonDown("Reload") && magazines > 0 && ammo != maxAmmo)    {
    101.             if(ammo > 0)    {
    102.                 StartCoroutine("SemiReload");
    103.             } else {
    104.                 StartCoroutine("Reload");
    105.             }
    106.         }
    107.         #endregion reload
    108.  
    109.         #region aimDownSight
    110.         if(Input.GetButton("Aim"))    {
    111.             //mainCam.position = aimsight.position
    112.             mainCam.fieldOfView = camFOV/1.5f;
    113.         } else {
    114.             //mainCam.position = norsight.position
    115.             mainCam.fieldOfView = camFOV;
    116.         }
    117.         #endregion aimDownSight
    118.  
    119.         #region spreadLess
    120.         if(Time.time > nextFire && spread > 0)    {
    121.             spread-=sprSpeed;
    122.         }
    123.         #endregion spreadLess
    124.  
    125.         #region dampenRecoil
    126.         //TODO
    127.         #endregion dampenRecoil
    128.     }
    129.  
    130.     void Fire()    {
    131.         RaycastHit hit;
    132.  
    133.         Vector3 direction = (mainCam.transform.right * Random.Range(-spread, spread)) + mainCam.transform.up * Random.Range(-spread, spread) + mainCam.transform.forward * 100;
    134.  
    135.         audio.Stop();
    136.         AudioSource.PlayClipAtPoint(gunShot[Random.Range(0,gunShot.Length)], barrel.transform.position);
    137.  
    138.         if(Physics.Raycast(mainCam.transform.position, direction, out hit, 1000f, masksToRay))    {
    139.             Quaternion newRot = Quaternion.LookRotation((hit.point - barrel.position).normalized);
    140.             GameObject newShot = Instantiate(projectile, barrel.position, newRot) as GameObject;
    141.             newShot.rigidbody.AddForce(newShot.transform.forward * force, ForceMode.VelocityChange);
    142.  
    143.         } else {
    144.             Quaternion rot = Quaternion.LookRotation((mainCam.transform.forward - barrel.position).normalized);
    145.             GameObject shell = Instantiate(projectile, barrel.position, rot) as GameObject;
    146.             shell.rigidbody.AddForce(shell.transform.forward * force, ForceMode.VelocityChange);
    147.         }
    148.  
    149.         look.offsetX += recoilX;
    150.         look.offsetY += recoilY;
    151.    
    152.         if(spread < spreadMax)
    153.             spread++;
    154.         ammo--;
    155.     }
    156. }

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. //MADE BY IMRE ANGELO @ http://forum.unity3d.com/threads/need-help-with-programming-guns.257663/
    5.  
    6. [AddComponentMenu("Evil/Weapons/Bullit_1.0/Bullet")]
    7. public class Bullet : MonoBehaviour {
    8.     public LayerMask ignoreRays;
    9.     public GameObject marker;
    10.     public float wind = 2;
    11.     public float mps = 16;
    12.  
    13.     private Vector3 prev = new Vector3(0,0,0);
    14.  
    15.     void Start () {
    16.         prev = transform.position;
    17.     }
    18.  
    19.     void FixedUpdate() {
    20.     //    transform.Translate(transform.forward*mps);
    21.         transform.Translate(transform.right*wind*Time.deltaTime);
    22.  
    23.         RaycastHit hit;
    24.         if(Physics.Linecast(prev, transform.position, out hit/*, ignoreRays*/))    {
    25.             if(hit.collider.tag == "Enemy")    {
    26.                 hit.transform.SendMessageUpwards("TakeDmg", 40.0f, SendMessageOptions.DontRequireReceiver);
    27.                 print("Hit enemy! *TODO: Hitmarker!*");
    28.  
    29.             //    mps--;
    30.             } else if(hit.collider.tag == "MaterialThinSteel")    {
    31.                 print ("Hit ThinSteel");
    32.             } else if(hit.collider.tag == "MaterialWood")    {
    33.                 print("Wood!");
    34.             } else if(hit.collider.tag == "Gun") {
    35.                 print("Hit gun!");
    36.             } else {
    37.                 Instantiate(marker, hit.point, transform.rotation);
    38.                 Destroy(this.gameObject);
    39.             }
    40.         }
    41.  
    42.         prev = transform.position;
    43.     }
    44. }
     
    Last edited: Mar 11, 2015