2
\$\begingroup\$

I have been manually creating and deleting clones of my game objects that I arrange in a circle around a given point. Each of the objects is rotated making each object the same angle apart from the others as seen in the image below.

enter image description here

My objects range from 2 to 10. Doing this manually is very cumbersome, especially when changes have to made. How can I create a unity custom editor that allows me to specify a number of game object clones I want to create around a specified anchor point? Additionally, adjusting the number of clones should dynamically create/delete clones and reposition/rerotate them.

\$\endgroup\$
  • \$\begingroup\$ Do you mean to create the objects at runtime? You can create a script, where you give it the number of objects, then creates a circle and places everything around it. \$\endgroup\$ – TomTsagk Apr 6 '18 at 14:37
  • \$\begingroup\$ @TomTsagk not at runtime. I would like them to be visible in the scene view before runtime so I can make adjustments to them without having to run the game. \$\endgroup\$ – Hilarious404 Apr 6 '18 at 14:57
1
\$\begingroup\$

Make an object and position at the center of your circle. If you already have an object with a custom script there, make an Inspector for it. If you don't have anything, make a script. It doesn't have to do anything. It might just hold data. A custom inspector just needs an script. Let's call them CircleSpawn and CircleSpawnEditor. CircleSpawn gets attached to the object at the center of the circle. It might look like this:

public class CircleSpawn : MonoBehaviour {
    public float radius;
    public int numOfItems;
    public GameObject clonedObject;
    public List<GameObject> spawnedObjects;
}

CircleSpawnEditor needs to be saved to a folder called Editor and looks something like this:

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

[CustomEditor(typeof(CircleSpawn))]
public class CircleSpawnEditor : Editor
{

    public override void OnInspectorGUI()
    {
        var tar = (CircleSpawn)target;

        //set its values
        tar.radius = EditorGUILayout.FloatField("Radius:", tar.radius);
        tar.numOfItems = EditorGUILayout.IntField("Number of Items:", tar.numOfItems);
        tar.clonedObject = (GameObject)EditorGUILayout.ObjectField(tar.clonedObject,
                       typeof(GameObject), true);

        //Inspector button for creating the objects in the Editor
        if (GUILayout.Button("Create"))
        {

            //clean up old objects
            if (tar.spawnedObjects != null)
            {
                foreach (var ob in tar.spawnedObjects)
                {
                    DestroyImmediate(ob);
                }
            }
            tar.spawnedObjects = new List<GameObject>();

            float angleBetween = 360.0f / tar.numOfItems;
            float angle = 0;
            for (int i = 0; i <= tar.numOfItems; i++)
            {
                //for each object, find a rotation and position
                var rot = Quaternion.Euler(0, angle, 0);
                var localPos = rot * Vector3.forward * tar.radius;
                tar.spawnedObjects.Add(Instantiate(tar.clonedObject,
                    tar.transform.position + localPos, rot));
                angle += angleBetween;
            }
        }
    }
}

I tested it and the result looks like this:

enter image description here

\$\endgroup\$
  • \$\begingroup\$ all the objects have the same x value and some seem to be scaled down on the y-axis. They are not created around the clonedObject as you suggest. I haven't been able to figure out what's causing this. \$\endgroup\$ – Hilarious404 Apr 11 '18 at 17:09
  • \$\begingroup\$ I just fixed a few minor compile errors, but I tested it in Unity and it works fine. \$\endgroup\$ – tyjkenn Apr 11 '18 at 23:18
  • \$\begingroup\$ I just found the problem. My game is actually in 2d that's why I'm having the issues. How will your solution change for 2d as in the image I provided above? \$\endgroup\$ – Hilarious404 Apr 13 '18 at 13:25
  • \$\begingroup\$ I know this was not in the original question. How can I add a slider to rotate all the objects round the circle at the same time? \$\endgroup\$ – Hilarious404 Apr 13 '18 at 13:28
  • \$\begingroup\$ For 2D, just rotate around z instead of y: var rot = Quaternion.Euler(0, 0, angle);. For your other question, EditorGUILayout has a slider tool. You could have a change in the slider either rebuild the objects but with an angle offset (float angle = sliderValue), or you can have all the objects be assigned to the same parent at creation, and rotate the parent. \$\endgroup\$ – tyjkenn Apr 13 '18 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.