最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - IEnumerator Not Taking Input Value - Stack Overflow

programmeradmin0浏览0评论

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;
        }
    }
}

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;
        }
    }
}
Share Improve this question asked Nov 19, 2024 at 14:27 Mike the ScripterMike the Scripter 176 bronze badges 2
  • 2 You have to physically hit the Z button really hard? Unity wouldn't have any idea about how hard you press it. Sounds like an issue with your keyboard. – Verpous Commented Nov 19, 2024 at 14:37
  • General hint: rather stick to your descriptive parameter names .. why would you store them in letter variables which only makes it harder to read? ;) I would then rather instead of writing DealDamage in multiple places, all basically with the same parameters except one, rather store this one parameter according to your cases and then call DealDamage in one single place right before slashSlider.gameObject.SetActive(false) – derHugo Commented Nov 19, 2024 at 15:31
Add a comment  | 

2 Answers 2

Reset to default 1

Input.GetKeyDown will return true only if you press the key during that frame. Because you called it after WaitForSeconds, there is no guarantee that you just press the key at that frame.

Normally, you can call Input.GetKeyDown in the Update event method to record the time the key is pressed, and then compare the difference between the current time and the pressed time in the coroutine. If it is less than a certain threshold, it is considered that the player presses the key during this period.

// Update
void Update()
{
    if (Input.GetKeyDown(KeyCode.Z))
        zPressedTime = Time.time;
}

// DamageSliderTick
if ((Time.time - zPressedTime < threshold) || i == 50)
{
    ...
}

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;
发布评论

评论列表(0)

  1. 暂无评论