0
\$\begingroup\$

I was trying to create a debug view for my Water object in my Unity application. The problem is that I generate the water at runtime, which makes it impossible to see what it looks like in the editor mode. To resolve this, I created a script that draws a simple sprite representing my water:

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

[ExecuteInEditMode]
public class WaterEditor : MonoBehaviour
{
    [SerializeField] Sprite waterSprite;

    GameObject debugWaterObject;
    SpriteRenderer tileRenderer;
    Water water;
    
    void OnEnable() {
        water = GetComponent<Water>();
    }

    void Update()
    {
        if (Application.isPlaying) {
            Debug.Log("Destroying debug object");
            Destroy(debugWaterObject);
            return;
        } else if (debugWaterObject == null) {
            Debug.Log("Creating debug object");
            debugWaterObject = new GameObject("Water Debug Object");
            debugWaterObject.transform.SetParent(transform);
            debugWaterObject.transform.localPosition = Vector3.zero;
            tileRenderer = debugWaterObject.AddComponent<SpriteRenderer>();
            tileRenderer.sprite = waterSprite;
            tileRenderer.drawMode = SpriteDrawMode.Sliced;
        }

        tileRenderer.size = new Vector2(water.width, water.height);
    }
}

The idea is that I create a debug object in editor mode and then destroy it in play mode. However, for some reason, when I run my application, I can still see the object in the editor: Object is not destroyed

I'm pretty sure that Destroy(debugWaterObject) is called, and the object is not recreated in play mode. It seems that it is not being destroyed. I haven't been able to find any explanation for that. Why could this happen?

\$\endgroup\$
1
  • \$\begingroup\$ Just to be sure, your script has as well the correct object assigned? \$\endgroup\$
    – Zibelas
    Commented Dec 30, 2023 at 11:00

2 Answers 2

1
\$\begingroup\$

When you set a debugger breakpoint* in your script, then you will see that the debugWaterObject becomes null as soon as you switch from game mode to play mode.

This has something to do with how Unity re-initializes objects in the scene on game launch. If you want changes to inspector-exposed variables made by edit mode scripts to persist, then it's not enough to just change the variable. You have to go through the serialized property API.

But there is probably a much easier solution to the problem: Just add this little script to the debug object that will cause it to self-terminate as soon as you enter play mode:

using UnityEngine;

public class SelfDestroyOnAwake : MonoBehaviour
{
    void Awake()
    {
        Destroy(gameObject);
    }
}

Note that this script does not have anything that causes it to execute in edit mode, so it will only execute in play mode.

In order to attach a script to an object that was just created via new GameObject, do this:

debugWaterObject.AddComponent<SelfDestroyOnAwake>();

*If you don't know what debugger breakpoints are, then I really recommend to learn how to use the debugger of your preferred code editor with Unity. It will help you solve about 95% of programming problems yourself that would otherwise require you to ask on the Internet.

\$\endgroup\$
0
\$\begingroup\$

You're working in the Editor, and using [ExecuteInEditMode]. It's better to use EditorApplication.isPlaying instead of Application.isPlaying. While both do essentially the same thing, one was made specifically for Editor stuff, and the other one works better for build applications (even though it should work in Editor as well, but sometimes it can behave weirdly).

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Can you describe in what way the editor version behaves "better" or what specifically is "weird" about the non-editor version? Does it account for an object not getting destroyed? \$\endgroup\$
    – DMGregory
    Commented Dec 30, 2023 at 2:02
  • \$\begingroup\$ Thanks for the hint! I will check the difference between EditorApplication.isPlaying and Application.isPlaying. But as I said Destroy is called, so it won't resolve the issue with object not being destroyed. \$\endgroup\$ Commented Dec 30, 2023 at 13:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .