C# 防止通过脚本编辑变量的统一性

C# 防止通过脚本编辑变量的统一性,c#,unity3d,scripting,global-variables,tooltip,C#,Unity3d,Scripting,Global Variables,Tooltip,当我将鼠标悬停在按钮上时,我试图弹出一个工具提示。我从一个单独的线程调用主线程时遇到了一些问题,因为主线程是唯一可以编辑游戏对象的线程。所以我决定使用一个布尔值和一个更新函数来获得所需的结果。然而,我遇到了一个我从未见过的问题。我正在将布尔showToolTip设置为true,这将触发create弹出函数。但是,在运行“我的更新”函数时,showTooltip始终为false。我知道当我将其设置为true时,它会变为true,因为我在requestShowTooltip函数中使用了调试语句来查看

当我将鼠标悬停在按钮上时,我试图弹出一个工具提示。我从一个单独的线程调用主线程时遇到了一些问题,因为主线程是唯一可以编辑游戏对象的线程。所以我决定使用一个布尔值和一个更新函数来获得所需的结果。然而,我遇到了一个我从未见过的问题。我正在将布尔showToolTip设置为true,这将触发create弹出函数。但是,在运行“我的更新”函数时,showTooltip始终为false。我知道当我将其设置为true时,它会变为true,因为我在requestShowTooltip函数中使用了调试语句来查看这一点。但是,当update函数运行时,它总是false。我做了一些测试,将showToolTip和removeToolTip更改为公共布尔值。我可以在运行应用程序时在编辑器中更改它们,当我通过编辑器手动更改它们时,它们将100%按预期工作,并且工具提示将在我更改相关布尔值时显示和隐藏。但是,当它们从脚本中更改时,将保留为false。我也尝试过让它们单元化,并在一开始将它们初始化为false,但我仍然有同样的问题。我甚至尝试过使用showTooltip=true;脱离线程,让函数立即执行,我仍然有同样的问题。调用更新函数时,showTooltip始终为false。我通过在update函数中添加一条debug语句来确定这一点,该语句报告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;
     }

}

因为基本上Unity中的所有内容都需要在主线程中调用,只有很少的例外情况,所以我建议使用一个函数来更改代码,并让主线程处理来自任何线程的所有响应

// 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();
    }
}

您可能想考虑BTW来键入Button对象类型Button对象,以确保传递的对象始终具有A/A按钮,而第二个则可以去掉高性能的GETEngult调用。p> 同样的方式,我宁愿储存

RectTransform toolTipBackgroundRectTransform;
Text toolTipText;
RectTransform toolTipTextrectTransform;

因为这些组件在开始时就可以获得一次,然后您可以始终重复使用相同的引用,并摆脱所有进一步的GetComponent调用。

如果要从另一个线程修改字段,您肯定需要标记该字段。我怀疑Unity不会支持这一点。我将它们改为volatile,但仍然得到了相同的结果。我还做了测试,从线程中取出布尔值,并在unity主线程中对其进行了更改,同时仍将其保留在requestShowTooltip函数中,但仍然存在相同的问题。使用单独的线程有什么特殊原因吗?延迟工具提示的出现似乎同样可以由协同程序轻松处理,而不必担心线程管理问题,这是一个长期问题,请尝试在布尔字段之前添加[System.Nonserialized],即:[System.Nonserialized]private bool showTooltip=false;[System.Nonserialized]private bool removeTooltip=false;一开始,线程似乎更快,但我将尝试协同程序。我会在周一跟进,因为在那之前我不会回去工作。然而,我仍然很好奇为什么这个变量一直在变化。我担心我会再次遇到这个问题。我知道这不是线索,我相信这与团结有关。谢谢你的回复。周一上班时我会试试这个。好吧,原来我的Unity仍然使用.Net 3.5,这阻止了我使用System.Collections.Concurrent,但当我切换到.Net 4.0时,我游戏对象中的所有链接都被删除了。所以我需要手动恢复这些,然后才能测试这个更改。好的,这是可行的。谢谢很好,你帮我发现我使用了错误的.Net版本。
RectTransform toolTipBackgroundRectTransform;
Text toolTipText;
RectTransform toolTipTextrectTransform;