I'm making a turn based RPG in Unity and I have a slider that pops up when the player attacks. A runs down the slider and the closer the player gets the slider to the center and presses Z, the more damage it deals. However, for some reason, instead of it being a simple input, you either have to smash Z or it won't take the input at all.
Here's the code:
void DamageGauge(int target, float power, bool special, string status, string name)
{
int t = target;
float p = power;
bool s = special;
string st = status;
string n = name;
meterOpen = true;
slashSlider.gameObject.SetActive(true);
slashSlider.value = 0;
StartCoroutine(DamageSliderTick(t, p, s, st, n));
}
// ReSharper disable Unity.PerformanceAnalysis
public IEnumerator DamageSliderTick(int target, float power, bool special, string status, string name)
{
bool press = false;
int t = target;
float p = power;
bool s = special;
string st = status;
string n = name;
BattleChar sTarget = activeBattlers[t];
for (int i = 0; i < 51; i++)
{
yield return new WaitForSeconds(.01f);
slashSlider.value += 4;
if (Input.GetKeyDown(KeyCode.Z) || i == 50)
{
float v = slashSlider.value;
if(i != 50)
{
switch (v)
{
case < 20:
DealDamage(t, p, .5f, s, st, n);
break;
case < 50:
DealDamage(t, p, .8f, s, st, n);
break;
case < 85:
DealDamage(t, p, 1, s, st, n);
break;
case < 97:
DealDamage(t, p, 1.4f, s, st, n);
break;
case < 132:
DealDamage(t, p, 1, s, st, n);
break;
case < 170:
DealDamage(t, p, .8f, s, st, n);
break;
case < 200:
DealDamage(t, p, .5f, s, st, n);
break;
}
} else
{
DealDamage(t, p, .5f, s, st, n);
}
slashSlider.gameObject.SetActive(false);
slashSlider.value = 0;
if (activeBattlers[t].currentHP <= 0)
{
RewardDialog.instance.xpPool += sTarget.xpWorth;
RewardDialog.instance.moneyPool += sTarget.dollarWorth;
if (sTarget.itemDrop[0] != null)
{
RewardDialog.instance.ShuffleItems(sTarget.itemDrop);
}
}
UpdateStatus(t);
NextTurn();
break;
}
}
}
You could also wait directly in the Coroutine, just instead of using WaitForSeconds
have a more manual wait loop like e.g.
for(var time = 0f; time < 0.01f; time += Time.deltaTime)
{
if(Input.GetKeyDown(KeyCode.Z))
{
break;
}
yield return null;
}
This allows to track input every frame without missing one and directly interrupts the wait and continues with the rest when Z is pressed.
Despite that, a waiting of 0.01
seconds barely makes sense. For 60
FPS one frame takes about 1/60 = 0.017
seconds. So you could as well just use a
yield return null;
so it waits exactly one frame. Then instead of increasing the slider by a hard value per frame you could go by per second and do
slashSlider.value += 4 * Time.deltaTime;