在短时间内显示文本图层

时间:2016-05-25 11:13:39

标签: c# user-interface unity3d

我有一名球员和一名敌人。当我右键击中敌人时,他的HP下降并且一个接收器上升。我想让它像你击中敌人一样,文字标签变得可见,当你停止攻击时,它会保持可见几秒钟,然后隐藏并将hitcounter设置回0。

这就是我现在所拥有的。

public Text GUIHit;
public int HitCounter = 0;

void OnMouseOver()
{
    if (Input.GetMouseButtonDown(1))
    {
        HitCounter++;
        StartCoroutine(ShowHitCounter(HitCounter.ToString(), 2));
    }
}

IEnumerator ShowHitCounter(string message, float delay)
{
    GUIHit.text = message;
    GUIHit.enabled = true;
    yield return new WaitForSeconds(delay);
    HitCounter = 0;
    GUIHit.enabled = false;
}

它会发生2秒的工作,但即使我仍然在攻击它时看不见它并且命中计数器回到0,协程也不会重置回起点。

3 个答案:

答案 0 :(得分:2)

让我们分析您的代码:

void OnMouseOver()
{
    if (Input.GetMouseButtonDown(1)) //you get passed that if when you hit first time
    {
        HitCounter++;
        StartCoroutine(ShowHitCounter(HitCounter.ToString(), 2)); //you call your label with delay of 2 sec
    }
}

IEnumerator ShowHitCounter(string message, float delay)
{
    GUIHit.text = message;
    GUIHit.enabled = true;
    yield return new WaitForSeconds(delay); // still on your first hit you get to here and wait 2 seconds
    HitCounter = 0; //after 2 seconds you reset hitcounter and disable label
    GUIHit.enabled = false;
}

要修复它,您需要知道何时停止按击,然后重置hitcounter并禁用标签。

我会将showhitcounter更改为以下内容:

IEnumerator ShowHitCounter(string message)
{
    GUIHit.text = message;
    GUIHit.enabled = true;
}
void ClearLabel()
{
    HitCounter = 0; 
    GUIHit.enabled = false;
}

} 我使用clearLabel来清除标签的单独方法。你的逻辑必须在不同的地方并调用这种方法。

有一个地方会举办活动。 其他地方将在你的onmouseover并添加一个属性

public static DateTime TimeLeft { get; set; }

void OnMouseOver()
{
    TimeSpan span = DateTime.Now - TimeLeft;
    int ms = (int)span.TotalMilliseconds;
    if (ms > 2000)
    {
        ClearLabel();
    }
    if (Input.GetMouseButtonDown(1)) 
    {
        HitCounter++;
        StartCoroutine(ShowHitCounter(HitCounter.ToString(), 2)); 
    }
}

此外,您需要在

之前的某处初始化TimeLeft

答案 1 :(得分:1)

刚刚完成我的解决方案并意识到已经有了答案。不能丢弃它。只需将其作为内存分配的解决方案。

每次点击鼠标时都需要启动Coroutine,就像您在问题中的代码中所做的那样。我这样说是因为在每次鼠标点击后调用StartCoroutine()时会有不断的内存分配。下面代码中的定时器基于帧速率,但可以使用DateTime.Now轻松更改为实时。您也可以将代码放在Coroutine中的while循环中,然后从Start函数中将其命名为一次

public Text GUIHit;
public int HitCounter = 0;
bool firstRun = true;

float waitTimeBeforeDisabling = 2f;
float timer = 0;

void Update()
{
    //Check when Button is Pressed
    if (Input.GetMouseButtonDown(1))
    {
        //Reset Timer each time  there is a right click
        timer = 0;

        if (!firstRun)
        {
            firstRun = true;
            GUIHit.enabled = true;
        }

        HitCounter++;
        GUIHit.text = HitCounter.ToString();
    }

    //Button is not pressed
    else
    {
        //Increement timer if Button is not pressed and timer < waitTimeBeforeDisabling
        if (timer < waitTimeBeforeDisabling)
        {
            timer += Time.deltaTime;
        }

        //Timer has reached value to Disable Text
        else
        {
            if (firstRun)
            {
                firstRun = false;
                GUIHit.text = HitCounter.ToString();
                HitCounter = 0;
                GUIHit.enabled = false;
            }
        }

    }
}

答案 2 :(得分:0)

Awh,好吧,这是另一个概念,只是为了它:)左边没有测试它,所以这样小心处理,但问题是,开始一个协程等看起来太多了(和太贵了)对于我来说,只要你想要的东西。

private float holdOutTime = 2.0f;
private float lastHitTime = 0.0f;

void OnMouseOver() {
    if (Input.GetMouseButtonDown(1)) { IncHitAndShowUI() } //compacted
}

private void Update() {
    if (GUIHit.enabled) { TestAndDisableHitUI(); } //compacted
}

#region priv/helper methods
//would force it inline if it was possible in Unity :)
private void IncHitAndShowUI() {
    HitCounter++;
    lastHitTime = Time.time;
    GUIHit.text = HitCounter.ToString();
    GUIHit.enabled = true;
}
//same here :)
private void TestAndDisableHitUI() {
    if (lastHitTime + holdOutTime >= Time.time) {
       GUIHit.enabled = false;
    }
}
#endregion