通常,大多数对象是通过拖动或其他方式放置在场景视图中的。我想右键单击鼠标(不拖动对象)以在场景视图中创建一个对象。我知道这需要一些编辑器编码,但是我不确定该怎么做。
更新
经过深思熟虑,我意识到使用MenuItem对我来说非常合适。这是我的代码如下:
SLMenuItems:
BRL
SLMenuItemsEditor:
currency = 'BRL'
options = '
<option selected>Select Currency</option>
<option value="AUD">(AUD) Australian Dollar</option>
<option value="BRL">(BRL) Brazilian Real</option>
<option value="CAD">(CAD) Canadian Dollar</option>
<option value="CZK">(CZK) Czech Koruna</option>
<option value="DKK">(DKK) Danish Krone</option>
<option value="EUR">(EUR) Euro</option>
<option value="HKD">(HKD) Hong Kong Dollar</option>
<option value="HUF">(HUF) Hungarian Forint</option>
<option value="ILS">(ILS) Israeli New Sheqel</option>
<option value="JPY">(JPY) Japanese Yen</option>
<option value="MYR">(MYR) Malaysian Ringgit</option>
<option value="MXN">(MXN) Mexican Peso</option>
<option value="NOK">(NOK) Norwegian Krone</option>
<option value="NZD">(NZD) New Zealand Dollar</option>
<option value="PHP">(PHP) Philippine Peso</option>
<option value="PLN">(PLN) Polish Zloty</option>
<option value="GBP">(GBP) Pound Sterling</option>
<option value="SGD">(SGD) Singapore Dollar</option>
<option value="SEK">(SEK) Swedish Krona</option>
<option value="CHF">(CHF) Swiss Franc</option>
<option value="TWD">(TWD) Taiwan New Dollar</option>
<option value="THB">(THB) Thai Baht</option>
<option value="TRY">(TRY) Turkish Lira</option>
<option value="USD">(USD) U.S. Dollar</option>'
options.sub(' selected', '').sub(%r{("#{currency}")}, '\1 selected').html_safe
我一直收到以下错误:
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;
}
}
指向该行:
[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'
中。
答案 0 :(得分:2)
您的CreateObject
方法是static
,但您的canClickSceneViewToCreatePath
值不是。
它与编辑器脚本无关,但与您的类SlMenuItems
本身无关。
static
方法未实例化,或者换句话说,该方法在该组件类型的所有实例之间共享,而每个组件的非静态值可能不同。
那么,应该如何使用静态方法-所有实例都相同-“知道”,应该访问哪个实例值?
因此,要么使方法为非静态方法,要么使变量为静态方法。取决于您的进一步需求。
由于MenuItem
需要静态方法,因此也将变量设为静态。
我建议您使该类完全不继承自MonoBehaviour
,因为它对GameObject没有任何行为。它仅带来一些编辑器功能,因此使其成为可以在Assets中“存在”而无需实例化的静态类。
比起您可以使用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;
}
}
}
但是我建议您更改问题标题,因为这实际上并不是您之前描述的“任务”的解决方案。