【问题标题】:Inter-functional timing error (C#, Unity)功能间计时错误(C#、Unity)
【发布时间】:2021-08-02 07:15:37
【问题描述】:

我有 2 个依赖于鼠标点击事件的脚本(RunControl.cs 和 FireControl.cs)。

RunControl.cs :由屏幕顶部的按钮触发。点击后,游戏停止。

FireControl.cs:允许角色在鼠标点击时触发。

问题:由于我想停止游戏时必须点击,所以首先角色射击,然后游戏停止。我尝试了以下代码进行阻止,但我无法阻止它。

//RunControll.cs
private void Start()
    {
        isRun = true;
    }
    public void OnButtonClick()
    {
        if(btn.image.sprite == runSprite)
        {
            btn.image.sprite = stopSprite;
            FindObjectOfType<FireControl>().isRun = false;
            isRun = false;
            
        }
        else
        {
            btn.image.sprite = runSprite;
            FindObjectOfType<FireControl>().isRun = true;
            isRun = true;
            
        }
    }
//FireControl.cs
private void Start()
    {
        isRun = true; //Controlled by RunControl.cs
    }

    private void Update()
    {
        if (isRun)
        {
            if (Input.GetKeyDown(KeyCode.Mouse0))
            {
                fire = true;
            }
            else
            {
                fire = false;
            }
        }
    }

!!! 将 FireControl.cs 更改为 lateupdate 不起作用

【问题讨论】:

  • 你有没有在PlayerSettings 中尝试过Script Execution Order 看看是否有效?
  • 我不知道我们可以选择以这种方式进行编辑。在您发表评论后,我做了一些研究,这似乎是一种可行的方法。
  • 让我随时通知您这些改进,如果您能根据具体情况将您的评论变成新的答案,我将不胜感激。
  • I added it like this 但它没有用。我在unity document-> 中找到了一个注释:这个设置窗口中指定的执行顺序不会影响用RuntimeInitializeOnLoadMethod属性标记的函数的顺序。 (您不能指定运行时初始化的顺序。)
  • 所以最好改变你的设计以在一个地方处理所有的触摸事件。

标签: c# unity3d


【解决方案1】:

您正在创建一个“竞争条件” - 这将首先发生,禁用游戏或触发。一个跟踪状态并由 OnClick 更新并由 FireControl 读取的单例 GameManager 类将有助于清理您的代码,但它不会修复竞争条件。

我会查看this answer 的问题“如何检测鼠标左键,但在 UI Button 组件上发生单击时不检测?”

根据该答案,您可以将 FireControl 更新为在单击按钮时不触发,这将一起避免竞争条件


    if (isRun)
    {
        if (Input.GetKeyDown(KeyCode.Mouse0) && !EventSystem.current.IsPointerOverGameObject())
        {
            fire = true;
        }
        else
        {
            fire = false;
        }
    }

选项 2 - 使用 RayCast

标记您的按钮,使其可识别,我们将其称为“按钮”。然后执行 RayCast 并检查指针是否在按钮上,如果是,请不要触发

var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var overButton = false;

if (Physics.Raycast(ray, out var hit)
{
    overButton = hit.collider.tag == "button";
}
else 
{
    overButton = false;
}

// Continue with your fire logic
if (Input.GetKeyDown(KeyCode.Mouse0) && !overButton)
{
    // Fire
}

上面有点乱,可以优化,但应该工作

【讨论】:

  • 我还没有测试过,所以如果它不起作用,你最好的选择是,正如@AminSojoudi 所暗示的那样,在触发的同时处理按钮点击,而不是通过OnClick 处理程序。这可以通过光线投射来完成,并且有许多教程。如果上述方法不起作用,我可以为您指明正确的方向。
  • 我调试了您建议中的代码。在您的建议中,只有当您离开游戏屏幕时,鼠标才会返回 false。但我的要求是当将鼠标悬停在停止按钮 UI 元素上时它是错误的。我将状态链接到link(红色:您的建议的输出,绿色:我需要的状态)
  • " 如果上述方法不起作用,我可以为您指出正确的方向。" -> 等待您的建议
  • 这应该可以帮助您入门:answers.unity.com/questions/1078490/…。您应该能够使用 raycast 来确定您何时在按钮上方,而不是触发
  • 用可能的光线投射示例更新了答案
猜你喜欢
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
相关资源
最近更新 更多