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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

How to time muzzle flash and recoil animations with bullet spread code?

Discussion in 'Scripting' started by Lethn, Jul 17, 2018.

  1. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    I've been thinking about an annoying problem and it's a bit of a project I've been wondering about the best way to handle muzzle flash and recoil animations. The actual making of the animations involved isn't a problem however I'm trying to make it time right with the actual fire rate in my code.

    Has anyone got any idea of how this would work? Perhaps I'm overthinking it and there's a really simple solution I was wondering if it was possible to use the fireTime float somehow but I don't think that will work.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class GunHit
    6.  
    7. {
    8.     public float damage;
    9.  
    10.     public RaycastHit raycastHit;
    11. }
    12.  
    13. public class RaycastShoot : MonoBehaviour {
    14.  
    15.  
    16.     public float fireDelay = 0.2f;
    17.     public float maxBulletSpreadAngle = 35.0f;
    18.     public float timeUntilMaxSpreadAngle = 1.0f;
    19.  
    20.     public GameObject tracerParticle;
    21.     public GameObject bulletImpact;
    22.     public LayerMask fAimDist;
    23.  
    24.  
    25.     private bool readyToFire = true;
    26.     private float fireTime;
    27.  
    28.     public Vector3 destination;
    29.  
    30.     // Use this for initialization
    31.     void Start () {
    32.        
    33.     }
    34.    
    35.     // Update is called once per frame
    36.     void Update () {
    37.  
    38.         if (Input.GetMouseButton (0) )
    39.        
    40.         {
    41.  
    42.             fireTime += Time.deltaTime;
    43.  
    44.             if (readyToFire)
    45.            
    46.             {
    47.  
    48.                 Vector3 fireDirection = transform.forward;
    49.                 Quaternion fireRotation = Quaternion.LookRotation (fireDirection);
    50.                 Quaternion randomRotation = Random.rotation;
    51.  
    52.                 float currentSpread = Mathf.Lerp (0.0f, maxBulletSpreadAngle, fireTime / timeUntilMaxSpreadAngle);
    53.  
    54.                 fireRotation = Quaternion.RotateTowards (fireRotation, randomRotation, Random.Range (0.0f, currentSpread));
    55.            
    56.                 RaycastHit hit;
    57.                 bool bHit = Physics.Raycast ( transform.position, fireRotation * Vector3.forward, out hit, fAimDist );
    58.    
    59.                     Invoke ("SetReadyToFire", fireDelay);
    60.                     readyToFire = false;
    61.            
    62.                     GameObject tracerParticleObject = Instantiate ( tracerParticle, transform.position, transform.rotation ) as GameObject;
    63.                     tracerParticleObject.GetComponent<moveTowardsBulletTracer>().destination = bHit ? hit.point : transform.position + ( fireRotation * Vector3.forward ).normalized * fAimDist;
    64.  
    65.                     if (bHit)
    66.  
    67.                     {
    68.                         GunHit gunHit = new GunHit();
    69.                         gunHit.raycastHit = hit;
    70.                         Instantiate ( bulletImpact, hit.point, Quaternion.LookRotation ( hit.normal ) );
    71.                     }
    72.  
    73.  
    74.             }
    75.  
    76.         }
    77.  
    78.         else
    79.        
    80.         {
    81.             fireTime = 0.0f;
    82.         }
    83.  
    84.     }
    85.  
    86.  
    87.  
    88.     void SetReadyToFire ()
    89.  
    90.     {
    91.         readyToFire = true;
    92.     }
    93.  
    94.  
    95.  
    96.  
    97.  
    98. }
    99.  
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    Why you can not make simple logic,
    if ( fire ) { // do animation }
    Wouldn't that just work?

    And, don't use instantiate in Update. these are expensive procedures, specially for firing bluets. Cache bullets in list, or other collection type as references.
     
  3. FlashMuller

    FlashMuller

    Joined:
    Sep 25, 2013
    Posts:
    449
    In Addition to Antypodish: Why isn't the muzzle flash part of the animation?
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,292
    That would be a pain in the ass to swap, if something changes.
     
  5. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    I was wondering about that, but I don't want it to just keep firing as the mouse button is pressed down, I want the animation and muzzle flash to match up with the fireRate so that way it looks right with the bullet spread. I'll check out the stuff you mentioned later, right now I'm just focusing on getting everything working, I also don't want the bullet spread to be changed because of any position movement due to the animation.

    You got it, I want to keep all of that seperate so that way I can swap any animations or muzzle flashes in and out if I want to do something fancy plus the if the recoil is caused by position changes then I don't want any weirdness happening if the muzzle flash is a child of the gun which is another thing I've been thinking about.

    . The recoil should not affect the bullet spread code and affect the bullets coming out as I want to be able to change the values easily

    . The muzzle flash should be timed with the recoil so every time the gun actually fires it needs to activate and then disable itself

    . The recoil animations themselves should time with the actual fire rate so it looks realistic and believable rather than just being some idle animation playing every time you hold the mouse button, if it were just a single shot weapon this would be easily dealt with but I'm going to have automatic weapons in my game too

    I appreciate I've picked a complicated subject that I'm a noob at but I'm moving onto shooters now so I'm learning as much as I can about how to deal with automatic weapons especially and it all needs to look right.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,558
    Simple fire rate is below.
    Or alternatively you can try use "invoke repeat" method. But I don't think is best approach for multiple weapons, with different fire rates.

    Code (CSharp):
    1.  
    2. private float fireRate = 0.1f ; // 10 times a second ( if fireTime is in seconds )
    3. private float nextFireTime = 0f ;
    4.  
    5. private bool fireNow = false ;
    6.  
    7. // Update is called once per frame
    8.     void Update () {
    9.  
    10.         fireNow = false ;
    11.  
    12.         if (Input.GetMouseButton (0) )      
    13.         {
    14.  
    15.             fireTime += Time.deltaTime;
    16.  
    17.             if (readyToFire)          
    18.             {
    19.  
    20.                 if ( fireTime >= nextFireTime )          
    21.                 {
    22.                     nextFireTime = fireTime + fireRate ;
    23.                     fireNow = true ;
    24.                 }
    25.  
    26.             }
    27.  
    28.         }
    29.  
    30.     }
     
  7. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    So would I simply activate my effects and animations within the fireNow boolean to get the mechanics I'm thinking of?