0

I am trying to create a procedural gun controller, but I can't find why my gun behaves so weird when I change the fire mod to automatic. To understand this better, I will give an example: when I try to shoot by pressing the "Mouse0" key, on semi auto mod it works fine, it behaves like I want it to (the bolt kicks back when I shoot, the front barrel kicks back - I animate them with code instead of frame animations from Unity or a 3rd party soft like Blender), but..., when I change to automatic, the problem is not that I get errors, The animations of the moving pieces don't work as they should and are not triggered correctly.

I tried to use different methods for shooting(using the WaitForSeconds() and WaitForSecondsRealtime() while using coroutines). It didn't work. I tried using the time function with scaled and unscaled time in the update function. I still got the same results.

What should I do to?

This is the shoot function untill now:

void GunFireManagement()
{
    if (fireType == fireMethod.single)
    {
        foreach (BlowBack anim in animations)
        {
            if (Input.GetKeyDown(KeyCode.Mouse0))
            {
                gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
                anim.piece.transform.position = anim.kickbackState.transform.position;
            }

            if (anim.piece.transform.position != anim.initialPosition.transform.position)
            {
                anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
            }
            Destroy(gunSoundClone, 0.5f);
        }
    }
    if (fireType == fireMethod.auto)
    {
        foreach (BlowBack anim in animations)
        {
            if (Input.GetKey(KeyCode.Mouse0) && Time.time - lastFired > 1f/autoFireRate)
            {
                lastFired = Time.time;
                gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
                anim.piece.transform.position = anim.kickbackState.transform.position;
            }

            if (anim.piece.transform.position != anim.initialPosition.transform.position)
            {
                anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
            }
            Destroy(gunSoundClone, 0.5f);
        }
    }
}
  • what error are you getting? null object reference? – Sherry Aug 29 '22 at 10:31
  • I am not getting any error – Fieraru X Aug 29 '22 at 10:33
  • The problem is the behavieur of the moving pieces – Fieraru X Aug 29 '22 at 10:34
  • I am sorry actually your question kinda feels hard to understand because you are not actually defining that what kind of behavior your bolt has on auto fire. Like, is it moving continuously and not stopping or it snaps from one position to another? – Sherry Aug 29 '22 at 10:49
  • When i press Mouse0 key, it needs to snap to a position I define(to have that quick kickback feeling u see on real guns) and then using the lerp function, it goes back to it's original position. I use emptyes for this. – Fieraru X Aug 29 '22 at 11:12
  • The problem on automatic mod is that if keep Mouse0 down, the bolt sometimes doesnt snap correctly or doesnt snap at all. It's movement it's inconsistent. – Fieraru X Aug 29 '22 at 11:16
  • have you tried using Vector3.Distance between two Vectors instead of directly comparing its values?? like the way you are doing? if (anim.piece.transform.position != anim.initialPosition.transform.position) because maybe its not detecting the position difference between its current and initial position; – Sherry Aug 29 '22 at 11:21
  • Basically what i mean to say is that debug the positions before mouse hold and after the lerping to see what are the differences in positions as far as I can see that should be the only issue other code looks fine but because (if I am not wrong) you are calling this loop inside the any update functions right? if that is so then try not calling loop all the time instead you can wrap that loop with in the mouse down functionality other wise loop will continue to run regardless of input – Sherry Aug 29 '22 at 11:26
  • I'm curious as to why `Time.deltaTime` is not part of your Lerp equation. Typically you'd do `anim.speed * Time.delatTime`. You may have defined anim.speed to function appropriately with a single shot but is not having the same effect in automatic mode. – jiveturkey Aug 29 '22 at 12:36
  • I did have Time.deltaTime, but it messed up the snaping in kickback position. It was visibly horrible. That's why I use a constant variable. when it depended on time, it always hanged the position of the next kickback – Fieraru X Aug 29 '22 at 14:44
  • changed the position* – Fieraru X Aug 29 '22 at 14:55

1 Answers1

0

The issue is how you are using Vector3.Lerp. The first two arguments you pass to the method are supposed to be the start and end positions of the animation, and the third one, t, is supposed to be the progress of the animation from the start towards the end, as a value between 0 and 1.

You can calculate the value of t by dividing the time since the shot started with the duration of the animation. For example if the length of the animation is 2 seconds, and the short started 1 second ago, then t should be 0.5.

    if(isFiring)
    {
        float timeSinceShotStart = Time.deltatime - lastFired;
    
        // t = s / v
        float animationDuration = 1f / anim.speed;

        UpdateBlockBackAnimationState(timeSinceShotStart / animationDuration);
    }   
}

private void SetBlowBackAnimationState(float progress01)
{
    foreach(BlowBack anim in animations)
    {
        Vector3 initialPosition = anim.initialPosition.transform.position;
        Vector3 finalPosition = anim.finalPosition.transform.position;
        anim.piece.transform.position = Vector3.Lerp(initialPosition, finalPosition, progress01);
    }
}

I recommend you try to split up your code into smaller methods that are easier to understand. You are trying to do so many things in one generic "GunFireManagement" method that it becomes pretty difficult to keep track of all the different pieces :)

I also recommend considering using a tweening framework such as DOTween to make it easier to animate things over time.

Sisus
  • 651
  • 4
  • 8