SOLVED: While loop not accessed with GetAxis()

I am making a laser beam attack, which is currently accessed by using (Input.GetMouseDown(KeyCode.F)), and I want to change it to use GetAxis(“Fire1”).

For some reason, a while loop does not run when using GetAxis instead of GetKey and I would be grateful if anyone could give an explanation as to why this is happening.

In my code, the lines 20, 30 and 52, are where I am tryng to access the firing coroutine.
Is there something unique about GetAxis that means it cannot be directly swapped with GetKey? I am using Unity 5.6.

Thanks for any help provided.

Script

    void Update()
    {
        if(reloading)
        {
            reloadTimer += Time.deltaTime;

            if(reloadTimer > reloadTimerMax)
            {
                reloadTimer = 0f;
                shootTimer = 0f;
                reloading = false;
                shootSlider.value = 0;

                spriteFill.color = Color.white;
            }
        }

        //Make this work with the MouseDown/Fire1 Axis!!
        if(Input.GetKeyDown(KeyCode.F))
//        if(Input.GetAxis("Fire1") != 0)
        {
            if(!reloading)
            {
                StopCoroutine(ShootForward());
                StartCoroutine(ShootForward());
            }
        }

        if(!Input.GetKey(KeyCode.F))
//        if(Input.GetAxis("Fire1) == 0)  
        {
            if(!reloading)
            {
                if(shootTimer > 0)
                {
                    shootTimer -= (Time.deltaTime / 3);
                }
                else
                {
                    shootTimer = 0;
                }
                shootSlider.value = shootTimer;
            }
        }
    }

    IEnumerator ShootForward()
    {
        lr.enabled = true;

        while(Input.GetKey(KeyCode.F) && shootTimer < shootTimerMax)
//        if(Input.GetAxis("Fire1) != 0)
        {
            shootTimer += Time.deltaTime;

            Ray ray = new Ray(firePosition.position, transform.forward);
            RaycastHit hit;

            lr.SetPosition(0, ray.origin);

            if(Physics.Raycast(ray, out hit, 100))
            {
                lr.SetPosition(1, hit.point);

                Vector3 hitPosition = lr.GetPosition(1);

                hitParticle.transform.position = hitPosition;
                hitParticle.SetActive(true);
            }
            else
            {
                lr.SetPosition(1, ray.GetPoint(100));
                hitParticle.SetActive(false);
            }

            shootSlider.value = shootTimer;

            yield return null;
        }

        if(shootTimer >= shootTimerMax)
        {
            reloading = true;
            spriteFill.color = Color.red;

            yield return null;
        }

        lr.enabled = false;
        hitParticle.SetActive(false);
    }

You’re executing the logic inside of the if statement every frame when using GetAxis.

Let’s assume that the user pushes the Fire1/F key and holds it down for 1 frame. That means Update() will be called 60 times while the user is holding the key down.

Input.GetKeyDown(…) will return true for 1 frame when the user first pushes the key down. After that first frame, it will return false.

Input.GetAxis(…) != 0 will return true every frame that the user is holding the key down. So it will return true each of the 60 frames in our example.

When using GetKeyDown, the logic inside of the if block will work as you expect it to. During the first frame where the user pushes the button, ShootForward coroutine will be stopped once, then re-started. During the subsequent frames where the user is holding the button, the if block won’t be run because GetKeyDown returns false.

When using GetAxis, the logic inside of the if block is being run every frame that the user holds the fire button down. So you’re restarting the coroutine (or starting a whole new one) every frame.

1 Like

Did you try
if (Input.GetButton(“Fire1”)
{
Debug.Log(“Fire1 Pressed”);
}

1 Like

EDIT: Thank you @johne5 , your suggestion has solved the problem.

Thank you @kru , that also makes sense.

Old Post

To ensure the Update is only called once per frame, I have added a bool which is set and checked to happen once per frame. (see Unity Answers link)

This has solved the issue, that it Updates too often. However, my While Loop happens more often, than the Update. This is shown through the regularity of specific Debug Logs. Can you suggest a way, to reduce the calls in the While Loop without returning a null statement?

Thank you for the assistance so far.

It looks as though your while loop can only be called once per frame, if it’s true…

I was partially confused by your last post, as Update() only runs once per frame, anytime…

1 Like