写代码写的时间长了,会经常写一些重复的东西,这些代码枯燥,乏味,浪费时间,没什么营养。想着能不能用一些工具帮我自动生成。想了半天,终于有了自己想要的效果。
这项工程的源代码,供大家进行下载参考:
https://download.csdn.net/download/liulei199079/10745835
先看看操作
等编译完了,然后执行如下操作
看,从事件注册到字段序列化,点两下就可以自动完成。是不是很方便。另外还同时支持事件的删除。
实现思路:
1:获取相关的脚本
Type type = GetType(FindGenerateCodeScript(obj.transform));
MonoBehaviour monoBehaviour = obj.GetComponentInParent(type) as MonoBehaviour;
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoBehaviour);
2:对该脚本进行格式化
static string AutoFormatCode(string orignal_code,bool is_contain_namespace)
{
string common_tab_char = is_contain_namespace ? "\t\t" : "\t";
if (!orignal_code.Contains(AutoCSharpConfig.auto_generate_code_split_start))
{
if(!orignal_code.StartsWith("#if UNITY_EDITOR"))
{
if(!orignal_code.Contains("using Newtonsoft.Json;"))
{
orignal_code = "using Newtonsoft.Json;\n"+orignal_code;
}
if(!orignal_code.Contains("using System.Reflection;"))
{
orignal_code = "using System.Reflection;\n"+orignal_code;
}
if(!orignal_code.Contains("using UnityEngine;"))
{
orignal_code = "using UnityEngine;\n" + orignal_code;
}
if(!orignal_code.Contains("using System;"))
{
orignal_code = "using System;" + orignal_code;
}
if(!orignal_code.Contains("using System.Collections.Generic;"))
{
orignal_code = "using System.Collections.Generic;" + orignal_code;
}
orignal_code = "#if UNITY_EDITOR\nusing UnityEditor;\n#endif\n"+orignal_code;
}
orignal_code = orignal_code.Remove(orignal_code.LastIndexOf('}'));
if (is_contain_namespace)
{
orignal_code = orignal_code.Remove(orignal_code.LastIndexOf('}'));
}
if(!orignal_code.Contains("void Awake()"))//注入Awake方法
{
foreach(string s in AutoCSharpConfig.auto_generate_code_awake_func_codes_model)
{
orignal_code += "\n" + common_tab_char + s;
}
}
foreach (string s in AutoCSharpConfig.auto_generate_codes)
{
orignal_code += "\n" + common_tab_char + s;
}
//orignal_code += "\n"+common_tab_char + AutoCSharpConfig.auto_generate_code_split_start + "\n"+common_tab_char + AutoCSharpConfig.auto_region_start + "\n"+common_tab_char + AutoCSharpConfig.auto_region_end + "\n"+common_tab_char + AutoCSharpConfig.auto_generate_code_split_end +"\n\t"+ "}";
if (is_contain_namespace)
{
orignal_code += "\n\t" + "}";
}
orignal_code += "\n}";
if (!orignal_code.Contains(AutoCSharpConfig.auto_generate_code_register_func_start))
{
orignal_code = orignal_code.Replace(AutoCSharpConfig.auto_generate_code_event_func_start, AutoCSharpConfig.auto_generate_code_event_func_start + "\n" + common_tab_char + GetRegisterCode(is_contain_namespace));
}
if(!orignal_code.Contains(AutoCSharpConfig.auto_generate_code_serialized_field_codes_model[0]))
{
string serialzed_field_code = string.Empty;
foreach (string s in AutoCSharpConfig.auto_generate_code_serialized_field_codes_model)
{
//if(s == AutoCSharpConfig.auto_generate_code_serialized_field_codes_model[0])
//{
// serialzed_field_code += s;
//}
//else
//{
serialzed_field_code += "\n" + common_tab_char + s;
//}
}
orignal_code = orignal_code.Replace(AutoCSharpConfig.auto_generate_code_event_func_end, AutoCSharpConfig.auto_generate_code_event_func_end + serialzed_field_code);
}
}
if (!orignal_code.Contains(AutoCSharpConfig.auto_generate_code_init_awake_func_model))//往Awake注入 初始化方法
{
string[] split_str = orignal_code.Split(new string[] { "void Awake()" }, StringSplitOptions.RemoveEmptyEntries);
orignal_code = split_str[0].TrimEnd() + " void Awake()" + "\n" + common_tab_char + "{\n\t" + common_tab_char + AutoCSharpConfig.auto_generate_code_init_awake_func_model + split_str[1].TrimStart().Remove(0, 1);
}
return orignal_code;
}
3:然后对该脚本代码进行修改
[MenuItem("GameObject/LazerSelect/AddPressEvent", false, 0)]
[MenuItem("LazerSelect/CSharp/AddPressEvent")]
static private void AddGameObjectPressEvent()
{
GameObject obj = Selection.gameObjects[0];
//Debug.Log(MonoScript.FromMonoBehaviour(obj.GetComponentInParent<FatherScript>()).text);
Type type = GetType(FindGenerateCodeScript(obj.transform));
MonoBehaviour monoBehaviour = obj.GetComponentInParent(type) as MonoBehaviour;//obj.GetComponentInParent<FatherScript>();
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoBehaviour);
//添加字段
string orignal_code = monoScript.text;
bool is_contain_namespace = orignal_code.Contains("namespace");
string common_tab_char = is_contain_namespace ? "\t\t" : "\t";
//添加自动生成代码区域标记
orignal_code = AutoFormatCode(orignal_code, is_contain_namespace);
//生成字段
string private_field_code = string.Format(AutoCSharpConfig.auto_generate_code_filed_model, obj.name, JsonConvert.SerializeObject(new { name = "m_" + obj.name, path = GetPath(obj.transform, monoBehaviour.transform) }));
if (!orignal_code.Contains(private_field_code))
{
orignal_code = orignal_code.Replace(AutoCSharpConfig.auto_generate_code_field_end, private_field_code + "\n" + common_tab_char + AutoCSharpConfig.auto_generate_code_field_end);
}
//生成方法
if (!orignal_code.Contains(string.Format("private void on_{0}_button_press(GameObject obj,bool pressed)", obj.name)))
{
string event_func_code = GetPressFuncCode(obj.name, is_contain_namespace);
orignal_code = orignal_code.Replace(AutoCSharpConfig.auto_generate_code_event_func_end, event_func_code + "\n" + common_tab_char + AutoCSharpConfig.auto_generate_code_event_func_end);
}
//注册方法
string register_click_code = string.Format(AutoCSharpConfig.auto_generate_code_register_onpress_func_model, obj.name);
if (!orignal_code.Contains(register_click_code))
{
orignal_code = orignal_code.Replace(AutoCSharpConfig.auto_generate_code_register_func_end, register_click_code + "\n\t" + common_tab_char + AutoCSharpConfig.auto_generate_code_register_func_end);
}
string path = AssetDatabase.GetAssetPath(monoScript);
File.WriteAllText(System.IO.Path.GetFullPath(path), orignal_code, System.Text.Encoding.UTF8);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
monoBehaviour = obj.GetComponentInParent(type) as MonoBehaviour;
//UnityEditor.EditorUtility.SetDirty(monoBehaviour.gameObject);
//monoBehaviour.GetType().InvokeMember("m_" + obj.name, BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic, null, monoBehaviour, new object[] { obj }, null, null, null);
}
这些操作本质上就是对修改的脚本进行文本编辑,目前还没有找到像vs那样提供丰富的加接口,删接口那样高度自动化的方法。
但使用这些方法已经完全可以对脚本进行无缝的编辑了。
我提供了注册该脚本的相关模板,方便大家在此基础上修改
public class AutoCSharpConfig
{
public static readonly List<string> auto_generate_codes = new List<string>()
{
"/*************************auto generate code start***********************/",
"#region auto generate code",
"/*************************auto generate code field start***********************/",
"/*************************auto generate code field end***********************/",
auto_generate_code_event_func_start,
auto_generate_code_event_func_end,
"#endregion",
"/*************************auto generate code end***********************/",
};
//自动生成代码起始
public const string auto_generate_code_split_start = "/*************************auto generate code start***********************/";
public const string auto_region_start = "#region auto generate code";
public const string auto_generate_code_field_start = "/*************************auto generate code field start***********************/";
public const string auto_generate_code_field_end = "/*************************auto generate code field end***********************/";
public const string auto_generate_code_event_func_start = "/*************************auto generate code event func start***********************/";
public const string auto_generate_code_event_func_end = "/*************************auto generate code event func end***********************/";
public const string auto_generate_code_register_func_start = "/*************************auto generate code register func start***********************/";
public const string auto_generate_code_register_func_end = "/*************************auto generate code register func end***********************/";
public const string auto_region_end = "#endregion";
//public const string auto_generate_code_serialized_field_config_json_start = "/*************************auto generate code serialized field config json start***********************/";
//public const string auto_generate_code_serialized_field_config_json_end = "/*************************auto generate code serialized field config json end***********************/";
//自动生成代码结束
public const string auto_generate_code_split_end = "/*************************auto generate code end***********************/";
public const string auto_generate_code_filed_model = "[SerializeField] private GameObject m_{0};//{1}[-]";
public const string auto_generate_code_register_onclick_func_model = "UIEventListener.Get(m_{0}).onClick = on_{0}_button_click;";
public const string auto_generate_code_register_onpress_func_model = "UIEventListener.Get(m_{0}).onPress = on_{0}_button_press;";
public const string auto_generate_code_click_func_flag_start_model = "//---------------------function :{0} click func start---------------";
public const string auto_generate_code_click_func_flag_end_model = "//---------------------function :{0} click func end---------------";
public const string auto_generate_code_press_func_flag_start_model = "//---------------------function :{0} press func start---------------";
public const string auto_generate_code_press_func_flag_end_model = "//---------------------function :{0} press func end---------------";
public const string auto_generate_code_init_awake_func_model = "RegisterButtonEvent();";
public static List<string> auto_generate_code_awake_func_codes_model = new List<string>()
{
"//此方法不能删掉",
"private void Awake()",
"{",
"\t"+auto_generate_code_init_awake_func_model,
"}",
};
public static List<string> auto_generate_code_serialized_field_codes_model = new List<string>(){
"/*************************auto generate code serialized field start***********************/",
"#if UNITY_EDITOR",
"[ContextMenu(\"序列化字段\")]",
"private void AutoSerializedField()",
"{",
"\tEditorUtility.SetDirty(this);",
"\tMonoBehaviour monoBehaviour = this;",
"\tMonoScript monoScript = MonoScript.FromMonoBehaviour(monoBehaviour);",
"\tstring orignal_code = monoScript.text.Split(new string[] { AutoCSharpConfig.auto_generate_code_field_start, AutoCSharpConfig.auto_generate_code_field_end }, StringSplitOptions.RemoveEmptyEntries)[1];",
"\tstring[] codes = orignal_code.Split(new string[] { \"//\", \"[-]\" }, StringSplitOptions.RemoveEmptyEntries);",
"\tfor (int i = 0; i < codes.Length; i++)",
"\t{",
"\t\tif (codes[i].Contains(\"\\\"path\\\":\"))",
"\t\t{",
"\t\t\tDictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(codes[i]);",
"\t\t\tmonoBehaviour.GetType().InvokeMember(dict[\"name\"], BindingFlags.SetField | BindingFlags.Instance | BindingFlags.NonPublic, null, monoBehaviour, new object[] { monoBehaviour.transform.Find(dict[\"path\"]).gameObject }, null, null, null);",
"\t\t}",
"\t}",
"\tEditorUtility.SetDirty(this);",
"}",
"#endif",
"/*************************auto generate code serialized field end***********************/",
};
}