Unity,编辑器时脚本,在添加到场景事件的游戏对象上
Unity, editor-time script, On GameObject Added to Scene Event
假设您有一个普通的预制件,"Box",我们会说它只不过是一个标准的立方体。
1 - 预制框在您的项目面板中
2 - 将其拖到场景中
3 - 显然它现在也出现在层次结构面板中,并且可能被选中并显示在检查器中
需要说明的是,当您执行此操作时,游戏并未开始运行,您仅处于普通编辑器模式。
是否可以制作一个脚本("Editor script"?)以便
当你执行上面的“1”和“2”时,(同样这是在编辑器模式下,而不是在游戏中)
当3发生时,我们可以影响场景中新的Box item
所以,简单的例子:无论你把它放在哪里,我们都会将 Z 位置始终设置为“2”。
简而言之:编辑器代码,以便每次将预制件 P 拖到场景中时,它都会将位置 z 设置为 2.0。
这在 Unity 中可行吗?我对 "editor scripts".
一无所知
很明显这应该是可能的。
Monobehaviours 有一个 Reset 方法,该方法 仅在编辑器模式下被调用 ,每当您重置 或首次实例化 一个对象。
public class Example : MonoBehaviour
{
void Reset()
{
transform.position =
new Vector3(transform.position.x, 2.22f, transform.position.z);
Debug.Log("Hi ...");
}
}
你可以这样做:
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class PrintAwake : MonoBehaviour
{
#if UNITY_EDITOR
void Awake() .. Start() also works perfectly
{
if(!EditorApplication.isPlaying)
Debug.Log("Editor causes this Awake");
}
#endif
}
见https://docs.unity3d.com/ScriptReference/ExecuteInEditMode.html
分析:
这确实有效!
一个问题!它发生在对象开始存在时,因此,当您将其拖动到场景中,但在您放手之前。所以事实上,如果你特别想以某种方式调整 position(捕捉到网格 - 无论如何),使用这种技术是不可能的!
因此,例如,这将完美地工作:
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class PrintAwake : MonoBehaviour
{
#if UNITY_EDITOR
void Start() {
if(!EditorApplication.isPlaying) {
Debug.Log("Editor causes this START!!");
RandomSpinSetup();
}
}
#endif
private void RandomSpinSetup() {
float r = Random.Range(3,8) * 10f;
transform.eulerAngles = new Vector3(0f, r, 0f);
name = "Cube: " + r + "°";
}
}
请注意,这可以正常工作,也就是说 "not run" 当您实际玩游戏时它可以正常工作。如果您点击 "Play",它将不会再次设置随机旋转:)
很棒的东西
您可以添加实现 OnHierarchyChange
的自定义 window 编辑器来处理层次结构 window 中的所有更改。该脚本必须位于 Editor 文件夹中。要使其自动运行,请确保先打开此 window。
using System.Linq;
using UnityEditor;
using UnityEngine;
public class HierarchyMonitorWindow : EditorWindow
{
[MenuItem("Window/Hierarchy Monitor")]
static void CreateWindow()
{
EditorWindow.GetWindow<HierarchyMonitorWindow>();
}
void OnHierarchyChange()
{
var addedObjects = Resources.FindObjectsOfTypeAll<MyScript>()
.Where(x => x.isAdded < 2);
foreach (var item in addedObjects)
{
//if (item.isAdded == 0) early setup
if (item.isAdded == 1) {
// do setup here,
// will happen just after user releases mouse
// will only happen once
Vector3 p = transform.position;
item.transform.position = new Vector3(p.x, 2f, p.z);
}
// finish with this:
item.isAdded++;
}
}
}
我在盒子里附上了以下脚本:
public class MyScript : MonoBehaviour {
public int isAdded { get; set; }
}
请注意,OnHierarchyChange
被调用了两次(一次是在您开始将框拖到场景中,一次是在您释放鼠标按钮时),因此 isAdded
被定义为一个 int
以使其与 2
进行比较。所以你也可以在 x.isAdded < 1
时有初始化逻辑
假设您有一个普通的预制件,"Box",我们会说它只不过是一个标准的立方体。
1 - 预制框在您的项目面板中
2 - 将其拖到场景中
3 - 显然它现在也出现在层次结构面板中,并且可能被选中并显示在检查器中
需要说明的是,当您执行此操作时,游戏并未开始运行,您仅处于普通编辑器模式。
是否可以制作一个脚本("Editor script"?)以便
当你执行上面的“1”和“2”时,(同样这是在编辑器模式下,而不是在游戏中)
当3发生时,我们可以影响场景中新的Box item
所以,简单的例子:无论你把它放在哪里,我们都会将 Z 位置始终设置为“2”。
简而言之:编辑器代码,以便每次将预制件 P 拖到场景中时,它都会将位置 z 设置为 2.0。
这在 Unity 中可行吗?我对 "editor scripts".
一无所知很明显这应该是可能的。
Monobehaviours 有一个 Reset 方法,该方法 仅在编辑器模式下被调用 ,每当您重置 或首次实例化 一个对象。
public class Example : MonoBehaviour
{
void Reset()
{
transform.position =
new Vector3(transform.position.x, 2.22f, transform.position.z);
Debug.Log("Hi ...");
}
}
你可以这样做:
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class PrintAwake : MonoBehaviour
{
#if UNITY_EDITOR
void Awake() .. Start() also works perfectly
{
if(!EditorApplication.isPlaying)
Debug.Log("Editor causes this Awake");
}
#endif
}
见https://docs.unity3d.com/ScriptReference/ExecuteInEditMode.html
分析:
这确实有效!
一个问题!它发生在对象开始存在时,因此,当您将其拖动到场景中,但在您放手之前。所以事实上,如果你特别想以某种方式调整 position(捕捉到网格 - 无论如何),使用这种技术是不可能的!
因此,例如,这将完美地工作:
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class PrintAwake : MonoBehaviour
{
#if UNITY_EDITOR
void Start() {
if(!EditorApplication.isPlaying) {
Debug.Log("Editor causes this START!!");
RandomSpinSetup();
}
}
#endif
private void RandomSpinSetup() {
float r = Random.Range(3,8) * 10f;
transform.eulerAngles = new Vector3(0f, r, 0f);
name = "Cube: " + r + "°";
}
}
请注意,这可以正常工作,也就是说 "not run" 当您实际玩游戏时它可以正常工作。如果您点击 "Play",它将不会再次设置随机旋转:)
很棒的东西
您可以添加实现 OnHierarchyChange
的自定义 window 编辑器来处理层次结构 window 中的所有更改。该脚本必须位于 Editor 文件夹中。要使其自动运行,请确保先打开此 window。
using System.Linq;
using UnityEditor;
using UnityEngine;
public class HierarchyMonitorWindow : EditorWindow
{
[MenuItem("Window/Hierarchy Monitor")]
static void CreateWindow()
{
EditorWindow.GetWindow<HierarchyMonitorWindow>();
}
void OnHierarchyChange()
{
var addedObjects = Resources.FindObjectsOfTypeAll<MyScript>()
.Where(x => x.isAdded < 2);
foreach (var item in addedObjects)
{
//if (item.isAdded == 0) early setup
if (item.isAdded == 1) {
// do setup here,
// will happen just after user releases mouse
// will only happen once
Vector3 p = transform.position;
item.transform.position = new Vector3(p.x, 2f, p.z);
}
// finish with this:
item.isAdded++;
}
}
}
我在盒子里附上了以下脚本:
public class MyScript : MonoBehaviour {
public int isAdded { get; set; }
}
请注意,OnHierarchyChange
被调用了两次(一次是在您开始将框拖到场景中,一次是在您释放鼠标按钮时),因此 isAdded
被定义为一个 int
以使其与 2
进行比较。所以你也可以在 x.isAdded < 1