Как я могу создать объект в точке мыши на виде сцены, нажав не перетаскивая объект?

Как правило, большинство объектов размещаются в виде сцены путем перетаскивания или чего-либо еще. Я хочу щелкнуть правой кнопкой мыши (без перетаскивания объекта), чтобы создать объект в виде сцены. Я знаю, что для этого потребуется некоторое редактирование кода, но я не уверен, как это сделать.

ОБНОВИТЬ

Подумав об этом, я понял, что использование MenuItem будет вполне подходящим для меня. Вот мой код ниже:

SLMenuItems:

public class SLMenuItems : MonoBehaviour {

public bool canClickSceneViewToCreatePath = false;

void Start()
{

}

[MenuItem("Component/Create Custom Object")]
static void CreateObject()  {
   Debug.Log("menu item selected");
    canClickSceneViewToCreatePath = true;
} 
}

SLMenuItemsEditor:

    [CustomEditor(typeof(SLMenuItems))]
public class SLMenuItemsEditor : Editor {
    SLMenuItems slMenuItems;


    void OnEnable()
    {
        slMenuItems = (SLMenuItems)target;

    }


    void OnSceneGUI()
        {
            if (slMenuItems.canClickSceneViewToCreatePath)  {
                Vector3 pointsPos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin;

                if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
                {

                    // create object here at pointsPos

                    slMenuItems.canClickSceneViewToCreatePath = false;
                }
            }

        }
    }

Я продолжаю получать следующую ошибку:

Assets/SLMenuItems.cs(23,9): error CS0120: An object reference is required to access non-static member `SLMenuItems.canClickSceneViewToCreatePath'

указывая на линию:

canClickSceneViewToCreatePath = true;

в SLMenuItems,

1 ответ

Решение

Ваш CreateObject метод static но твой canClickSceneViewToCreatePath значение не

Это не имеет ничего общего со скриптом редактора, но с вашим классом SlMenuItems сам.

static Метод не является экземпляром или другими словами, он является своего рода общим для всех экземпляров этого типа компонента, в то время как нестатическое значение может отличаться для каждого компонента.

Так как же статическому методу - который является одинаковым для всех экземпляров - "знать", к каким значениям экземпляров он должен получить доступ?

Так что либо сделайте метод нестатичным, либо переменную статической. В зависимости от того, что вам нужно.

Так как MenuItem нужен статический метод, чтобы сделать переменную статической.


Я хотел бы предложить вам сделать этот класс не наследовать от MonoBehaviour вообще, так как он не имеет никакого поведения для GameObject. Он содержит только некоторые функции редактора, поэтому лучше сделать его статическим классом, который может "жить" в ресурсах без необходимости его создания.

Чем вы можете использовать SceneView.onSceneGUIDelegate зарегистрировать обратный звонок для OnSceneGUI без реализации сценария редактора для этого:

private static GameObject lastCreated;

private static bool isCreating;

public static class SLMenuItems
{   
    [MenuItem("Component/Create Custom Object")]
    private static void CreateObject() 
    {
        Debug.Log("menu item selected");

        isCreating = true;
        lastCreated = null;

        // Add a callback for SceneView update
        SceneView.onSceneGUIDelegate -= UpdateSceneView;
        SceneView.onSceneGUIDelegate += UpdateSceneView;
    }

    private static void UpdateSceneView(SceneView sceneView)
    {
        if(lastCreated)
        {
            // Keep lastCreated focused
            Selection.activeGameObject = lastCreated;
        }

        if(isCreating)
        {  
            if (Event.current.type == EventType.MouseDown && Event.current.button == 0)
            {
                Vector3 pointsPos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin;

                //Todo create object here at pointsPos
                lastCreated = Instantiate(somePrefab);

                // Avoid the current event being propagated
                // I'm not sure which of both works better here
                Event.current.Use();
                Event.current = null;

                // Keep the created object in focus
                Selection.activeGameObject = lastCreated;

                // exit creation mode
                isCreating = false;
            }
        } 
        else
        {
            // Skip if event is Layout or Repaint
            if(e.type == EventType.Layout || e.type == EventType.Repaint)
            {
                Selection.activeGameObject = lastCreated;
                return;
            }

            // Prevent Propagation
            Event.current.Use();
            Event.current = null;
            Selection.activeGameObject = lastCreated;
            lastCreated = null;

            // Remove the callback
            SceneView.onSceneGUIDelegate -= UpdateSceneView;
        }      
    }
}

Но я предлагаю вам поменять заголовок ваших вопросов, так как это на самом деле не решение "задачи", которую вы описали ранее.

Другие вопросы по тегам