how to procedurally lay out a bunch of instances (while not in play-mode).

Hi all,

I have a prefab object, that I’d like to populate my world with, say 200-300 of them, laid out in a completely parametric procedural way (e.g. in a grid, or circle, spiral, surface of a sphere etc).

I know how to do this in play-mode using a prefab and creating all the instances in a Start() function. But I’d like to be able to see this layout in the editor too, so I can manually position a number of helper objects, cameras etc depending on how the layout looks. I feel like what I want to do is run a script to populate the hierarchy and do the layout with all of the instances, while not in play-mode but in edit mode. And all of those instances are permanently placed in the scene file (and thus saved with it). But then if I don’t like the layout, I want to have them all deleted, tweak a few of the layout parameters, and then re-run the script and have a new layout generated. Then once I’m happy with that layout, I can manually position my cameras etc in the editor.

In 3D software like Maya / Houdini etc this would be quite easy just writing some python in the console, or even create a custom python tool and sticking it on the toolbar or something.

It would be even more amazing, if - instead of having to delete all of the instances, tweaking the layout parameters, and re-running the layout generation script - I could have the layout parameters affecting the layout in real-time, but still in edit-mode instead of play-mode. I.e. in edit mode I have 100 of my instances all placed in the right position and in my hierarchy etc. then I change the layout parameters in my script from 10x10 grid to 10x15 grid and immediately the layout changes. Or I tweak the grid distance and the layout updates immediately. (This is just luxury, I’m happy to press an ‘update’ button if need be :slight_smile:

Is anything like this possible in Unity using C# scripting? Or would I need to write a proper C++ plugin?

It’s a shame no-one has responded. I’m not very knowledgeable on editor stuff, but shall attempt to help out.

If you want to call a function on a script when Not in playmode, the easiest way is to use ContextMenu

for example : create a new scene, create an empty gameObject, attach the below script to it :

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ContextMenuCsharp : MonoBehaviour
{
   // http://docs.unity3d.com/ScriptReference/ContextMenu.html

#if UNITY_EDITOR
   [ContextMenu ("Make Cube Grid")]
   void MakeCubeGrid()
   {
     // destroy all existing cubes first
     if ( cubeList.Count > 0 )
     {
       for ( int i = 0; i < cubeList.Count; i ++ )
         DestroyImmediate( cubeList[i] );
     }

     // generate Cube Grid
     CubeGrid();

     Debug.Log ("MakeCubeGrid() run from ContextMenu");
   }
#endif

   public List< GameObject > cubeList;
   
   public int gridX = 5;
   public int gridY = 5;
   public int cubeSpacing = 2;
   
   
   void Start()
   {
     CubeGrid();
   }
   
   
   void CubeGrid()
   {
     int x, y;
     GameObject cube;

     cubeList = new List< GameObject >();

     for ( y = 0; y < gridY; y ++ )
     {
       for ( x = 0; x < gridX; x ++ )
       {
         cube = GameObject.CreatePrimitive( PrimitiveType.Cube );
         cube.transform.position = new Vector3( x * cubeSpacing, y * cubeSpacing, 0 );
         cubeList.Add ( cube );
       }
     }
   }
}

now when you right-click on the script component in the Inspector, you get the usual drop-down menu, with one addition at the end, “Make Cube Grid”. Click on this and watch the magic happen. Now change a variable in the Inspector, again right-click on the script component in the Inspector and select “Make Cube Grid”

A more complex way would be to write a custom editor script.

create a new scene, create an empty gameObject, attach the below script to it :

using UnityEngine;
using System.Collections;

public class CubeGrid : MonoBehaviour
{
   public GameObject cubePrefab;

   public void ButtonOne()
   {
     Debug.Log ( "Button One was pressed" );
   }
   
   public void ButtonTwo()
   {
     Debug.Log ( "Button Two was pressed" );
   }
}

Now you need a folder in the Hierarchy window named Editor. Put this script in the Editor folder :

using UnityEditor;
using UnityEngine;
using System.Collections;

[CustomEditor (typeof(CubeGrid)) ]
public class CubeGridEditor : Editor
{
   private GameObject obj;
   private CubeGrid objScript;

   void OnEnable()
   {
     obj = Selection.activeGameObject;
     objScript = obj.GetComponent< CubeGrid >();
   }
   
   public override void OnInspectorGUI()
   {
     DrawDefaultInspector();
     
     // Editor GUI Buttons

     // Button One
     EditorGUILayout.BeginHorizontal();

     if ( GUILayout.Button( "Button One", GUILayout.MinWidth( 80 ), GUILayout.MaxWidth( 250 ) ) )
     {
       objScript.ButtonOne();
     }

     EditorGUILayout.EndHorizontal();
     
     // Button Two
     EditorGUILayout.BeginHorizontal();
     
     if ( GUILayout.Button( "Button Two", GUILayout.MinWidth( 80 ), GUILayout.MaxWidth( 250 ) ) )
     {
       objScript.ButtonTwo();
     }
     
     EditorGUILayout.EndHorizontal();

   }
}

now when you select the gameObject, the Inspector should look the same as normal, with the addition of two buttons under the variables. Click on these buttons, and you should see the Debug print in the console. Now you can call as many functions as you want from the Inspector.

Here is a great tutorial that includes setting up a custom Inspector : http://catlikecoding.com/unity/tutorials/star/

This is as far as my knowledge goes with custom editor scripts. I think there is a call SetDirty which will automatically run and update the script if a variable is changed (this might only work with ExecuteInEditMode, again I have no knowledge on this). Hopefully someone with actual working knowledge will reply and supply much better information. Here is the Unity API link : Unity - Scripting API: Editor

wow that sounds perfect thanks, will check it out.

I didn’t think of linking to Unitys Learn material (they have added a lot of stuff in the last 6 months). If you havn’t already, check out the editor section (Intermediate) : Learn game development w/ Unity | Courses & tutorials in game design, VR, AR, & Real-time 3D | Unity Learn