嗨大家好我有这个2D小家伙有2个状态" IsSpeaking"和#34;沉默"我使用它们来使Animator设置为真或假的bool,而角色似乎在说话。
我需要IsSpeaking持续不同的时间,具体取决于屏幕上显示的文字数量,如下所示:
Text dialogueNumber(X) appears
Animate Speaking
Wait "X" time...
Animate Idle
Wait in Idle for next text (dialogueNumber) to appear and restart cycle...
我试着用这个小代码做到这一点:
void Update () {
StartCoroutine(IsSpeaking());
}
IEnumerator IsSpeaking()
{
switch (dialogueNumber)
{
case 0:
yield return null;
break;
case 1:
functionsScript.IsSpeaking();
yield return new WaitForSeconds(3);
functionsScript.Silence();
yield break;
case 2:
functionsScript.IsSpeaking();
yield return new WaitForSeconds(6);
functionsScript.Silence();
yield break;
}
yield break;
因此,文本越长,等待时间切换到静音动画的时间越长,但第一次(情况1)似乎正常工作,并且在进入静音之后,它会继续从IsSpeaking到Silence随机来回,我不确定这是否是实现这一目标的最佳方式,或者是否有更好的方式在状态之间切换并等待一段时间?
非常感谢您的建议...
答案 0 :(得分:5)
您正在IsSpeaking
函数中的每一帧调用Update
,这意味着即使另一个因WaitForSeconds
而尚未完成,它也会一遍又一遍地启动。您当前的代码可以在主题时间内生成超过400个协程,并且还会尝试"说"和#34;沉默"同时。
您可以使用简单的布尔变量来解决该问题。
bool speaking = false;
void Update()
{
//Run only if not running
if (!speaking)
StartCoroutine(IsSpeaking());
}
然后在断开协程中的switch语句之前将布尔变量设置为false
。
IEnumerator IsSpeaking()
{
speaking = true;
switch (dialogueNumber)
{
case 0:
yield return null;
speaking = false;
break;
case 1:
functionsScript.IsSpeaking();
yield return new WaitForSeconds(3);
functionsScript.Silence();
speaking = false;
yield break;
case 2:
functionsScript.IsSpeaking();
yield return new WaitForSeconds(6);
functionsScript.Silence();
speaking = false;
yield break;
}
yield break;
}
答案 1 :(得分:1)
让玩家决定下一个对话何时出现会不会更好? 不是每个人都读取相同的速度。
沿线的某些事情(希望这不是在错误的轨道上):
while(!ExitDialogue)
{
animation.Play("Idle");
yield return StartCoroutine(IdleUntilNext()); //waits for player to press the defined button _keyCode_
diaNumber++;
animation.Stop("Idle");
animation.Play("Speak");
StartCoroutine(SpeakDialogue(diaNumber)); //wait for X seconds depending on diaNumber before stopping the animation
animation.Stop("Speak");
}
IEnumerator SpeakDialogue(int diaNumber)
{
switch (diaNumber)
{
case 1:
yield return new WaitForSeconds(3);
yield break;
case 2:
yield return new WaitForSeconds(6);
yield break;
default:
ExitDialogue = true;
yield break;
}
}
IEnumerator IdleUntilNext()
{
while(!Input.GetKeyDown(_keyCode_))
{
yield return null;
}
}
答案 2 :(得分:0)
确实我的问题有一个糟糕的方法,更容易在更新功能之外做这个,结果更容易在同一个“下一步”按钮中设置数字作为On Click()内部调用的函数导致某事像这样:
public void TextID()
{
textID= (int)VD.nodeData.extraVars["cuadro"];
print(textID);
switch (textID)
{
case 0:
break;
case 1:
StartCoroutine(LipsMoving(3));
break;
case 2:
StartCoroutine(LipsMoving(6));
break;
}
}
IEnumerator LipsMoving(int talkTime)
{
funcionesScript.Speaking();
yield return new WaitForSeconds(talkTime);
funcionesScript.Idle();
yield return null;
}
通过这种方式,我可以在用户单击按钮时获取帧ID,并且还可以在没有奇怪循环的情况下运行我的协同程序。 再次感谢您的帮助和耐心,让您有不同的观点来寻找合适的方式令人耳目一新,希望这对您们有用