#1 编辑器创建新场景
EditorApplication.SaveCurrentSceneIfUserWantsTo();
//打开是否保存场景的对话框
EditorApplication.NewScene();
//创建新场景,方法以废弃=> EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
//Editor里摧毁物体用DestroyImmediate不要用Destory;
GameObject.DestroyImmediate(gameObject);
#2 Gizmos In Scene
脚本内设置
public class GizmoExample : MonoBehaviour {//和Start()等一样自动调用private void OnDrawGizmos() {GUI...} //常态时显示Gizmosprivate void OnDrawGizmosSelected(){GUI...}//被选中时显示的Gizmos,不会覆盖前者,两者同时渲染
}
脚本外设置(Editor文件夹内)
[DrawGizmo(GizmoType.InSelectionHierarchy//自己被选中或者父级被选中时调用|GizmoType.NotInSelectionHierarchy//自己和父级都没被选中时调用|GizmoType.Selected//自己被选中时调用|GizmoType.NonSelected//自己没被选中时调用|GizmoType.Active//激活状态时调用|GizmoType.Pickable//可以通过点击Gizmos选择物体)]private static void Gizmos4ExampleNoSelected(GizmoExample target, GizmoType type){...等同于OnDrawGizmos}[DrawGizmo(GizmoType.InSelectionHierarchy|GizmoType.Pickable)]private static void Gizmos4ExampleOnSelected(GizmoExample target, GizmoType type){...等同于OnDrawGizmosSelected}
自己写一个静态方法 方法的第一个参数类型填你想要让该方法Gizmos作用的目标类型,第二个是GizmoType类型的参数的参数,
添加特性[DrawGizmo(GizmoType gizmo)] GizmoType类型参数gizmo指定调用的时机 。
Gizmos类
Gizmos.color;
//Gizmos的颜色,最好在换色前保存原有原色,Gizmos写完后reset原来的颜色,避免影响别的Gizmos
//如下所示-------------------
Color oldCol=Gizmos.color;
Gizmos.color=Color.red;
...end
Gizmos.color=oldCol
//--------------------------Gizmos.matrix;
//Gizmos的4x4矩阵 应该存了Gizmos参考的位移 旋转 大小 默认应该是原点 0旋转 1缩放(后两个猜的)
//比如为了方便设置,你想设Gizmos作用物体的Transform作为参考的原点 同样要记得reset
//如下设置-------------------
Matrix4x4 oldMatrix = Gizmos.matrix;
Gizmos.matrix = transform.localToWorldMatrix;
...end
Gizmos.matrix = oldMatrix;
//--------------------------Gizmos.Draw(Wire)Cube/Line/ray/Mesh/Sphere/Frustrum();
//具体可以绘制的各种Gizmos 实体/线框 的方块,线、射线、自定义mesh,球 、视锥体(camera的那个)
#3 Custom Inspectors
继承Editor类
[CustomEditor(typeof(targetType))]
[CustomEditor(typeof(targetType))]public class targetTypeEditor : Editor {private void OnEnable () {//启用时调用...}private void OnDisable () {//关闭时调用...}private void OnDestroy () {//摧毁时调用...}public override void OnInspectorGUI () {//...绘制Inspector面板DrawDefaultInspector();//默认显示targetType t=(targetTyp)target;//target来自Editor基类,表示目标实例}}
//打开一个Unity对话框,
bool a=EditorUtility.DisplayDialog("对话框标题","对话框内容","Yes","No");bool oldEnable=GUI.enabled;
GUI.enabled=flase;
//...enabled设为false,下面的GUI控件就无法交互和使用
GUI.enabled=oldEnable;//GUI有变化就调用SetDirty,把Target标记为dirty,告知unity保存数据
if(GUI.changed) {EditorUtility.SetDirty(_myTarget);
}
Property Drawers&DecoratorDrawer
[CustomPropertyDrawer (typeof(TypeName))]public class TypeDrawer : PropertyDrawer {//这里也可以选择继承DecoratorDrawer,装饰类型的编辑public override void OnGUI (Rect position, SerializedPropertyproperty, GUIContent label) {//这里只能用GUI和EditorGUI,不能用GUILayout和EditorGUILayout}}
所针对的Type即可以是普通的类也可以是特性类,如果是特性类,要继承PropertyAttribute
在OnGUI里写控件布局,要注意这里只能写GUI和EditorGUI中的方法,不能用带自动布局的Layout
DecoratorDrawer:
DecoratorDrawer 和Property Drawers类似,但是它不是绘制一个属性,而是单纯的根据从PropertyAttribute中得到的数据绘制用于装饰的GUI元素。(从类的成员里看,DecoratorDrawer 只有atttibute 而PropertyDrawer还有fieldInfo)
用DecoratorDrawer的特性可以叠加多个在同一个字段上。
如果是放在List 数组之类的的类型上,一个特性总共只会调用一次,不会每个数组元素都调用。
如何让自定义特性作用于自定义的Inspector里也能生效:
在OnInspectorGUI()之类的绘制方法里,我们如果直接取值,就会失去值附带的特性,为了保存附带特性我们用到SerializedObject SerializedProperty EditorGUILayout.PropertyField()
private SerializedObject _mySerializedObject;
private SerializedProperty _serializedTotalTime;private void InitSerialized () {//用target生成一个SerializedObject对象_mySerializedObject = new SerializedObject (target);//用FindProperty ("name");找到你要用的值或属性 SerializedProperty可以保留特性相关信息_serializedTotalTime = _mySerializedObject.FindProperty ("_totalTime");
}private void OnInspectorGUI() {...//这样就会显示指定特性所实现的GUIEditorGUILayout.PropertyField (_serializedTotalTime);...
}
Unity内置编辑器特性----Property Drawers---------------------[Range (0, 1)]
public float floatRange = 0.5f;[Multiline (2)]
public string stringMultiline = "This text is using a multiline
property drawer";[TextArea (2, 4)]
public string stringTextArea = "This text \nis using \na text area \
nproperty \ndrawer";[ContextMenu ("Do Something")]//..点Inspector右边的齿轮会多这个选项public void DoSomething() {Debug.Log ("DoSomething was called...");} [ContextMenuItem("Reset this value", "Reset")]//给指定的控件提供一个方法 和上面类似
public int intReset = 100;
public void Reset() {intReset = 0;}----Property Drawers-------------------------Decorator Drawers---------------------[Header("This is a group of variables")]
public int varA = 10;public int varC = 10;
[Space(40)]//上下隔空格
public int varD = 20;[Tooltip("This is a tooltip")]//鼠标移在上面的提示框
public int varE = 30;----Decorator Drawers---------------------
#4 Editor Windows
public class MyWindow : EditorWindow {public static MyWindow instance;//打开窗口的静态方法public static void OpenMyWindow () {//EditorWindow.GetWindow()创建一个窗口instance = (PaletteWindow) EditorWindow.GetWindow(typeof(PaletteWindow));instance.titleContent = new GUIContent("Palette");}private void OnEnable() {}private void OnDisable() {}private void OnDestroy() {}private void OnGUI() {}private void Update () {}}
面板选项的快捷键设置
在路径设置后 空格( )+前缀(_)+快捷键 如下面设置快捷键为 shift+p
[MenuItem(" xxxx/xxx/xx _#p") ]
[MenuItem ("Tools/Level Creator/Show Palette _#p")]
private static void ShowPalette () {PaletteWindow.ShowPalette ();
}
特殊键位表示符号
string | key |
% | Ctrl on Windows / Command on OSX |
# | Shift |
& | Alt |
LEFT/RIGHT/UP/DOWN | Arrow keys |
F1…F2 | F keys |
HOME, END, PGUP, PGDN | Home, End, Page Up, Page Down |
搜寻指定资源,第一个参数是筛选的字符串,具体规则看下面,第二个是要搜索资源的文件路径,可以同时搜寻多个路径中的文件,返回值是符合要求的guid(全局唯一标识符 global unique identifier)
string[] guids = AssetDatabase.FindAssets ("t:Prefab", new string[] {path});
//得到guid后在找资源路径,再通过路径找到具体的资源
assetPath = AssetDatabase.GUIDToAssetPath (guids [i]);
asset = AssetDatabase.LoadAssetAtPath (assetPath, typeof(GameObject)) as GameObject;
FindAssets的筛选规则:可以用三种筛选方式,且可以混合用
1、通过资源名称查找,全名或部分名称度可以 比如 找一个叫“test”的资源,可以写"Test",也可以写"Te"
2、通过资源的标签(label)查找,查找的标签名前加"l:"来区分3、通过资源的类型查找,查找的类型名前加"t:"来区分
比如"player l:img t:Texure2D"表示搜寻Texture2D类型 label为img 名称里带有player的资源
注意:查找不分大小写,多个条件用空格分开
AssetPreview.GetAssetPreview(Object asset)得到资源的预览图片,返回Texture2D
#5 自定义Scene界面
用的是Ediotr中的中的OnSceneGUI,也就是说,当你选中目标物体,对应的SceneGUI就会被调用,绘制GUI元素到Scene视窗上
[CustomEditor(typeof(targetType))]public class targetTypeEditor : Editor {...public override void OnSceneGUI () {//因为是在OnSceneGUI上调用,所以最好用这个包裹GUI//The start of a GUILayout sequence of function calls. As expected the EndGUI is used to close these.Handles.BeginGUI();//确定绘制的范围,不然默认整个屏幕了GUILayout.BeginArea(new Rect(10,10,360,30));//GUIlayout代码...GUILayout.EndArea();Handles.EndGUI();Repaint();//重新绘制,在GUI变化是可以尝试调用来更新显示}
}
除了一些属性字段 Handles类里还有有unity提供的各种Handle(?操控杆)
像Handles.PositionHandle就是我们移动物体时跟坐标轴一样的三个箭头
通过SceneView.currentDrawingSceneView 可以得到SceneView的相关信息
比如SceneView.currentDrawingSceneView.in2DMode = true;就是开启
另外SceneView.currentDrawingSceneView.camera可以得到渲染sceneView的相机,要注意这个相机不是场景中放置的相机
通过Tools.current 得到的相关信息
将在SceneView中输入的控制权从Unity默认处理转到自己处理,避免点击其他地方导致物体失去焦点,GUI消失
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Event.current 里可以得到各种键盘鼠标的输入事件
Event.current.mousePosition得到鼠标位置是基于左上的 如果想要得到基于左下,可以这样转化一下
Vector2 mousePos = Event.current.mousePosition; mousePos=new Vector2(mousePos.x,camera.pixelHeight-mousePos.y);
通过InstantiatePrefab生成对象,可以让对象是预制体(物体引用的prefab改变,物体自身也会改变)
GameObject go = PrefabUtility.InstantiatePrefab(_selectedPieces.gameObject)as GameObject;
为InspectorScript生成默认的GUI 懒得为某个引用的类特意绘制自定义的GUI,可以用这个方法
Editor.CreateEditor(InspectorScript).OnInspectorGUI();
hiding flags
每个Object都有,有下面这些选择
? None: 默认
? HideInHierarchy: 物体在Hierarchy面板隐藏
? HideInInspector: 物体在Inspector面板隐藏
? NotEditable: 物体在inspector无法编辑(变灰,不可交互)
? DontSaveInEditor: It is not saved to the scene in the editor.
? DontSaveInBuild: It is not saved when a player is built.
? DontUnloadUnusedAsset: It is not unloaded by Resources. UnloadUnusedAssets.
? DontSave: It is not saved to the scene. It will not be destroyed when a new scene is loaded. It is a shortcut for HideFlags.DontSaveInBuild | HideFlags. DontSaveInEditor | HideFlags.DontUnloadUnusedAsset.
? HideAndDontSave: It is a combination of not shown in the hierarchy, not saved to scenes, and not unloaded by the object; it will not be unloaded by Resources.UnloadUnusedAssets.
#6 GUI Styles &GUI Skins
每个GUI控件方法,基本最后都会有一个GUIStyle的选项,用来决定控件的整体显示状况
你可以用它设置控件的字体、高宽、背景图切割方式border(像边框类的九宫格式切割)等等,此外它共有8个状态,你可以设置不同状态(GUIStyleState)时显示的背景图片、字体颜色等
注:用于GUI的图片,要把它的格式变为Editor GUI and Legacy GUI
共8个状态 normal hover active onNormal onHover onActive focused onFocused
GUISkin
GUISkin就是聚和一套GUIStyle的可序列化资源,在Project里右键菜单的Create的菜单里就可以直接创建
这样就不用代码来一个个给不同类型的控件创建不同的GUIStyle了,而且因为是一种序列化资源可以在不同的项目里重复使用
#7 Scriptable Objects
继承自:: ScriptableObject
[Serializable]
public class LevelSeting:ScriptableObject
{public float gravity;public AudioClip bgm;public Sprite background;
}public static T CreateAsset<T>(string path) where T:ScriptableObject
{//创建实例T asset = ScriptableObject.CreateInstance<T>();//保存至AssetAssetDatabase.CreateAsset(asset,path);AssetDatabase.Refresh();AssetDatabase.SaveAssets();return asset;
}[MenuItem("Tools/Level Creator/NewLevelSeting")]
static void CreateLevelSeting()
{//打开一个选择存储路径的窗口string path = EditorUtility.SaveFilePanelInProject("NewLevelSetingAsset", "LevelSetings", "asset",
"Define the name for the LevelSettings asset");if (path!=null){EditorUtils.CreateAsset<LevelSeting>(path);}
}
#8 资源导入处理
实现资源导入预处理类应该继承:AssetPostprocessor
下面是一个例子
public class TexturePipeline:AssetPostprocessor{//Texture资源导入时调用private void OnPreprocessTexture(){//如果资源导入到该文件夹下,就会返回trueif (assetPath.StartsWith("Assets/Art/Bg")){ImportBackground();}}//Texture资源导入完成后调用private void OnPostprocessTexture(Texture2D texture){}void ImportBackground(){Debug.Log("Loading Background...");TextureImporter importer = assetImporter as TextureImporter;//这里就是对导入的图片的一些格式信息进行修改importer.textureType = TextureImporterType.Sprite;TextureImporterSettings importSeting=new TextureImporterSettings();importer.ReadTextureSettings(importSeting);importSeting.spriteAlignment = (int)SpriteAlignment.BottomLeft;importSeting.mipmapEnabled = false;importer.SetTextureSettings(importSeting);}}
上面只是texture资源的导入调用的方法,还有很多其他的方法可以用。