- Home /
OnSceneGUI has odd behaviour with multiple objects selected
So, I've made a prefab object, and I've written a script to make it stick to my ground as I move it in the editor (I want it to be something that only ever appears flat to the ground, so being able to place it in the editor is nice). My code is here:
[CustomEditor(typeof(Pad))]
[CanEditMultipleObjects]
public class PadEditor : Editor
{
void OnSceneGUI()
{
RaycastHit h;
foreach (Transform transform in Selection.transforms)
{
if (transform.gameObject.GetComponent<Pad>() == null) continue;
if (Physics.Raycast(transform.position, -transform.up, out h))
{
if (h.collider.tag == "Ground")
{
transform.rotation = Quaternion.LookRotation(Vector3.Exclude(h.normal, transform.forward), h.normal);
transform.position = h.point + transform.up * 0.05f;
}
}
else
if (Physics.Raycast(transform.position, transform.up, out h))
{
if (h.collider.tag == "Ground")
{
transform.rotation = Quaternion.LookRotation(Vector3.Exclude(h.normal, transform.forward), h.normal);
transform.position = h.point + transform.up * 0.05f;
}
}
}
}
}
This works absolutely perfectly... as long as I only try and move one object at once. If I select more than one, it works for a little bit, but then starts moving all over the place.
The error seen here occurs by moving the objects along the z-axis only. Once they leave the red object, one object moves correctly, and the other seems to hop about at random.
I'm completely stumped by this. I can't think of anything that would cause this, if anyone else can, then I'd be very grateful if you would give me a hand in working this out. Thanks.
Answer by Sjiggle · Jul 04, 2013 at 11:10 PM
Store all the data you need for the process inside the actual gameobject, rather than storing it on an editor class level basis. It seems that the OnSceneGUI routine gets called for each object, but gets called on the same editor class.
What this basically means is that if you set a variable in the editor class (isDragging = false), the second object has isDragging false. If you set it per target (target.isDragging = false) it will do the same routine in the second target, since you set the status per object, not per editor class.
You use selection.transforms, I used target as my "object". This worked fine in my scenario.
First of all, as you can see, I'm storing no data for the editor. Secondly, even if I were, I would avoid putting it on the target class if at all possible because I want the efficiency of this code never being looked at in-game. Thirdly, I'm not entirely sure what you mean by using "target", because it is not designed to be used in this way, and throws numerous errors.
What I mean by using the target ins$$anonymous$$d of selection.transforms, is the following code I use:
void OnSceneGUI()
{
var csgTarget = target as BrushComponent;
.......
$$anonymous$$ight be worth a shot, since what you are using right now does not work.
You could avoid cluttering your component classes with irrelevant data by using
#if UNITY_EDITOR
although you are right, you are not storing any essential data.
I tried that, and it seems to work a little better, but I still get the same error, just not as frequently or as severely. I think I'll just set it to not apply to multiple targets for now.