- Home /
Replace Existing Component?
So I have a Monobehaviour class (Item), and a class that inherits from it (WearableItem).
Similarly to how the Editor asks whether you would like to replace a collider with a different collider, I'd like to have only one Item script on a GameObject at any time. If I were to put another on it, it would prompt me to replace the existing one, just like Unity does with colliders.
I don't have much experience extending the editor thusfar, but what should look toward to get started?
Answer by L Elf · Oct 23, 2013 at 03:49 PM
This code works without additional components:
public class Test : MonoBehaviour {
void Reset() {
if (GetComponents<Test>().Length > 1) {
Invoke("DestroyThis", 0);
}
}
void DestroyThis() {
DestroyImmediate(this);
}
}
Shouldn't the Invoke be executed from found components? For example like
GetComponent<Animated$$anonymous$$esh>().Invoke("DestroyThis", 0);
Answer by Bunny83 · May 10, 2011 at 10:11 PM
Well, first i thought it wouldn't be possible because there's no direct event that tells you that a Component has been added. But i've figured out that Reset() is called in the editor to initialize new components.
I thought well now it's easy but unfortunately Reset is called right before the adding-process is completed. Calling DestroyImmediate inside Reset() will crash Unity :D.
You can't use the normal Destroy in the editor so that's the only way to remove the second component. In the end I've found a solution. Not as easy as i thought but also not that difficult:
DeleteComponent.cs is a helper script that is executed in editmode. We need that just for delaying the DestroyImmediate call. Just place it somewhere in your project. You don't need to attach this to something, that's done via script. It just destroys another component and itself when start is invoked (which happens right after it has been attached).
// DeleteComponent.cs using UnityEngine; using System.Collections;
[ExecuteInEditMode()] public class DeleteComponent : MonoBehaviour { public Component componentReference = null; void Start () { if (componentReference != null) DestroyImmediate(componentReference); DestroyImmediate(this); } }
Here's the actual script:
using UnityEngine; using System.Collections;
public class WearableItem : Item { #if UNITY_EDITOR void Reset () { Component OldItem = GetComponent<Item>(); if (OldItem != null && OldItem != this) { if (UnityEditor.EditorUtility.DisplayDialog("Component already exists", "Do you want to replace it?", "Ok, replace it", "No, thanks!")) { gameObject.AddComponent<DeleteComponent>().componentReference = OldItem; } else { gameObject.AddComponent<DeleteComponent>().componentReference = this; } } } #endif }
I've adjusted the classnames for your case. Maybe you want to check against Item instead of WearableItem.
Reset is only called in the editor (not at runtime) but since I use something from the editor namespace i placed the whole Reset() function in preprocessor tags to make sure it doesn't go into the build.
Your answer
Follow this Question
Related Questions
How to replace the Button component in the editor with a subclassed version 1 Answer
Extend Unity ObjectField / Array function/Gui interface 1 Answer
Is it possible to override SceneView / AnimX Private Types? 0 Answers
Multi-Object Editing not supported 1 Answer
Custom [Require*] attribute 2 Answers