这篇的主要内容为如何通过编辑器窗口(EditorWindow)实现简单的技能编辑功能。大致思想为在窗口中输入内容并且保存为后续可以读取使用的配置文件。
一、准备工作
- Unity需要下载NewtonSoft Json插件
- 创建特殊文件夹——Editor(不一定要创建在Assets目录下,Scripts/Editor也可以生效)
- 在Editor文件夹中创建脚本
二、代码部分
(一)生成技能编辑器窗口
-
脚本引入UnityEditor 并改继承为EditorWindow
-
在unity菜单栏中生成目录
注意:此函数必须为静态函数
-
生成技能编辑器窗口
注意:红框中必须为当前脚本名,不能直接用EditorWindow类
打开技能编辑器窗口完整代码如下
static SkillData sd;
static Texture texture;
static List<SkillData> list;
[MenuItem("Skill/技能编辑器")]
public static void Init()
{
var window = GetWindow<SkillEditor>("技能编辑器");
if (window != null)
{
window.Show();
}
//读取配置文件中的数据
list = JsonConvert.DeserializeObject<List<SkillData>>(Resources.Load<TextAsset>("SkillData").text);
sd = new SkillData();
sd.skillID = list.Count;
//生成按钮的贴图
texture = Resources.Load<Texture>("SkillIcon/binshuangfashi_1b");
}
(二)生成简易技能信息类
/// <summary>
/// 技能类型
/// </summary>
public enum SkillType
{
指向技能,
范围技能,
主动技能,
被动技能
}
/// <summary>
/// 特效移动类型
/// </summary>
public enum EffectMoveType
{
直线,
弧线
}
public struct V3
{
public float x;
public float y;
public float z;
public V3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
public class SkillData
{
public int skillID; // ID
public string skillNick; // 名称
public string skillIconPath; // 图标路径
public SkillType skillType; // 技能类型
public float beginAnimTime; // 开始播放动画时间
public string skillAnimPath; // 动画路径
public float beginEffectTime; // 开始创建特效时间
public string skillEffectPath; // 特效路径
public V3 beginEffectPos; // 创建特效位置
public float effectDuration; // 特效持续时间
public EffectMoveType effectMoveType; // 特效移动类型
public int effectNum; // 特效数量
public float effectCD; // 特效间隔时间
public string endEffectPath; // 结束特效路径
public float castingDistance; // 施法距离
public float skillCD; // 技能释放间隔时间
}
(三)生成技能编辑器窗口中的具体内容
注意:有 GUILayout.BeginHorizontal() 就一定要有 GUILayout.EndHorizontal() 来结尾
GUILayout.BeginVertical() 与 GUILayout.EndVertical() 同理
AnimationClip anim;
GameObject skillEffect;
GameObject endEffect;
Vector3 pos;
private void OnGUI()
{
//开始纵向排序
GUILayout.BeginVertical();
//开始横向排序
GUILayout.BeginHorizontal();
//输出文字
GUILayout.Label("技能ID");
GUILayout.Label(sd.skillID.ToString());
//结束横向排序
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("技能名称");
//输入字符串
sd.skillNick = GUILayout.TextField(sd.skillNick);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
//创建按钮
if (GUILayout.Button(texture, GUILayout.Width(50), GUILayout.Height(50)))
{
//打开指定文件夹选择图片 并返回路径
string path = EditorUtility.OpenFilePanel("选择图片", Application.dataPath + "/Resources/SkillIcon", "png");
Debug.Log(path);
sd.skillIconPath = "SkillIcon/" + GetIconPath(path);
texture = Resources.Load<Texture>(sd.skillIconPath);
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
//枚举下拉列表
sd.skillType = (SkillType)EditorGUILayout.EnumPopup("技能类型", sd.skillType);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
//输入数字
sd.beginAnimTime = EditorGUILayout.FloatField("开始播放动画时间", sd.beginAnimTime);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("选择技能动画");
//输入指定类型对象
anim = EditorGUILayout.ObjectField(anim, typeof(AnimationClip), false) as AnimationClip;
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.beginEffectTime = EditorGUILayout.FloatField("开始创建特效时间", sd.beginEffectTime);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("选择技能特效");
skillEffect = EditorGUILayout.ObjectField(skillEffect, typeof(GameObject), false) as GameObject;
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
pos = EditorGUILayout.Vector3Field("生成特效位置", pos);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.effectDuration = EditorGUILayout.FloatField("特效持续时间", sd.effectDuration);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.effectMoveType = (EffectMoveType)EditorGUILayout.EnumPopup("特效移动类型", sd.effectMoveType);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.effectNum = EditorGUILayout.IntField("特效数量", sd.effectNum);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.effectCD = EditorGUILayout.FloatField("特效间隔时间", sd.effectCD);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.castingDistance = EditorGUILayout.FloatField("施法距离", sd.castingDistance);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("选择结束特效");
endEffect = EditorGUILayout.ObjectField(endEffect, typeof(GameObject), false) as GameObject;
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
sd.skillCD = EditorGUILayout.FloatField("技能释放间隔时间", sd.skillCD);
GUILayout.EndHorizontal();
//保存按钮
if (GUILayout.Button("保存"))
{
sd.beginEffectPos = new V3(pos.x, pos.y, pos.z);
string aniPath = AssetDatabase.GetAssetPath(anim);
sd.skillAnimPath = GetPath(aniPath);
string skillPath = AssetDatabase.GetAssetPath(skillEffect);
sd.skillEffectPath = GetPath(skillPath);
string effectPath = AssetDatabase.GetAssetPath(endEffect);
sd.endEffectPath = GetPath(effectPath);
//保存数据 写入json文件
list.Add(sd);
string json = JsonConvert.SerializeObject(list);
File.WriteAllText(Application.dataPath + "/Resources/SkillData.json", json);
//刷新
AssetDatabase.Refresh();
}
//结束纵向排序
GUILayout.EndVertical();
}
具体效果展示
(四)获取所需资源的路径
/// <summary>
/// 获取图片名
/// </summary>
/// <param name="path">完整路径</param>
/// <returns>图片名</returns>
public string GetIconPath(string path)
{
string[] arr = path.Split('/');
string name = arr[arr.Length - 1].Split('.')[0];
return name;
}
/// <summary>
/// 获取文件名
/// </summary>
/// <param name="path">完整路径</param>
/// <returns>文件名</returns>
public string GetPath(string path)
{
string str = "Assets/Resources/";
string p = path.Substring(str.Length);
//Debug.Log(p);
string[] arr = p.Split(".");
//Debug.Log(arr[0]);
return arr[0];
}
生成的配置文件如下
三、完整效果展示
简单版技能编辑器效果展示