unity3d 如何让for循环只在玩家每次按Z键时循环

whhtz7ly  于 2022-12-19  发布在  其他
关注(0)|答案(2)|浏览(138)

我正在尝试循环通过一个对话列表来更新一个文本组件。
var i应该只在玩家按下z时增加,但每次我尝试时,var i都会增加到最大值,而不是每次我按下Z时增加一次。

IEnumerator gameDialog ( )
{
    while ( i < prologueDialog.Count )
    {
        PlayerPrefs.SetInt ( "StoryProgress(Prologue)", i );
        currentListIndex = PlayerPrefs.GetInt ( "StoryProgress(Prologue)" );

        if ( i == 0 )
        {
            dialogText.text = prologueDialog [ 0 ];
        }

        if ( Input.GetKey ( KeyCode.Z ) )
        {
            pressedZ = true;
            dialogText.text = "";
            dialogText.text = prologueDialog [ i ];
        }

        yield return new WaitUntil ( ( ) => pressedZ );
        pressedZ = false;
        oldi = i;
        i++;
        if ( oldi + 1 != i )
        {
            i = oldi + 1;
        }
        Debug.Log ( i );
    }
}

我已经尝试了所有能想到的方法,使用yieldWaitUntilWaitForSecondsbool值来阻止if语句多次运行。

sgtfey8w

sgtfey8w1#

Input.GetKey将在按键被按住时返回true。您所追求的可能是Input.GetKeyDown,它在最初按下的帧期间返回true,并且在释放相同按键之前不会返回true。

vhmi4jdf

vhmi4jdf2#

WaitUntilIEnumerator导致代码执行暂停在该位置,直到函数 predicate 返回true。用外行的话来说,这意味着代码将停止在该行上,不再移动,直到pressedZ以某种方式变为true。但是,假定代码不会继续执行,您可以开始看到这些键再也不会被读取,因此,pressedZ永远不会成为真。
需要注意的一点是,将任何游戏状态保存到PlayerPrefs几乎是普遍不赞成的。但这是另一个问题,可以在运行对话后解决。
与其尝试在“协同程序”中轮询键盘输入,我是否可以建议您使用已经可用的Update方法作为基于帧的轮询机制?它还包括PlayerPrefs持久性,我建议您尽早将其替换。这已经编写,但没有测试。

public class Test : MonoBehaviour
{
    [SerializeField] private TextMeshPro dialogText;

    private List<string> _dialoguePhrases = null;
    private string _storyName;
    private int _dialogueIndex = 0;

    private void Awake ( )
    {
        HideDialogue ( );
    }

    public void ShowDialogue ( List<string> dialoguePhrases, string storyName = "StoryProgress(Prologue)" )
    {
        _dialogueIndex = PlayerPrefs.GetInt ( storyName, 0 );

        // check the saved progress index with the newly passed in dialoguePhrases (or -1 if null).
        if ( _dialogueIndex >= ( dialoguePhrases?.Count ?? -1 ) )
        {
            HideDialogue ( );
            return;
        }

        _dialoguePhrases = dialoguePhrases;
        _storyName = storyName;
        dialogText.text = dialoguePhrases [ _dialogueIndex ];
        enabled = true; // Lets the Update method run.
    }

    public void HideDialogue ( )
    {
        _dialoguePhrases = null;
        _dialogueIndex = 0;
        dialogText.text = string.Empty;
        enabled = false; // Stops the Update method from being called.
    }

    private void Update ( )
    {
        if ( Input.GetKeyDown ( KeyCode.Z ) && _dialoguePhrases != null )
        {
            if ( ++_dialogueIndex < _dialoguePhrases.Count )
            {
                dialogText.text = _dialoguePhrases [ _dialogueIndex ];
                PlayerPrefs.SetInt ( "StoryProgress(Prologue)", _dialogueIndex );
            }
            else
            {
                // You've clicked on the last one, and now you need to do something after the dialogue has finished.
                HideDialogue ( );
            }
        }
    }
}

这里的想法是,您发送一个对话短语列表,以及对话状态将被持久化的位置的名称(id)(最好不在PlayerPrefs中)。
然后,当组件自身的enable标志设置为true时,Update方法被启用。在Update中进行正常检查,当到达对话的结尾时,组件关闭自身,等待下一个show dialogue命令。

相关问题