【问题标题】:Unity - how to show text for few seconds for each good moveUnity - 如何为每个好的动作显示几秒钟的文本
【发布时间】:2018-11-19 01:19:53
【问题描述】:

我是 Unity 和编程的新手,所以我需要一些帮助。在玩家做出好的动作后,我试图显示文本 3 秒。它正在第一步,文本消失但仍在闪烁。可能是因为它处于更新方法并且该项目仍然被锁定......但是我怎样才能改变它以在每次好的移动后显示这个文本 3 秒?每件商品只限一次。谢谢

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameControl : MonoBehaviour
{
[SerializeField]
private GameObject someText
[SerializeField]
private GameObject goodMove;

// Use this for initialization
void Start()
{
    someText.SetActive(false);
    goodMove.SetActive(false);
}
void Update()
{
    if (item1.locked && item2.locked && item3.locked)
    {
        someText.SetActive(true);
    }

    if (item1.locked || item2.locked || item3.locked)
    {
        StartCoroutine(waiter());
    }
}
IEnumerator waiter()
{
    goodMove.SetActive(true);
    yield return new WaitForSeconds(3);
    goodMove.SetActive(false);
}

}

编辑:项目被拖动到正确位置时被锁定

...case TouchPhase.Ended:
            if (Mathf.Abs(transform.position.x - somePlace.position.x) <= 2f &&
            Mathf.Abs(transform.position.y - somePlace.position.y) <= 2f)
                    {
                        transform.position = new Vector2(somePlace.position.x, somePlace.position.y);
                        transform.localScale -= new Vector3(0.4F, 0.4F, 0.4F);
                        locked = true;
                    }
                    else
                    {
                        transform.position = new Vector2(initialPosition.x, initialPosition.y);
                    }
                    break;

【问题讨论】:

  • 我不知道这些变量的用途,但if (item1.locked || item2.locked || item3.locked) 看起来不正确。但是,如果是这样,如果您希望您的文本显示 3 秒,为什么它不是您现有的 3 秒协程的一部分,或者不是其他协程的一部分?
  • @vb381 Draco 是对的,您的代码实际上是在锁定 3 个项目时设置文本,并在锁定一些项目时设置好移动。我还有一个问题:当您锁定一个项目并开始 3 秒的 goodMove 节目时,如果您在第一个项目结束的 3 秒之前激活另一个项目,会发生什么?
  • 我在锁定时添加了我的问题代码。如果我激活另一个项目,什么都不会发生我可以将它拖到正确的位置,但文本只显示一次......

标签: c# unity3d


【解决方案1】:

它在闪烁,因为您每帧都在调用StartCoroutine(waiter());。您可以使用布尔变量使其仅调用一次。如果我是你,我会删除 Update 函数并使用协程来修复它,避免在触摸检测脚本中移动你的代码。

另外,下面的代码每帧都执行:

if (item1.locked && item2.locked && item3.locked)
{
    someText.SetActive(true);
}

最好创建另一个锁定变量,这样您就可以在执行if 语句之前使用它来检查锁定变量何时发生变化。注意下面的ItemChanged() 函数,它就是这么做的。

public class GameControl : MonoBehaviour
{
    //Change YourItemType to whatver your item1, item2, item3 types are
    YourItemType item1, item2, item3;

    [SerializeField]
    private GameObject someText;
    [SerializeField]
    private GameObject goodMove;

    bool oldVal1;
    bool oldVal2;
    bool oldVal3;

    // Use this for initialization
    void Start()
    {
        someText.SetActive(false);
        goodMove.SetActive(false);

        StartCoroutine(LockChecker());
    }

    IEnumerator LockChecker()
    {
        oldVal1 = item1.locked;
        oldVal2 = item2.locked;
        oldVal3 = item3.locked;

        //Run this code forever as the Update function
        while (true)
        {

            //Check if item has changed
            if (ItemChanged())
            {
                if (item1.locked && item2.locked && item3.locked)
                {
                    someText.SetActive(true);
                }

                if (item1.locked || item2.locked || item3.locked)
                {
                    //Call the waiter function then wait for it to return
                    yield return StartCoroutine(waiter());
                }
            }

            yield return null;
        }
    }

    bool ItemChanged()
    {
        //Check if the booelan variable changed
        if (oldVal1 != item1.locked ||
            oldVal2 != item2.locked ||
            oldVal3 != item3.locked)
        {
            //Update old values
            oldVal1 = item1.locked;
            oldVal2 = item2.locked;
            oldVal3 = item3.locked;

            return true;
        }

        return false;
    }

    IEnumerator waiter()
    {
        goodMove.SetActive(true);
        yield return new WaitForSeconds(3);
        goodMove.SetActive(false);
    }
}

更好的是,将您的锁定变量声明为属性,然后使用getset 评估器来检测锁定变量何时更改并启动协程。有一个例子here

【讨论】:

  • 非常感谢您的出色回答。效果很好!也感谢所有其他人的帮助
【解决方案2】:

你是对的,它可能会闪烁,因为一旦一个项目被锁定,它将继续被锁定,并且 Update 方法将继续触发你的协程。相反,我会在项目被锁定的时候调用你的协程(当然,从你的更新中删除检查):

        if (Mathf.Abs(transform.position.x - somePlace.position.x) <= 2f &&
        Mathf.Abs(transform.position.y - somePlace.position.y) <= 2f)
                {
                    transform.position = new Vector2(somePlace.position.x, somePlace.position.y);
                    transform.localScale -= new Vector3(0.4F, 0.4F, 0.4F);
                    locked = true;

                    StartCoroutine(waiter());
                }

【讨论】:

  • 谢谢,但是如何从另一个脚本调用协程服务员? prntscr.com/ljvo5e
  • 和你通常做的一样,除了在 startcoroutine 里面。即。StartCoroutine(myscript.waiter());
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
相关资源
最近更新 更多