Search Unity

Delaying A Function Update Method

Discussion in 'Scripting' started by Jake_The_Snake, Jun 29, 2016.

  1. Jake_The_Snake

    Jake_The_Snake

    Joined:
    Mar 2, 2016
    Posts:
    8
    Hi everyone, I'm currently creating a first-person shooter and I've run up against a wall. I've figured out how to set the ammunition amount to 30 on my functional gun, yet when I play the animation to reload after the gun is emptied of those 30 rounds, it resets the number of bullets to 30 instantaneously; allowing the user to fire the gun mid-animation. I am aware that this is because my function Update method calls the reset to 30 bullets instantly, even though the animation is still playing. I've tried looking to covert that portion of scripting into a coroutine, but I can't seem to get it to work. Below is the unmodified script of my gun raycast shooting script. My animation triggers are within another script but that is unimportant. Please help me fix my script, I can't seem to figure it out.

    Code (JavaScript):
    1.  #pragma strict
    2.  
    3. var bulletHole : GameObject;
    4. var ammo = 30; //AMMO VARIABLE
    5. var BulletFire : AudioSource;
    6. var recoilMod : Transform;
    7.      var weapon : GameObject;
    8.      var maxRecoil_x : float = -20;
    9.      var recoilSpeed : float = 10;
    10.      var recoil : float = 0.0;
    11.  
    12. function Start () {  
    13. }
    14. function Update () {
    15.   var fwd = transform.TransformDirection(Vector3.forward)*10;
    16.   var hit : RaycastHit;
    17.   Debug.DrawRay(transform.position, fwd, Color.green);
    18.   var hitRotation = Quaternion.FromToRotation(Vector3.forward, hit.normal);
    19.  
    20.     if(Input.GetButtonDown("Fire1")){ //FIRING MECHANISM
    21.         if(ammo > 0) {
    22.             recoil+= 0.1;
    23.             BulletFire.Play();
    24.             GetComponent.<ParticleSystem>().Emit(10);
    25.             Physics.Raycast(transform.position, fwd, hit, 1000);
    26.             var clone = Instantiate(bulletHole, hit.point, Quaternion.identity);
    27.             clone.transform.rotation = Quaternion.FromToRotation(transform.up, hit.normal) * clone.transform.rotation;
    28.             Destroy(clone.gameObject, 5);
    29.             ammo --;
    30.         }
    31.         else{ //AMMO RUNS OUT AND PLAYS THIS SOUND
    32.             GetComponent.<AudioSource>().Play();
    33.         }
    34.       }
    35. [B]      [/B]else if(Input.GetKeyDown (KeyCode.R)) { //CODE THAT RESETS AMMO
    36.             ammo = 30;
    37.         }
    38.       recoiling();
    39. }
    40.       function recoiling() {
    41.          if(recoil > 0)
    42.          {
    43.              var maxRecoil = Quaternion.Euler (maxRecoil_x, 0, 0);
    44.              // Dampen towards the target rotation
    45.              recoilMod.rotation = Quaternion.Slerp(recoilMod.rotation, maxRecoil, Time.deltaTime * recoilSpeed);
    46.              weapon.transform.localEulerAngles.x = recoilMod.localEulerAngles.x;
    47.              recoil -= Time.deltaTime;
    48.          }
    49.          else
    50.          {
    51.              recoil = 0;
    52.              var minRecoil = Quaternion.Euler (0, 0, 0);
    53.              // Dampen towards the target rotation
    54.              recoilMod.rotation = Quaternion.Slerp(recoilMod.rotation, minRecoil,Time.deltaTime * recoilSpeed / 2);
    55.              weapon.transform.localEulerAngles.x = recoilMod.localEulerAngles.x;
    56.          }
    57. }
    58.          
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,603
    You could use Invoke to call a method after a set number of secs(equal to the time of your reload) before the reload actually happens.

    Normally if I'm doing a coroutine for something like this, you would do something like
    Set a bool to true (something like, isCurrentlyReloading)
    Start coroutine that checks the bool in a while loop. As long as it's true, just wait.
    Once reloading is done, set isCurrentlyReloading to false.
    while loop in coroutine exits and grants ammo.

    Now, you might be able to check if the animation is playing, and if it is, don't grant the ammo.
    Or, you could start the coroutine with a yield return new waitForSeconds(animationTime);

    The simplest way is probably the invoke. The downside is you can't pass parameters to a method called by invoke. Plus you'll have to have a way to get your reload time(assuming different guns with different reload times).
     
    Jake_The_Snake likes this.
  3. LTK

    LTK

    Joined:
    Jul 16, 2015
    Posts:
    22
    you need a bool fiel for check reloading
    bool reloading = false;
    //------------------Update---------------------///
    //---- Fire---//
    if(ammo > 0 && !reloading)
    // spawn bullet
    ....
    //---- Start Reload----//
    reloading = true;
    startcoroutine(reloading);
    //-------------------------------------------------------------
    //----Reloading---//
    yield WaitForSeconds (time reload);
    ammo = 30;
    reloading = false;
     
    Jake_The_Snake likes this.
  4. Jake_The_Snake

    Jake_The_Snake

    Joined:
    Mar 2, 2016
    Posts:
    8
    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var isReloading : boolean = false;
    4. var bulletHole : GameObject;
    5. var ammo = 30;
    6. var BulletFire : AudioSource;
    7. var recoilMod : Transform;
    8.      var weapon : GameObject;
    9.      var maxRecoil_x : float = -20;
    10.      var recoilSpeed : float = 10;
    11.      var recoil : float = 0.0;
    12.  
    13. function Start () {
    14.     while(isReloading){
    15.         Invoke("reloading", 2);
    16.     }
    17. }
    18. function Update () {
    19.   var fwd = transform.TransformDirection(Vector3.forward)*10;
    20.   var hit : RaycastHit;
    21.   Debug.DrawRay(transform.position, fwd, Color.green);
    22.   var hitRotation = Quaternion.FromToRotation(Vector3.forward, hit.normal);
    23.  
    24.     if(Input.GetButtonDown("Fire1")){
    25.         if(ammo > 0 && !isReloading) {
    26.             recoil+= 0.1;
    27.             BulletFire.Play();
    28.             GetComponent.<ParticleSystem>().Emit(10);
    29.             Physics.Raycast(transform.position, fwd, hit, 1000);
    30.             var clone = Instantiate(bulletHole, hit.point, Quaternion.identity);
    31.             clone.transform.rotation = Quaternion.FromToRotation(transform.up, hit.normal) * clone.transform.rotation;
    32.             Destroy(clone.gameObject, 5);
    33.             ammo --;
    34.         }
    35.         else{
    36.             GetComponent.<AudioSource>().Play();
    37.         }
    38.       }
    39.       else if(Input.GetKeyDown (KeyCode.R)) {
    40.                 isReloading = true;
    41.         }
    42.       recoiling();
    43. }
    44.       function reloading () {
    45.               ammo = 30;
    46.               isReloading = false;
    47.       }
    48.       function recoiling() {
    49.          if(recoil > 0)
    50.          {
    51.              var maxRecoil = Quaternion.Euler (maxRecoil_x, 0, 0);
    52.              // Dampen towards the target rotation
    53.              recoilMod.rotation = Quaternion.Slerp(recoilMod.rotation, maxRecoil, Time.deltaTime * recoilSpeed);
    54.              weapon.transform.localEulerAngles.x = recoilMod.localEulerAngles.x;
    55.              recoil -= Time.deltaTime;
    56.          }
    57.          else
    58.          {
    59.              recoil = 0;
    60.              var minRecoil = Quaternion.Euler (0, 0, 0);
    61.              // Dampen towards the target rotation
    62.              recoilMod.rotation = Quaternion.Slerp(recoilMod.rotation, minRecoil,Time.deltaTime * recoilSpeed / 2);
    63.              weapon.transform.localEulerAngles.x = recoilMod.localEulerAngles.x;
    64.          }
    65. }
    66.          
    I've tried to create an Invoke method and it cancels firing during the animation, but then doesn't ever give 30 ammo again. The gun doesn't shoot after the animation. Here is my edited script. Thanks for all the help.
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,603
    Your reloading invoke is in start. How are you triggering it? Shouldn't you have it with your reload key press?
    So when you do your reload (pressing r) it should check if you're already reloading(so it doesn't trigger multiple times) then set isReloading to true and then hit the invoke.

    Also may need a check to make sure the gun isn't full.
     
    Jake_The_Snake likes this.
  6. Jake_The_Snake

    Jake_The_Snake

    Joined:
    Mar 2, 2016
    Posts:
    8
    Thank you so much for all your help; I got my script to work completely after your last post. I really appreciate it, have a great day!