- Home /
[CanEditMultipleObjects] doesn't actually work for an ObjectField?
If I had two GameObjects
GO_1 and GO_2 both with a MonoBehaviour
Test. In Test there's just a GameObject
reference.
public class Test : MonoBehaviour
{
public GameObject testGo;
}
Now if I select the two GOs I'll get a "Doesn't support multi editing" for the "Test" component. OK, so I make a custom editor for MB, and mock it with [CanEditMultipleObjects] - And in OnInspectorGUI, I just call the base. Now, I can select the two objects, and when I assign a GO to testGo
, the object will gets assigned to both the references, cool!
But, if I override OnInspectorGUI and make an ObjectField
for testGO
, suddenly when I select the two objects and try to assign something to 'testGo' - it will only get assigned to the last object I selected, not both!
Why is this happening? and how to get multi editor support in this case? am I missing something? is there something else I should do?
Thanks!
EDIT: And please, don't reply to me with something related to SerializedProperties - My question is about the CanEditMultipleObjects attribute.
Answer by Jamora · Feb 12, 2014 at 12:11 PM
It would seem you need to manually assign the changed value in one script to all other selected scripts.
[CanEditMultipleObjects]
[CustomEditor(typeof(listScript))]
public class ListEditor : Editor {
listScript _target;
MonoBehaviour s = null;
void OnEnable(){
_target = (listScript)target;
s = _target.script;
}
public override void OnInspectorGUI(){
EditorGUI.BeginChangeCheck();
s = (MonoBehaviour)EditorGUILayout.ObjectField(_target.script,typeof(MonoBehaviour),true);
if(EditorGUI.EndChangeCheck()){
/*manual assignment here, remember to check that the selected objects
are in fact of the appropriate type.*/
foreach(Object obj in targets){
((listScript)obj).script = s;
}
}
}
}
This will not show the dotted line whenever objects have differing values, like SerializedProperties would. This just overrides the old value in all objects.
I know I'm a little late to the party, but how do you support undoing change to multiple objects? I tried this:
EditorGUI.show$$anonymous$$ixedValue = !targetsHaveSameUpdate$$anonymous$$ode;
EditorGUI.BeginChangeCheck ();
var newUpdate$$anonymous$$ode = (Update$$anonymous$$ode)EditorGUILayout.EnumPopup (update$$anonymous$$odeContent, firstUpdate$$anonymous$$ode);
if (EditorGUI.EndChangeCheck ())
{
Undo.RecordObjects (targets, "Changed Update $$anonymous$$ode");
foreach (var t in targets)
{
var deformable = t as Deformable;
deformable.Update$$anonymous$$ode = newUpdate$$anonymous$$ode;
}
}
Setting the update mode of multiple objects works great, but nothing happens when I undo the change. I tried this as well:
EditorGUI.show$$anonymous$$ixedValue = !targetsHaveSameUpdate$$anonymous$$ode;
EditorGUI.BeginChangeCheck ();
var newUpdate$$anonymous$$ode = (Update$$anonymous$$ode)EditorGUILayout.EnumPopup (update$$anonymous$$odeContent, firstUpdate$$anonymous$$ode);
if (EditorGUI.EndChangeCheck ())
{
foreach (var t in targets)
{
var deformable = t as Deformable;
Undo.RecordObject (deformable, "Changed Update $$anonymous$$ode");
deformable.Update$$anonymous$$ode = newUpdate$$anonymous$$ode;
}
Undo.CollapseUndoOperations (targets.Length - 1);
}
but had no luck.
I'm an idiot. It didn't work because I was changing properties and the private fields that the properties were restricting access to weren't serialized.
Answer by Darkgaze · Feb 27, 2020 at 04:43 PM
This is not explained in the documentation and I think it is quite important.
If you have your own properties, not using the automatically managed Serialized Properties, then you have to use "targets" instead of "target". I noted that if you select different types of objects with no shared script, it doesn't show shared properties, so we don't need to check if the targets are all the same type. Then you do whatever you want to do by hand with each of them.
Here's a working example of the contents of OnInspectorGUI method inside an Editor class with a simple checkbox that is changed across several scripts. Hope it helps.
var myScript = (UnityTerrainWrapper)target;
var allSelectedScripts = targets;
EditorGUI.BeginChangeCheck();
var value = GUILayout.Toggle(myScript.ShowNativeTerrain, "Draw Unity Terrain");
if (EditorGUI.EndChangeCheck())
{
foreach (var script in allSelectedScripts)
((UnityTerrainWrapper)script).ShowNativeTerrain = value;
SceneView.RepaintAll();
}
DrawDefaultInspector();
Your answer
Follow this Question
Related Questions
Is there any way to associate a "custom asset" with a particular file type? 1 Answer
Filter "Select XXX" dialog in Editor with custom code? 1 Answer
How can I restrict the object selection to prefabs only? 1 Answer
EditorGuiLayout - Objectfield 1 Answer
Are there any Editor fields which are Drag and Drop? 0 Answers