Editor Scripting. How to add objects in Editor on Click

Hi there. I am hoping to streamline the process of building game waypoints using some Editor scripting, but Im not quite sure how to do it.

Basically I wish to create a waypoint on a plane at the position where the mouse is clicked.

My questions are:

a) Is it possible to ‘turn on’ a mouse click response, so that I can click to add waypoints

b) How do I retrieve the “click” positions, and is there a process to convert into world space so that I can do a raycast down onto the plane.

c) The prefab that I plan on instantiating has an id variable, I wish to set this as I click (based on the length of a static array of previously added items)

Thanks for any pointers, Im quite excited by the possibility of using unity editor scripts to do my level builds for me!!!

Mark

You can use an OnSceneGUI function in your editor script to intercept actions in the scene.

Raycasting still works in the scene view (I think Camera.current is the best way to access the camera). There is a thread about raycasting here.

There should be no problem setting the id variable from the editor script.

for anyone interested in a point click add waypoint system

I created a plane and added an arbitrary class WaypointContainer to it
I then added the script below to the Editor class. When you click enable editing you can then just click around and add waypoints. Might help someone else out.

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

[CustomEditor(typeof(WaypointContainer))]
public class WaypointContainerEditor : Editor
{

    private static bool m_editMode = false;
    private static int m_count = 0;
    private GameObject m_container;

    void OnSceneGUI()
    {

        if (m_editMode)
        {
            if (Event.current.type == EventType.MouseUp)
            {
                Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                RaycastHit hitInfo;

                
                if (Physics.Raycast(worldRay, out hitInfo))
                {
                    GameObject waypoint = Resources.LoadAssetAtPath("Assets/Prefabs/Waypoint.prefab", typeof(GameObject)) as GameObject;
                    GameObject waypointInstance = Instantiate(waypoint) as GameObject;
                    waypointInstance.transform.position = hitInfo.point;
                    waypointInstance.name = "Waypoint" + m_count.ToString("00");
                    waypointInstance.transform.parent = m_container.transform; 
                    Waypoint waypointScript = waypointInstance.GetComponent("Waypoint") as Waypoint;
                    waypointScript.id = m_count;

                    EditorUtility.SetDirty(waypointInstance); 

                    m_count++;
                } 
                
            }

            Event.current.Use();

        }

    }
    public void OnInspectorGUI()
    {
        if (m_editMode)
        {
            if (GUILayout.Button("Disable Editing"))
            {
                m_editMode = false;
            }
        }
        else
        {
            if (GUILayout.Button("Enable Editing"))
            {
                m_editMode = true;

                // GET Current number of waypoints currently in window and start from there
                UnityEngine.Object[] waypoints = FindObjectsOfType(typeof(Waypoint));
                m_count = waypoints.Length;
                if (m_count < 0) m_count = 0;

                m_container = GameObject.Find("z_Waypoints");

            }
        }

        if (GUILayout.Button("Reset"))
        {
            m_count = 0;
        }

    }


}

WaypointContainer.cs - attach this to the plane that adding waypoints too

using UnityEngine;
using System.Collections;
using System;


public class WaypointContainer : MonoBehaviour
{
    void Start()
    {
        //Waypoint.InitAll();
    }
}

And finally My waypoint (You’ll need to modify it im sure to your own concept)

using UnityEngine;
using System.Collections;
using System;

//-----------------------------------------------------------------
// Waypoint
//-----------------------------------------------------------------

public class Waypoint : MonoBehaviour, IComparable
{
	public static ArrayList waypoints = new ArrayList();
	
    public int id;
    
	public ArrayList targets;

    private Waypoint m_target;
	private int m_steps = 2;
	private float m_stepWidth = 5f;
	private float m_angle;
    private bool m_initilised = false;


    public static void reset()
    {
        waypoints = new ArrayList();
    }

    public static void InitAll()
    {
        Waypoint waypoint;

        waypoints.Sort(); // sort based on id

        for (int i = 0; i < waypoints.Count; i++)
        {
            waypoint = (Waypoint)waypoints[i];
            waypoint.Init();
        }

    }

    public void Awake()
    {
        m_initilised = false;

        waypoints.Add(this);
    }

    public void Init()
    {
		targets = new ArrayList();

        int nextWaypoint;
        nextWaypoint = id + 1;

        if (nextWaypoint > waypoints.Count - 1) nextWaypoint = 0;

        m_target = (Waypoint)waypoints[nextWaypoint];
        
        //Debug.Log("Waypoint Added");

		float dx = m_target.transform.position.x - transform.position.x;
		float dz = m_target.transform.position.z - transform.position.z;
		
		m_angle = Mathf.Atan2(dz,dx) + Mathf.PI * 0.5f;
		
		// Build Subwaypoints
		
		dx = Mathf.Cos(m_angle);
		dz = Mathf.Sin(m_angle);
		
		for (int i = -m_steps; i < m_steps; i++)
        {
			Vector3 position = new Vector3( dx , 0f, dz) * i * m_stepWidth ;
			targets.Add(position + transform.position);
		}

        m_initilised = true;

			
    }
	
	public int CompareTo(object obj)
    {
        Waypoint u = (Waypoint)obj;
        return this.id.CompareTo(u.id);
    } 

    public void OnDrawGizmos()
    {
        

        Gizmos.color = Color.red;
        Gizmos.DrawCube(transform.position, Vector3.one * 5f);

        if (!m_initilised) return; 

	    Gizmos.color = Color.red;
        Gizmos.DrawLine (transform.position, m_target.transform.position);
       
		
		/*
		for (int j = 0; j < targets.Count; j++)
	    {
			Vector3 position = (Vector3)targets[j];
			Gizmos.color = Color.white;
			Gizmos.DrawCube(position, Vector3.one);
		}
		*/
		
	
		//Gizmos.DrawLine (transform.position - range, range + transform.position);
    }
}
6 Likes

I realize this was over 6 years ago, but I’m curious how you keep your game object (processed by the custom editor you wrote) from losing focus when you click in the scene view?

3 Likes