【问题标题】:Showing a Text layer for a short amount of time在短时间内显示文本图层
【发布时间】:2023-04-03 09:58:01
【问题描述】:

我有一个玩家和一个敌人。当我右键单击敌人时,他的HP下降并且命中计数器上升。我想让它就像当你击中敌人时文本标签变得可见,当你停止攻击时它保持可见几秒钟,然后隐藏并将命中计数器设置回 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,协程也不会重置回起点。

【问题讨论】:

  • 对此类计时器使用 Invoke

标签: c# user-interface unity3d


【解决方案1】:

让我们分析您的代码:

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

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

我会将 showhitcounter 更改为以下:

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

} 我让 clearLabel 有单独的方法来清除标签。您的逻辑必须位于不同的位置并调用此方法。

一个地方会发生 onmouseleave 事件。 其他地方将在您的鼠标悬停并添加一个属性

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

【讨论】:

  • if (Input.GetMouseButtonDown(1)) 中设置TimeLeft = DateTime.Now 并在IEnumerator ShowHitCounter(string message) 中添加yield return null 使一切正常,非常感谢!
【解决方案2】:

刚刚完成我的解决方案并意识到已经有了答案。不能丢弃。只是把它作为一个no内存分配的解决方案。

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

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

    }
}

【讨论】:

    【解决方案3】:

    哦,好吧,这是另一个概念,只是为了它:)
    没有测试它,所以要小心处理,但问题是,启动协程等看起来太多了(而且也是贵)对我来说,只要你想要的东西。

    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

    【讨论】:

      猜你喜欢
      • 2022-11-15
      • 2015-07-04
      • 1970-01-01
      • 2014-11-20
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      相关资源
      最近更新 更多