想了很多方法,最后形成了一个初步的想法,主要思想是,在需要生成的UI上添加一个GenerateUIViewBase,作为控制这个整个View的生成,然后在它的子物体上添加GenerateUIViewItem,添加每个Item的属性,控制每个Item的行为。
生成代码需要解决下边几个问题:
一、需要添加删除base和item这些脚本。
因为这些生成和辅助生成代码的脚本是项目预制上不需要的,所以需要在代码中控制代码的添加和删除。
(等以后改良一下,不用添加脚本这个方法。)
///
/// 添加脚本
///
public static T AddScript(GameObject go) where T : MonoBehaviour
{
MonoBehaviour _script = go.GetComponent();
if (_script == null)
{
_script = go.AddComponent();
}
return _script as T;
}
///
/// 删除脚本
///
public static void RemoveScript(GameObject go) where T : MonoBehaviour
{
MonoBehaviour _script = go.GetComponent();
if (_script != null)
{
DestroyImmediate(_script);// 编辑模式下不能使用Destroy
}
}
二、需要知道每个item上需要生成的组件列表。
首先,没有新建窗口,就需要扩展一下Base和Item在Inspector上的显示,添加一些功能按钮和显示信息。做了一个示例:
Base的Inspector面板:
Item的Inspector面板:
本来想贴代码的,但是代码写的不怎么美,只是匆忙的实现了功能,比较杂乱。所以这里说一下主要的思想吧,主要思想是:
1、在需要生成代码的UI界面上添加Base脚本
BaseEditor中写了四个功能按钮,通过模板生成代码(生成代码按钮)、更新路径(新添加的GameObject时可能没有Item脚本,改变Item层级之后需要更新路径)、添加item(添加Item脚本)、删除Item(Item脚本)
2、添加Item按钮
会将Item 添加到所有未隐藏的GameObject上(应该改一下,隐藏的也应该添加Item),Item上显示该GameObject到Base的路径和路径输入框,变量名和变量名输入框,组件Toggle(既要显示全部组件,还要显示已选择的组件,想用Button的Inspector面板上OnClick添加事件那种方式,没有找到,就用Toggle了)。
将当前Item 的信息用一个ItemData(路径,变量名,组件列表)存起来,然后将组件列表(就是勾选了Toggle的)这些ItemData存到Base的字典中(以变量名做为key),如果有同名的变量,Log提示。
3、同一个Item 有多个组件(组件列表长度大于1)
如果一个GameObject需要查找多个组件,变量名根据组件添加后缀,比如GameObject添加GO,Transform添加Tran,看个人习惯。
4、点击生成代码按钮
根据存在Base字典中的信息生成代码,之前的版本是将只生成变量声明和组件查找两个部分,后来通过模板之后,先创建一个通用模板Template,和VisualStudio的模板差不多(根据自己的需求修改),然后代码根据字典内容组装类名,变量声明,组件查找,几个部分,替换到模板里面去。
5、点击删除Item
删除item,Base,将生成的代码拷贝到项目中去(没有做路径输出,输出路径写在Base的filepath中的)。
三、需要对文件的读写。
直接贴代码吧,网上应该有很多Unity读写Txt的帖子。(本来不应该这么多代码的,有空整理一下代码)
public void WriteFileWithTemplate(string path)
{
//读
StreamReader _testReader = new StreamReader(TemplatePath, Encoding.Default);
string _text = _testReader.ReadToEnd();
string _scriptName = Selection.activeGameObject.name;
string _componentVariabelName = string.Empty;
string _getComponent = string.Empty;
foreach (var item in m_itemDic)
{
GenerateUIViewItemData _data = item.Value;
for (int i = 0; i < _data.GenerateComponentList.Count; i++)
{
string _variavleName = GenerateUIViewUtils.GetVariableNameByType(_data.GenerateComponentList[i], _data.VariableName);
string _varStr = string.Format(m_getVarStr, _data.GenerateComponentList[i].ToString(), _variavleName);
string _path = "";
string _parentStr = m_parentTranStr;
if (GenerateUIViewUtils.IsUseGameObjectStr(_data.GenerateComponentList[i]))
{
_parentStr = m_parentGoStr;
}
if (GenerateUIViewUtils.IsUseGenericityStr(_data.GenerateComponentList[i]))
{
_path = string.Format(m_getPathGenericityStr, _variavleName, _data.GenerateComponentList[i].ToString(), _parentStr, _data.Path);
}
else
{
_path = string.Format(m_getPathStr, _variavleName, _parentStr, _data.Path);
}
_componentVariabelName += _varStr+"\n";
_getComponent += _path + "\n";
}
}
_text = _text.Replace("$safeitemrootname$", _scriptName);
_text = _text.Replace("$componentvariablename$", _componentVariabelName);
_text =_text.Replace("$getcomponent$", _getComponent);
_testReader.Close();
//写
FileStream _fs = new FileStream(path, FileMode.OpenOrCreate);
StreamWriter _textWriter = new StreamWriter(_fs,Encoding.Default);
_textWriter.Write(_text);
_textWriter.Flush();
_textWriter.Close();
_fs.Close();
Debug.Log("代码生成成功!");
}
写的不好请见谅,如果有还有什么不好的地方,欢迎指正,如果有什么好的方法,可以提出来讨论。
代码和template文件:
链接:https://pan.baidu.com/s/1AXEwx9wphnTlaTekiOA3gA
提取码:2tu4