- Home /
Prefab generalization
Hi! I want to have one generalized prefab, with some properties (scripts) and I want to be able to automatically update the scene GameObject with properties that I set. For example, I want to have one object, in which I can select the needed sprite by some textfield (direction, for example) or so.
Of course, I can use the Start function, but I will need to start the game to see changes. Is there any possibility to see the modified prefab in editor mode (because I want to use Unity scene editor as game level editor)? Or I just need to create many prefabs?
Looks like [ExecuteInEdit$$anonymous$$ode] is what I want.
If the prefabs contain a script which you modify, all the instances using that script will be modified too.
I don't understand. I mean, if I have one instantiated prefab with some properties, and I want to see the changes in Editor Window - this is the question.
For example, I have string field, I put "ugly" and I see, that prefab is using the ugly sprite.
Answer by Baste · Feb 16, 2015 at 11:31 PM
You can do this with a custom editor. Say you have this simple script:
public class SpriteThingy : MonoBehaviour
{
public SpriteRenderer spriteRenderer;
public string spriteChoice;
public Sprite t1;
public Sprite t2;
}
Then you can create a custom editor that makes the spriteRenderer's sprite be dependent on what the spriteChoice string is:
[CustomEditor(typeof(SpriteThingy))]
public class SpriteThingyEditor : Editor
{
SpriteThingy script;
void OnEnable()
{
script = (SpriteThingy)target;
}
public override void OnInspectorGUI()
{
script.t1 = (Sprite)EditorGUILayout.ObjectField("First sprite", script.t1, typeof(Sprite), false);
script.t2 = (Sprite)EditorGUILayout.ObjectField("Second sprite", script.t2, typeof(Sprite), false);
script.spriteRenderer = (SpriteRenderer)EditorGUILayout.ObjectField("Sprite Renderer", script.spriteRenderer, typeof(SpriteRenderer), true);
script.spriteChoice = EditorGUILayout.TextField("Select sprite", script.spriteChoice);
if (GUI.changed)
{
if (script.spriteChoice == "first")
script.spriteRenderer.sprite = script.t1;
else if (script.spriteChoice == "second")
script.spriteRenderer.sprite = script.t2;
else
script.spriteRenderer.sprite = null;
EditorUtility.SetDirty(script);
}
}
}
The example is a bit contrived - it might be more interesting to say load the correct sprite from resources or some database depending on the input string. You can also create dropdowns to let you select from custom lists, and a ton of other stuff. Custom editors are powerful.
I'll not go too much into detail on what the scripts does, but you can paste them and see that it works. Check out the docs for the Editor class. Sadly, those are only in JS (bad Unity, bad).
The short version - the editor class creates a custom view in the inspector. So it allows you to replace int fields with sliders and give stuff custom tooltips and whatever. But it also allows you to change the layout of the inspector, and change the attached object or other scripts as a reaction to what the designer does in the inspector.
The target variable is the component of the type you're looking at. OnInspectorGUI is called whenever the object is selected in the scene view. OnEnable is called when you first select it - I generally use it to cast the target variable to a variable with the correct type.
EditorGUILayout contains a bunch of auto-layouted methods. Check out the docs for the different methods for explanations.
GUI.changed is set to true whenever the gui changes. You can use that to prevent switching the sprite every frame.
EditorUtility.SetDirty(object) makes the editor save the changes to an object. This happens automatically when properties are changed through EditorGUILayout, but when I set the sprite directly, this has to be called.
Shout out if you have any questions or can't get this to work.