前言
主要介绍框架是如何自动生成代码的,自动生成代码主要是为了addressable资源引用的。
结构
添加应用栏目录
在JKMenuItem这个脚本中添加2个按钮,“生成资源引用代码”“清理资源引用代码”,前提是要资源加载方式是addressable下
#if ENABLE_ADDRESSABLES
[MenuItem("JKFrame/生成资源引用代码")]
public static void GenerateResReferenceCode()
{
GenerateResReferenceCodeTool.GenerateResReferenceCode();
}
[MenuItem("JKFrame/清理资源引用代码")]
public static void CleanResReferenceCode()
{
GenerateResReferenceCodeTool.CleanResReferenceCode();
}
#endif
方法实现
主要是GenerateResReferenceCodeTool这个脚本,是实现自动生成代码的。
创建脚本的模板
private static string fileStr =
@"using UnityEngine;
using UnityEngine.UI;
using UnityEditor.Animations;
using System;
using UnityEngine.Playables;
using JKFrame;
namespace R
{
~~成员~~
}";
成员-就是脚本的内容
接下来创建几个模板:类模板,属性模板,子资产属性-模板,获取GameObject方法-模板
//类-模板
private static string classTemplate =
@"
public static class ##类名##
{
~~成员~~
}";
//属性-模板
private static string PropertyTemplate =
@"
public static ##类型## ##资源名称## { get => ResSystem.LoadAsset<##类型##>(""##资源路径##""); }";
//子资产属性-模板
private static string SubAssetPropertyTemplate =
@"
public static ##类型## ##资源名称## { get => ResSystem.LoadAsset<##类型##>(""##资源路径##""); }";
//获取GameObject方法-模板
private static string GameObjectPropertyTemplate =
@"
public static GameObject ##资源名称##_GameObject(Transform parent = null,string keyName=null,bool autoRelease = true)
{
return ResSystem.InstantiateGameObject(""##资源路径##"", parent, keyName,autoRelease);
}";
清除生成的资源代码方法
删除文件,refresh资源
public static void CleanResReferenceCode()
{
if (File.Exists(scriptPath))
{
File.Delete(scriptPath);
AssetDatabase.Refresh();
}
Debug.Log("清除资源代码脚本成功");
}
生成资源代码方法
创建文件
获取addressable的全部group
更改之前创建的脚本模板
写入文件
保存,关闭
public static void GenerateResReferenceCode()
{
// 开始生成
Debug.Log("开始生成资源代码");
//.cs文件如果已经存在,先删除
if (File.Exists(scriptPath)) File.Delete(scriptPath);
FileStream file = new FileStream(scriptPath, FileMode.CreateNew);
StreamWriter fileW = new StreamWriter(file, System.Text.Encoding.UTF8);
// 获取全部Addressable的Group
string groupsStr = "";
AddressableAssetSettings assets = AddressableAssetSettingsDefaultObject.Settings;
foreach (AddressableAssetGroup group in assets.groups)
{
if (group.name == "Built In Data") continue;
string name = group.name.Replace(" ", ""); // 去除空格
// 建立子类名称
string groupStr = classTemplate.Replace("##类名##", name);
// 找到子类全部资源以及类型
List<AddressableAssetEntry> allAssetEntry = new List<AddressableAssetEntry>();
group.GatherAllAssets(allAssetEntry, true, true, true);
string propertyStrs = ""; // 属性的字符串
for (int i = 0; i < allAssetEntry.Count; i++)
{
AddressableAssetEntry assetItem = allAssetEntry[i];
if (assetItem.IsSubAsset) // sub资源主要存在[]无法生成class
{
string subAssetPropertyStr = SubAssetPropertyTemplate.Replace("##类型##", assetItem.MainAssetType.Name);
string assetName = assetItem.address.Replace("[", "_").Replace("]", ""); // 去除子资源中的括号
subAssetPropertyStr = subAssetPropertyStr.Replace("##资源名称##", assetName.Replace(" ", ""));
subAssetPropertyStr = subAssetPropertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += subAssetPropertyStr;
}
else
{
string propertyStr = PropertyTemplate.Replace("##类型##", assetItem.MainAssetType.Name);
propertyStr = propertyStr.Replace("##资源名称##", assetItem.address.Replace(" ", ""));
propertyStr = propertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += propertyStr;
if (assetItem.MainAssetType == typeof(GameObject)) // 游戏物体增加一个用于直接实例化的
{
string gameObjectPropertyStr = GameObjectPropertyTemplate.Replace("##资源名称##", assetItem.address.Replace(" ", ""));
gameObjectPropertyStr = gameObjectPropertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += gameObjectPropertyStr;
}
}
}
groupStr = groupStr.Replace("~~成员~~", propertyStrs);
groupsStr += groupStr;
}
fileStr = fileStr.Replace("~~成员~~", groupsStr);
fileW.Write(fileStr);
fileW.Flush();
fileW.Close();
file.Close();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
// 结束生成
Debug.Log("生成资源代码成功");
}
源码
#if ENABLE_ADDRESSABLES
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
public static class GenerateResReferenceCodeTool
{
static string scriptPath = Application.dataPath + "/JKFrame/R.cs";
private static string fileStr =
@"using UnityEngine;
using UnityEngine.UI;
using UnityEditor.Animations;
using System;
using UnityEngine.Playables;
using JKFrame;
namespace R
{
~~成员~~
}";
//类-模板
private static string classTemplate =
@"
public static class ##类名##
{
~~成员~~
}";
//属性-模板
private static string PropertyTemplate =
@"
public static ##类型## ##资源名称## { get => ResSystem.LoadAsset<##类型##>(""##资源路径##""); }";
//子资产属性-模板
private static string SubAssetPropertyTemplate =
@"
public static ##类型## ##资源名称## { get => ResSystem.LoadAsset<##类型##>(""##资源路径##""); }";
//获取GameObject方法-模板
private static string GameObjectPropertyTemplate =
@"
public static GameObject ##资源名称##_GameObject(Transform parent = null,string keyName=null,bool autoRelease = true)
{
return ResSystem.InstantiateGameObject(""##资源路径##"", parent, keyName,autoRelease);
}";
/// <summary>
/// 清除资源代码脚本
/// </summary>
public static void CleanResReferenceCode()
{
if (File.Exists(scriptPath))
{
File.Delete(scriptPath);
AssetDatabase.Refresh();
}
Debug.Log("清除资源代码脚本成功");
}
/// <summary>
/// 生成资源代码脚本
/// </summary>
public static void GenerateResReferenceCode()
{
// 开始生成
Debug.Log("开始生成资源代码");
//.cs文件如果已经存在,先删除
if (File.Exists(scriptPath)) File.Delete(scriptPath);
FileStream file = new FileStream(scriptPath, FileMode.CreateNew);
StreamWriter fileW = new StreamWriter(file, System.Text.Encoding.UTF8);
// 获取全部Addressable的Group
string groupsStr = "";
AddressableAssetSettings assets = AddressableAssetSettingsDefaultObject.Settings;
foreach (AddressableAssetGroup group in assets.groups)
{
if (group.name == "Built In Data") continue;
string name = group.name.Replace(" ", ""); // 去除空格
// 建立子类名称
string groupStr = classTemplate.Replace("##类名##", name);
// 找到子类全部资源以及类型
List<AddressableAssetEntry> allAssetEntry = new List<AddressableAssetEntry>();
group.GatherAllAssets(allAssetEntry, true, true, true);
string propertyStrs = ""; // 属性的字符串
for (int i = 0; i < allAssetEntry.Count; i++)
{
AddressableAssetEntry assetItem = allAssetEntry[i];
if (assetItem.IsSubAsset) // sub资源主要存在[]无法生成class
{
string subAssetPropertyStr = SubAssetPropertyTemplate.Replace("##类型##", assetItem.MainAssetType.Name);
string assetName = assetItem.address.Replace("[", "_").Replace("]", ""); // 去除子资源中的括号
subAssetPropertyStr = subAssetPropertyStr.Replace("##资源名称##", assetName.Replace(" ", ""));
subAssetPropertyStr = subAssetPropertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += subAssetPropertyStr;
}
else
{
string propertyStr = PropertyTemplate.Replace("##类型##", assetItem.MainAssetType.Name);
propertyStr = propertyStr.Replace("##资源名称##", assetItem.address.Replace(" ", ""));
propertyStr = propertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += propertyStr;
if (assetItem.MainAssetType == typeof(GameObject)) // 游戏物体增加一个用于直接实例化的
{
string gameObjectPropertyStr = GameObjectPropertyTemplate.Replace("##资源名称##", assetItem.address.Replace(" ", ""));
gameObjectPropertyStr = gameObjectPropertyStr.Replace("##资源路径##", assetItem.address);
propertyStrs += gameObjectPropertyStr;
}
}
}
groupStr = groupStr.Replace("~~成员~~", propertyStrs);
groupsStr += groupStr;
}
fileStr = fileStr.Replace("~~成员~~", groupsStr);
fileW.Write(fileStr);
fileW.Flush();
fileW.Close();
file.Close();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
// 结束生成
Debug.Log("生成资源代码成功");
}
}
#endif