I made a very simple code to convert terrains to mesh, but playing with the Selection class, I found that it not only returns the list of objects I selected, but it returns it n times.
Note that it is the same for Selection.objects.
[MenuItem("GameObject/Tools/Terrain To Mesh", false, 0)]
public static void CreateMaterial(MenuCommand command)
{
Terrain terrain = Selection.activeGameObject.GetComponent<Terrain>();
foreach (var item in Selection.gameObjects)
{
Debug.Log(item);
}
}
Haven’t used MenuItems a lot recently, but you created a context specific menu item. AFAIK the method will be called for every object you have currently selected and the actual object will be passed in the MenuCommand context. You just additionally iterate through all objects in the selection.
If you want a general tool menu item, you probably shouldn’t group it under GameObject and remove the MenuCommand parameter from your method. If you want context specific MenuItems, you should use something like
Though when you select multiple Terrain objects and execute that command, it would be executed multiple times. So it depends on what you actually want to do here. Why do you select multiple objects in the first place?
Also you may try adding a Debug.Log to the start of your method to see how many times it gets called.
I have a map made from several unity terrains. Since unity does not allow light baking with custom shaders, at least mine, I want to convert my terrain into a mesh to benefit from light baking. But I would need to implement a LOD system etc.
With the two terrains selected, it is called 2 times. So it loops through the selected objects 2 times.
I guess you missed this particular part of Bunny’s example:
[MenuItem("CONTEXT/Terrain/Terrain2Mesh")]
Where this will mean the context menu option will only show up when right clicking the component header of a Terrain component. Makes much more sense to only show it in a more narrow context here.
If you multi-select game objects which share one or more components, it should still draw the component header, even if the component itself doesn’t support multi-editing:
I mean I don’t find it intuitive showing an option that doesn’t do anything if the game object doesn’t have a terrain component.
But at least write your code to pattern match the context into a GameObject, and TryGetComponent for a Terrain component so it doesn’t at least ram head-first into cast exceptions or null-reference exceptions.
Adding a MenuCommand parameter makes the method context specific. Which means Unity will call it for every instance that matches the context. When you just create a MenuItem like this
Not sure if the GetFiltered would work but I guess it should. This would be a normal menu item which you can also add a keyboard shortcut to it if you want.