当前位置:   article > 正文

unity编辑器扩展开发总结_unity editorapplication.update

unity editorapplication.update

转自unity Scene View扩展之编辑器扩展总结

最近一段时间都在搞编辑器,扩展各种功能,如添加Inspector上的Add Component回调功能,Unity Package 一键更新功能, 还有现在的Scene扩展,也算小有心得了,出来总结一下。

一、不运行时也可以运行的类

比较特殊的类,比如说Editor,EditorWindow,ScriptableObject,AssetPostprocessor等特殊一点的就不说了,网上一抓一大把介绍的,主要讲讲两个重要特性ExecuteInEditMode和InitializeOnLoad。

1、ExecuteInEditMode

// ExecuteInEditMode主要是让MonoBehaviour可以在不运行时,也可以执行各个生命周期的特性
// 可以配合Mono单例使用
// 需要把组件拖到GameObject上才能执行
[ExecuteInEditMode]
public class PackageManager : MonoBehaviour
{
    // 其中值得介绍的是OnEnable和OnDisable
    // 因为改了代码之后会将数据清零,而且不会执行Awake和Start
    // 但是会在编译前执行OnDisable,编译后会执行OnEnable
    // 可以用这一个时机,对一些委托的绑定与解绑,或者数据的初始化和销毁
    // 当然正常的SetActive也会触发这两个时机
    void OnEnable()
    {
    }

    void OnDisable()
    {
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2、InitializeOnLoad

// InitializeOnLoad主要是让一个普通类可以在编辑器下初始化
// 个人认为虽然可以用Mono调用单例也可以达到相同效果,不过有些时候并不需要创建一个GameObject
// 所以直接定义一个这么的类就好了
[InitializeOnLoad]
public static class EditorTiming
{
	// 构造函数可以在编辑器打开,或者编译后执行,放心地把Init或者Reset放在这里
	static EditorTiming()
	{
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3、单例模式

单例模式没什么好说的,无论时普通的Singleton,还是MonoSingleton,都可以在网上找到,这里只说一下在Unity源码里翻出来的ScriptableObjectSingleton

二、几个重要的时间节点

这里的话,就主要讲讲我用的最多的几个委托接口:

1、编辑器Update委托——EditorApplication.update

既然InitializeOnLoad只是初始话普通类,并不能update之类的,所以需要绑定一个update委托给它,让他能自行Update,用的就是这个EditorApplication.update

2、在SceneView上面写写画画——SceneView.duringSceneGui(这个为2019版的,2019前的为SceneView.onSceneGUIDelegate)

主要是处理SceneView的一些Event、操作、只在SceneView里画出各种GUI等等,详见可以看本系列的其他文章

3、代码编译相关

在编辑器编辑状态,肯定需要知道代码是不是在编译,或者编译好之后的回调之类的,这里有几个方法

(1)DidReloadScripts特性

	// 注意这个特性需要的函数时静态函数
	// 就算这个类没被使用,甚至没被实例化,都会被执行到
	// 所以用的时候需要注意判断执行条件
	[DidReloadScripts]
	private static void Reload()
	{
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(2)AssemblyReloadEvents类

这个主要两个回调:AssemblyReloadEvents.beforeAssemblyReload, AssemblyReloadEvents.afterAssemblyReload。一个在编译前执行,一个在编译后执行。

这三个的执行顺序为:AssemblyReloadEvents.beforeAssemblyReload —》 AssemblyReloadEvents.afterAssemblyReload -》 DidReloadScripts

4、资源导入相关——EditorApplication.projectChanged

既然要知道代码编译了,那么也不能缺资源被修改的回调了。

在人为操作的删除、添加、修改、编译之后,都会执行这个回调,不过坑的是,这里并没有告诉我们什么资源被修改了。

如果在代码中对资源修改之后,需要执行AssetDataBase.Refresh()

5、撤销操作——UnDo

这个暂无太多了解,只是看了这么一个例子,了解到了一些撤回的操作

https://answers.unity.com/questions/975578/undoredo-on-meshes-this-code-works-but-how.html

6、大部分都集中在EditorApplication

7、个人一些建议

个人感觉可以都把这些回调绑定在一个类里面,这样有两个好处

(1)不用每个类都关心绑定、解绑的时机

(2)可以控制每个类的执行顺序

比如说可以这样

[InitializeOnLoad]
public static class EditorTiming
{
	static EditorTiming()
	{
		EditorApplication.update += Update;
	}

	// 所有类都在这个函数里执行,顺序明显,且a、b不需要管绑定与解绑委托的事情
	void Update()
	{
		a.Update();
		b.Update();
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

三、善用反射

毕竟很多时候,Unity提供的接口并不能满足我们的开发需求,虽然有时我们可以将需要用到的代码照抄过来,但若是需要处理的数据牵扯到许多地方,这个时候,用到反射是一个很不错的选择。

这个时候就推销以下我的反射框架了,详细介绍见Unity Package 一键更新功能开发之C#反射框架篇。

然后自己也建了一个对标unity开源代码UnityCsReference的UnityCsReflection,欢迎Star→_→

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/141624
推荐阅读
相关标签
  

闽ICP备14008679号