Unity阻止通过脚本编辑变量

时间:2019-07-11 21:50:39

标签: c# unity3d scripting global-variables tooltip

当我将鼠标悬停在按钮上时,我试图弹出一个工具提示。我在从单独的线程调用主线程时遇到了一些问题,因为主线程是唯一可以编辑游戏对象的线程。因此,我决定使用布尔值和更新函数来获得所需的结果。但是,我遇到了一个从未见过的问题。我将boolean showToolTip设置为true,这应该会触发创建弹出功能。但是,在我的更新功能运行时,showTooltip始终为false。我知道将其设置为true时,它就会变为true,因为我在requestShowTooltip函数中使用了调试语句来查看此信息。但是,在运行更新功能时,它始终为false。我通过将showToolTip和removeToolTip更改为公共布尔值进行了一些测试。我可以在运行应用程序时在编辑器中对其进行更改,当我通过编辑器手动对其进行更改时,它们将按预期的方式工作100%,并且当我更改相关的布尔值时,工具提示将显示和隐藏。但是,当从脚本中更改它们时,它们将保留为false。我还尝试过将它们统一化,并在一开始将它们初始化为false,但我仍然遇到同样的问题。我什至尝试使用“ showTooltip = true;”在线程之外,只是让函数立即执行,而我仍然遇到相同的问题。调用更新函数时,showTooltip始终为false。我通过在update函数中添加调试语句来确定这一点,该语句报告showTootip和removeTooltip布尔值。此外,无论如何,“调用创建工具提示”都不会出现在控制台中。除了我公开布尔值并通过编辑器对其进行更改的时间。

有关我如何进行设置的一些进一步说明。我制作了一个工具提示游戏对象,该对象是画布的子代,其中包含我想要工具提示的按钮。我在工具提示对象中添加了工具提示脚本。我在游戏对象按钮中创建了事件触发器。指针进入触发器调用requestShowTooltip()函数,指针退出触发器调用requestHideTooltip()函数。

工具提示背景和工具提示文本游戏对象也是同一画布的子代。

public class Tooltips : MonoBehaviour
{
     private GameObject toolTipBackground;
     private GameObject toolTipText;
     private GameObject inButtonObject;

     private bool showTooltip = false;
     private bool removeTooltip = false;

     void Start()
     {
          toolTipBackground = GameObject.Find("Tooltip background");
          toolTipText = GameObject.Find("Tooltip Text");
          //inButton = GameObject.Find("Aft Button");

          toolTipBackground.SetActive(false);
          toolTipText.SetActive(false);

          //Debug.Log("Tool Tip Start");
     }

     void Update()
     {
          // show the tooltip when the appropriate boolean has been set 
          // to true
          if(removeTooltip)
          {
               hideTooltip();
          }
          // this if statement is always false, because showTooltip is 
          // always false when the update function is called??
          if(showTooltip)
          {

               Debug.Log("Calling create tooltip");
               createTooltip();
          }
     }

     // A timed request for a tooltip to show.  The tooltip should 
     // currently show one second after the request has been made.  The 
     // text of the tooltip will be equal to the passed object's name
     public void requestShowTooltip(GameObject inButtonObject)
     {
          Thread thread = new Thread(delegate ()
          { 
               System.Threading.Thread.Sleep(1000);
               this.inButtonObject = inButtonObject;

               // I know this runs, but showTooltip is always returning 
               // to false when the update function is called??
               showTooltip = true;

               removeTooltip = false;
               Debug.Log("Request function completed");
          });

          thread.start();
     }

     public void createTooltip()
     {
          toolTipText.SetActive(true);
          toolTipBackground.SetActive(true);

          string labelString = inButtonObject.name;

          Button inButton = inButtonObject.GetComponent<Button>();

          int width = labelString.Length * 10;
          int height = 35;

          Vector2 size = new Vector2(width, height);
          Vector3 position = new Vector3(inButton.transform.x, 
                                     inButton.transform.position.y,
                                     inButton.transform.position.z + 1);

          toolTipBackground.GetComponent<RectTransform>().
          sizeDelta = size;

          toolTipText.GetComponent<RectTransform>().sizeDelta = size;

          toolTipBackground.transform.position = position;
          toolTipText.transform.position = position;

          toolTipText.GetComponent<Text>().text = labelString;

          showTooltip = false;
     }

     public void requestHideTooltip()
     {
          removeTooltip = true;
          showTooltip = false;
     }

     public void hideTooltip()
     {
          Vector2 hide = new Vector2(0, 0);
          toolTipBackground.GetComponent<RectTransform>().
          sizeDelta = hide;
          toolTipText.GetComponent<RectTransform>().sizeDelta = hide;

          toolTipText.setActive(false);
          toolTopBackground.SetActive(false);

          removeTooltip = false;
          showTooltip = false;
     }

}

1 个答案:

答案 0 :(得分:0)

因为基本上所有Unity中的所有内容都需要在主线程中调用(很少有例外),所以我建议使用ConcurrentQueue<Action>TryDequeue来更改代码,以使主线程在所有线程中正常工作来自任何线程的响应。

// a queue for storing actions that shall be handled by the main thread
// a ConcurrentQueue in specific is thread-save
private ConcurrentQueue<Action> actions = new ConcurrentQueue<Action>();

private void Update()
{
    // invoke all actions from the threads in the main thread
    while(!actions.IsEmpty)
    {
        // TryDequeue writes the first entry to currentAction
        // and at the same time removes it from the queue
        // if it was successfull invoke the action otherwise do nothing
        if(actions.TryDequeue(out var currentAction))
        {
            currentAction?.Invoke();
        } 
    }

    if(removeTooltip)
    {
         hideTooltip();
    }

    if(showTooltip)
    {
         Debug.Log("Calling create tooltip");
         createTooltip();
    }
}

然后在您的Thread中,而不是让线程直接执行事务本身,而是使用actions队列将其传递回主线程,并使用末尾添加一个新的Action Enqueue

public void requestShowTooltip(GameObject inButtonObject)
{
     Thread thread = new Thread(delegate()
     { 
          System.Threading.Thread.Sleep(1000);

          // add an Action to the end of the queue
          // e.g. as lambda-expression
          actions.Enqueue(()=>
          {
              this.inButtonObject = inButtonObject;

              // I know this runs, but showTooltip is always returning 
              // to false when the update function is called??
              showTooltip = true;

              removeTooltip = false;
              Debug.Log("Request function completed");
          });
     });

     thread.start();
}

您可能要考虑使btw的类型为inButtonObject的{​​{1}}-首先要确保传递的对象始终具有a /是Button,然后可以摆脱激烈的Button通话中。

我想存储的方式相同

GetComponent

由于这些都是组成部分,因此您可以在RectTransform toolTipBackgroundRectTransform; Text toolTipText; RectTransform toolTipTextrectTransform; 一次,然后可以重复使用始终相同的引用并摆脱所有进一步的Start调用。