At some point, I found myself writing the following code:
public class TestScript : MonoBehaviour { private BoxCollider col_1; private BoxCollider col_2; private Text message; private void CheckComponents() { col_1 = GetComponent<BoxCollider>(); if(!col_1) { Debug.LogWarning(string.Format("{0} does not have a component of type BoxCollider./nAdding one...", name)); col_1 = gameObject.AddComponent<BoxCollider>(); } col_2 = GetComponent<BoxCollider>(); if (!col_2) { Debug.LogWarning(string.Format("{0} does not have a component of type BoxCollider./nAdding one...", name)); col_2 = gameObject.AddComponent<BoxCollider>(); } message = GetComponent<Text>(); if (!message) { Debug.LogWarning(string.Format("{0} does not have a component of type Text./nAdding one...", name)); message = gameObject.AddComponent<Text>(); } } }
See how quickly it can get very annoying and repetitive very fast? So, the obvious solution was to write a more functional and generic GetComponent<>() method. Here is what I did:
public static bool GetComponent<T>(this Transform t, out T component, bool needWarning = false, bool ensureComponent = false, bool addedMessage = false) where T : Component { component = t.GetComponent<T>(); if (!component) { if (needWarning) Debug.LogWarning(string.Format("{0} does not have a component of type {1}!", t.name, typeof(T))); if (ensureComponent) { component = t.gameObject.AddComponent<T>(); if (addedMessage) Debug.Log(string.Format("Added a component of type {0} to {1}", typeof(T), t.name)); } } return component; }
And my ChceckComponents() method was quickly reduced to this:
public class TestScript : MonoBehaviour { private BoxCollider col_1; private BoxCollider col_2; private Text message; private void CheckComponents() { transform.GetComponent(out col_1, true, true, true); transform.GetComponent(out col_2, false, true, false); transform.GetComponent(out message); } }
Check out the GitHub repo and let me know if you have any suggestions or ideas for the next post!
Hiya!
Alternatively, you could add the following attribute to the class definition:
[RequireComponent(typeof(BoxCollider))]
public class TestScript : MonoBehaviour {
//…
}
The editor will now force you to always have that component together with the TestScript.
Once you know the component is guaranteed to be there, you could use serialized private variables:
[SerializeField] private BoxCollider col_1;
void Reset() {
col_1 = GetComponent(); //tnx to RequireComponent, this will always work
}
That’s true! I’m actually using this method as well. Thanks for the addition 🙂
PS: Perhaps I should add this method to the the post as well 🙂