【问题标题】:Unity EditorWindow - Toggle Gameobject from WindowUnity EditorWindow - 从窗口切换游戏对象
【发布时间】:2019-01-31 12:43:55
【问题描述】:

我使用 Unity 已经有一段时间了,但从未尝试过编辑器。今天我决定尝试制作一个 EditorWindow 来帮助我的开发捷径。

我想要的是单击窗口上的按钮来打开和关闭场景中的特定灯光。

在下面添加了代码和窗口的图像。

我不知道如何继续。任何帮助将不胜感激!

public class DevTools : EditorWindow
{
    public Object workLight;

    [MenuItem("Window/DevTools")]
    public static void ShowWindow()
    {
        GetWindow<DevTools>("Development Tools");
    }

    private void OnGUI()
    {
        GUILayout.Label("This is the development tools.", EditorStyles.boldLabel);

        workLight = EditorGUILayout.ObjectField(workLight, typeof(object), true);

        if (GUILayout.Button("Working Light"))
        {
            if(workLight == null)
            {
                ShowNotification(new GUIContent("No light selected"));
            }
            else
            {

            }
        }
    }
}

This is my current Window

【问题讨论】:

  • 请在问题中输入代码
  • 您需要将 workLight 对象转换为实际的 Light 或 Unity 中的任何等效类型,这样您就可以访问灯光的属性/方法并调用适当的方法 -只是看一下文档,因为所有对象都是 GameObject 实例,您需要使用GetComponent&lt;Light&gt;() 从实例中获取Light 组件-您的workLight 不应该是GameObject 类型吗?如果没有,我假设您可以直接投射,然后使用 GetComponent?

标签: c# visual-studio unity3d


【解决方案1】:

嗯,您需要对该对象的引用才能继续打开和关闭它。您可以在编辑器中添加字段并从场景中手动选择对象,也可以通过 GameObject.Find 动态查找。

【讨论】:

  • 我应该把GameObject.Find放在哪里?我刚刚在我的 else 语句中尝试了 workLight.gameObject.SetActive(true);。将GameObject.Find("Work Light"); 放在上面之后。我是这个编辑器编码的新手,所以不知道如何构建它。
  • 我认为您不需要这个 - 我相信 GUI 中的编辑器框允许您在单击对象时选择它?如果是这样,则在单击按钮时,您已经在 worklight 变量中拥有游戏对象的实例
【解决方案2】:

我不太了解 Unity(从未使用过它),但它看起来很简单。

EditorFieldForObject 方法似乎采用第二个类型参数,表示您可以使用 GUI 中的字段选择哪些类型 - 我不确定您是否可以将其设为 GameObject,但基本上有两种应该可行的方法:

保留您的代码并转换对象(在OnGUI 方法中):

var gameObject = workLight as GameObject;

if(gameObject == null)
{
    ShowNotification(new GUIContent("No light selected"));
}
else
{
    var light = gameObject.GetComponent<Light>();

    if(light == null) 
    {
        ShowNotification(new GUIContent("Selected object is not a light"));
        return;
    }

    // Not sure if this is the correct way to disable a light but you can figure it out
    light.enabled = false;
    // or light.enabled = !light.enabled to toggle state
}

另一种方法是让编辑器 GUI 框首先查找 GameObject 实例:

public GameObject workLight;
....
workLight = EditorGUILayout.ObjectField(workLight, typeof(GameObject), true);

但我不确定这是否可能(正如我所说,我不了解 Unity)

编辑:显然您需要使用 GameObject.SetActive(boolean) 来切换 对象的状态

由于您想要切换,您可以使用GameObject.activeSelf 字段,它为您提供当前对象上的活动真/假标志

所以这应该有效:

light.SetActive(!light.activeSelf);

