5
\$\begingroup\$

I have a script that expected the game object to have a Terrain component.

Is there an attribute I can add (or some other way) which will prevent a designer from adding my script/component/MonoBehavior to a GameObject that does not have the Terrain component?

The only alternative I have been able to find is to attach my script to something else, and then have a public Terrain field, which requires the user to attach the terrain object to it. (since the editor won't allow you to associate a different object type.) - I just want the reverse.

Any thoughts?

\$\endgroup\$
  • \$\begingroup\$ I changed the wording of your question a bit, since objects are not inherently terrain (or anything else), it's the components that make an object. \$\endgroup\$ – MichaelHouse Nov 25 '14 at 0:01
  • \$\begingroup\$ @Byte56 thank you, they way you changed the question solved my issue. While I had realized that most things were based off of the simple GameObject, it had not occurred to me that Terrain was just a component attached to it. Which would mean my original request was impossible. :) \$\endgroup\$ – Dan Violet Sagmiller Nov 26 '14 at 12:17
11
\$\begingroup\$

Applying the RequireComponent decoration to a script will ensure that the GameObject has the specified component.

If the component is missing:

  1. Unity will attempt to add a component of this type for you,
  2. If this fails (e.g. mixing RigidBody/RigidBody2D) then the script will refuse to attach.

C# sample:

[RequireComponent (typeof (Rigidbody))]
public class PlayerScript : MonoBehaviour {
    // stuff
}

UnityScript sample:

@script RequireComponent(Rigidbody)

// stuff
\$\endgroup\$
3
\$\begingroup\$

Unity has built in functionality for this called RequireComponent. Used like this in Unityscript:

@script RequireComponent(Terrain)

This will actually automatically add a Terrain component to the object if it doesn't have one already. If the user removes the Terrain component, your script will throw a compile error about the missing component.

\$\endgroup\$
1
\$\begingroup\$

Two methods come to mind, but none are very elegant.

1) Implement OnValidate(). The downside is that's it's called only when modifying component's values, or entering/exiting game mode.

void OnValidate() {
    if (GetComponent<Terrain>() == null) {
        Debug.LogError("You can't attach this component without terrain!");
        DestroyImmediate(this);
    }
}

2) Make the script run in the editor, and implement OnAwake(). But be aware that methods like Update() will be called in the editor.

[ExecuteInEditMode]
class MyScript: MonoBehaviour {
    void OnAwake() {
        if (GetComponent<Terrain>() == null) {
            Debug.LogError("You can't attach this component without terrain!");
            DestroyImmediate(this);
        }
    }
}
\$\endgroup\$

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.