Properly checking the value of a constantly changing variable

Hi everyone!

I’m making a flight game (Ace Combat clone) and seem to have run into a wall.

I’m trying to make it so that the screen shakes every time the player’s throttle reaches 25%, 50%, 75%, and 100%.

I’ve already got a perfectly working screen shake – here’s the relevant bits:

if (shakeTimer < shakeTimeLimit)
		{
			shakeX = Random.Range(-shakeAmount, shakeAmount);
			shakeY = Random.Range(-shakeAmount, shakeAmount);
			shakeTimer += Time.deltaTime;
		}

//set camera rotation
		Quaternion targetRot;
		targetRot = targetTransform.rotation;

		transform.rotation = Quaternion.Lerp(transform.rotation, targetRot, rotCamSpeed * Time.deltaTime) * Quaternion.Euler(finalSwayX, finalSwayY, 0) * Quaternion.Euler(shakeX, shakeY, 0);

My problem now is checking when the player’s throttle has reached these key thresholds. I’ve tried stuff like:

if (throttle == maxThrottle/4)
{
    //do stuff
}

But it’s not reliable. The throttle values are floats and I’m using gamepad analog triggers to change their values, so often times throttle never equals maxThrottle/4.

What is the proper way to check the throttle/maxThrottle, and then get some kind of true/false state I can use to trigger my camera shake?

Thanks!

You could check if the step changed (up or down) with something like this:

private int oldThrottleStep;

void Update() { // or some other method probably
     int step = (int)Mathf.Floor(throttle / (maxThrottle/4)); // I think floor is even unnecessary
     if (step > oldThrottleStep) {
          // increased one step: shake it! 
     } else if (step < oldThrottleStep) {
          // decreased one step: probably play some sound
     }
     oldThrottleStep = step;
}

Ok I found the answer to my problem.

First thing I did was setup a coroutine in Start():

boostShaker = BoostShaker();
StartCoroutine(boostShaker);
boostShakerRunning = true;

I turn on this Coroutine when the jet is accelerating, and turn it off when it is decelerating.

if (playerController.oldThrottle > playerController.throttle)
{
	if (boostShakerRunning == true)
	{
		StopCoroutine(boostShaker);
		boostShaker = null;
		boostShakerRunning = false;
	}
}
else if (playerController.oldThrottle < playerController.throttle)
{
	if (boostShakerRunning == false)
	{
		boostShaker = BoostShaker();
		StartCoroutine(boostShaker);
		boostShakerRunning = true;
	}
}

Here is the screen shake code:

if (shakeDone == false)
{
	if (shakeTimer < shakeTimeLimit)
	{
		shakeX = Random.Range(-shakeAmount, shakeAmount);
		shakeY = Random.Range(-shakeAmount, shakeAmount);
		shakeTimer += Time.deltaTime;
	}
	else
	{
		shakeDone = true;
	}
}		

Now for the coroutine itself:

IEnumerator BoostShaker()
{
	Debug.Log("starting BoostShaker");

	yield return new WaitUntil( ()=> playerController.throttle >= playerController.maxThrottle/4f );

	BoostShakeReset();
	Debug.Log("step 1");

	yield return new WaitUntil( ()=> playerController.throttle >= playerController.maxThrottle/2f );

	BoostShakeReset();
	Debug.Log("step 2");

	yield return new WaitUntil( ()=> playerController.throttle >= playerController.maxThrottle * .75f );

	BoostShakeReset();
	Debug.Log("step 3");

	yield return new WaitUntil( ()=> playerController.throttle >= playerController.maxThrottle );
	
	BoostShakeReset();
	Debug.Log("step 4");
}

void BoostShakeReset()
{
	shakeDone = false;
	shakeTimer = 0;
}

Is it a dirty hack? I don’t know. I’ve only known Unity and C# for like a month. :smiley: It works though!