【讨论】:

  • 显然,如果我在 else 中执行 light.SetActive(false);,这现在可以工作,但我希望每次按下按钮时它都会切换。
  • 试试light.SetActive(!light.activeSelf) - 我认为activeSelf 会根据此处的文档告诉您对象是否处于活动状态:docs.unity3d.com/ScriptReference/GameObject-activeSelf.html
  • 所以我也遇到了同样的事情,我可以关灯了。但是当灯光为 Null 时,它给了我一个空参考。我试过var light =GameObject.Find("Work Light");var light = GameObject.FindGameObjectWithTag("WorkLight"); 他们在尝试重新打开它时都给出了空引用。
  • 如果我理解正确,您不需要找到GameObject - 您在按钮上方添加的框允许您单击它,然后在场景中选择一个对象(或者您可能选择场景中的一个对象,此框会自动填充)。如果是这样,您的原始代码中的 workLight 变量中已经有一个游戏对象的实例。您不需要找到游戏对象,因为 GUI 已经为您填充了对该对象的引用。你只需要尝试投射,它应该可以工作。如果您使用我发布的确切代码,它应该可以工作。
  • 如果您查看此处的示例代码:docs.unity3d.com/ScriptReference/…,您可以看到他们不使用GameObject.Find,而只是响应OnGUI 事件,假设source == null(在这种情况下)未选择任何内容)或其他布尔结果(已选择某些内容)。他们直接在source 上操作,而不需要Find
【解决方案3】:

非常感谢查理!

稍微重写一下,这似乎可行。不确定它是否完美优化,但它工作顺利(atm):p。

public class DevTools : EditorWindow
{
    Object workLight = default;

    [MenuItem("Window/DevTools")]
    public static void ShowWindow()
    {
        GetWindow<DevTools>("Development Tools");
    }
    private void OnGUI()
    {
        GUILayout.Label("This is the development tools.", EditorStyles.boldLabel);
        if (GUILayout.Button("Working Light"))
        {
            if (workLight == null)
            {
                ShowNotification(new GUIContent("No light selected"));
            }
            else
            {
                var light = GameObject.Find("Work Light");
                if (light == null)
                {
                    ShowNotification(new GUIContent("Selected object is not a light"));
                    return;
                }
                else
                {
                    light.gameObject.GetComponent<Light>().enabled = !light.gameObject.GetComponent<Light>().enabled;
                }
            }
        }
    }
}

【讨论】:

  • 这仅适用于场景中的一种灯光,如果灯光处于非活动状态,则无效。查看文档中的GameObject.Find 会显示此This function only returns active GameObjects. If no GameObject with name can be found, null is returned. If name contains a '/' character, it traverses the hierarchy like a path name.。也不确定对象命名 - 我假设您有不止一盏灯,并且您只能使用此代码切换一盏灯(名为 Work Light`)
  • 此外,如果您不打算使用它所连接的变量,那么在您的窗口上使用 GUI 选择器是没有意义的 - 您将忽略 workLight 变量并使用 GameObject.Find 这是无论您在场景中选择哪种灯光,每次都会找到相同的对象。
  • 这只是一个定向光,它为我的整个场景提供光。所以我只有一个。 :)
  • 拥有workLight = EditorGUILayout.ObjectField(workLight, typeof(object), true);workLight 变量是没有意义的,因为它应该在那里,所以你可以在场景中选择一个对象,这样你就可以用它做一些事情。如果您只有一盏灯,那么您应该没问题,假设您每次单击按钮时都没有覆盖 GameObject.Find 的先前结果 - 文档指出尝试查找非活动对象将返回 null 所以我不确定这是怎么回事?
  • if (GUILayout.Button("Working Light")) { var light = GameObject.Find("Work Light"); var lighting = light.gameObject.GetComponent&lt;Light&gt;(); if (light == null) { ShowNotification(new GUIContent("Selected object is not a light")); return; } else { lighting.enabled = !lighting.enabled; } } 是的,我将整个按钮缩短到这个。
猜你喜欢
  • 1970-01-01
  • 2016-09-23
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 2017-12-13
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多