unity3d - 如何通过单击不拖动对象在场景视图中的鼠标点处创建对象?
问题描述
通常,大多数对象通过拖动或其他方式放置在场景视图中。我想右键单击鼠标(不拖动对象)以在场景视图中创建对象。我知道这需要一些编辑器编码,但我不知道该怎么做。
更新
经过一番思考,我意识到使用 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
.
解决方案
你的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;
}
}
}
但我建议您更改您的问题标题,因为这实际上不是您之前描述的“任务”的解决方案。
推荐阅读
- ios - Swift 和 SpriteKit:如何使用 SKShapeNode 实现非模糊圆形计时器
- java - 当嵌套枚举在其构造函数中引用父静态成员时,为什么我会得到 NPE?
- excel - 如何突出显示不包含任何列中特定文本的单元格
- javascript - 在一个页面上重复复制一个表格是否不合适?
- python - 为什么我的脚本在不应该的时候打开然后立即关闭?(Python)
- xctest - xcodebuild error DVTAssertions: ASSERTION FAILURE while execution single command line test,但所有测试用例命令工作正常
- nginx - 如何创建子域
- c++ - 使用 ifstream,被调用文件中的数据不打印
- c# - 哪个构建操作 (C# Microsoft Visual Studio) 适合启动在 Windows 窗体中具有零个或多个依赖项的 .exe 软件?
- java - 带有 Maven 的 Java 自动模块