2
\$\begingroup\$

In Unity3D, I have a MonoBehaviour which gets added to game objects. I'm adding a string "name" field to it. I'd like the default value for the name to be the name of the game object the component is added to. Is there an easy way to do this? Some more details:

  • The component is an existing one to which I'm adding the name field. In old versions, the name was always the name of the game object, and this is a new feature to allow them to be different.

  • The common case is (still) for the name to be the name of the game object, so having that as the default would simplify the process of adding the component to a new object.

  • Ideally, deserializing an old scene will fill in the default, so updating scenes takes zero effort. I'm less concerned about this than about newly created scenes/objects.

  • The component already uses a CustomEditor.

  • I don't care about updating the name in the component if the game object's name is changed, or if the component values are pasted into a different game object.

One way I can think of is to add a bool "override name" to the object. If the bool is unchecked, it uses the default name (the game object); if it's checked, it uses the new field. But I'd like to avoid adding complexity to the GUI to support it. The whole point of my request is to add the new functionality (overriding the name) without adding steps to the creation workflow.

\$\endgroup\$
6
\$\begingroup\$

Here's an alternative solution that will copy the current name when the component is added in the editor or at runtime:

public class NamedComponent : MonoBehaviour {

    new public string name = "";

    // For editor support: newly added scripts and deserialized scripts, respectively.
    void Reset() { InheritName(); }
    void OnValidate() { InheritName(); }

    // For components added at runtime.
    void Awake() { InheritName(); }

    void InheritName()
    {
        if (name == "")
            name = gameObject.name;
    }
}

This way the inspector field always shows the inherited name, rather than needing to explain a special behaviour when the field is empty.

\$\endgroup\$
  • 1
    \$\begingroup\$ This is closer to what I had in mind when I wrote the question; I just wasn't initially sure of which callbacks I'd need to use. The comments in the example explain perfectly. \$\endgroup\$ – Dan Hulme May 22 '17 at 16:41
4
\$\begingroup\$

So I had a bit of a "rubber duck debugging" moment with this question. Obviously the easiest way to do it is not to default the field at all, but to add a runtime wrapper for the field like this:

public string theField
{
    get
    {
        return !string.IsNullOrEmpty(_theField) ? _theField : gameObject.name;
    }
    set { _theField = value; }
}

That is, if the field isn't set, return the default value instead. That even handles the cases of pasting the component or renaming the object. It just needs a bit of extra UI or documentation so your users understand the effect of leaving the field empty. (In my case, there's only a handful of users, so it's easy enough to just tell them, but you could instead add a note using the custom editor.)

\$\endgroup\$
  • \$\begingroup\$ If you use the C# 6.0 compiler extension, you can just write return _theField ?? gameObject.name;, the null coalescing operator. \$\endgroup\$ – wondra May 22 '17 at 20:04
  • \$\begingroup\$ That's cool. Does ?? also coalesce empty strings? Most of the time the field is going to be empty, not null. \$\endgroup\$ – Dan Hulme May 23 '17 at 8:31
  • \$\begingroup\$ Sadly, I dont think so - that is a part of the answer I missed, it only checks for null. Anyhow, if it is possible, I would suggest using null as semantics for absence of value rather than empty which is not semantically entirely correct and might surprise other programmers working on same codebase - there is difference between zero and absence of value, for example. \$\endgroup\$ – wondra May 23 '17 at 10:11
  • \$\begingroup\$ @wondra I'm not sure how you think the user would set it to null through the Inspector GUI. \$\endgroup\$ – Dan Hulme May 23 '17 at 10:29
  • \$\begingroup\$ That is actually quite interesting problem - on one hand the user clearly does want to set "undefined" value, on the other hand the textbox doesn't allow it. I think it is a flaw in unity editor.The IsNullOrEmpty is better in this case(simpler=better in most cases), unless you are planning to improve editor itself via custom scripts. \$\endgroup\$ – wondra May 23 '17 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.