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

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

UPDATE

Подумав немного, я понял, что использование 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 Ответ

0 голосов
/ 03 ноября 2018

Ваш 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;
        }      
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...