using System.IO; using System.Text.RegularExpressions; using System.Xml; using UnityEditor; using UnityEngine; namespace ET { public class OnGenerateCSProjectProcessor: AssetPostprocessor { /// /// 对生成的C#项目文件(.csproj)进行处理 /// 文档:https://learn.microsoft.com/zh-cn/visualstudio/gamedev/unity/extensibility/customize-project-files-created-by-vstu#%E6%A6%82%E8%A7%88 /// public static string OnGeneratedCSProject(string path, string content) { GlobalConfig globalConfig = Resources.Load("GlobalConfig"); // 判空原因:初次打开工程时会加载失败, 因为此时Unity的资源数据库(AssetDatabase)还未完成初始化 BuildType buildType = globalConfig != null? globalConfig.BuildType : BuildType.Release; if (buildType == BuildType.Release) { content = content.Replace("false", "true"); content = content.Replace(";DEBUG;", ";"); } if (path.EndsWith("Unity.Core.csproj")) { return GenerateCustomProject(content); } if (path.EndsWith("Unity.Model.csproj") || path.EndsWith("Unity.Hotfix.csproj")) { return AddCopyAfterBuild(GenerateCustomProject(content)); } if (path.EndsWith("Unity.ModelView.csproj") || path.EndsWith("Unity.HotfixView.csproj")) { return AddCopyAfterBuild(GenerateCustomProject(content)); } return content; } /// /// 对生成的解决方案文件(.sln)进行处理, 此处主要为了隐藏一些没有作用的C#项目 /// public static string OnGeneratedSlnSolution(string _, string content) { // Client content = HideCSProject(content, "Ignore.Generate.Client.csproj"); content = HideCSProject(content, "Ignore.Model.Client.csproj"); content = HideCSProject(content, "Ignore.Hotfix.Client.csproj"); content = HideCSProject(content, "Ignore.ModelView.Client.csproj"); content = HideCSProject(content, "Ignore.HotfixView.Client.csproj"); // Server content = HideCSProject(content, "Ignore.Generate.Server.csproj"); content = HideCSProject(content, "Ignore.Model.Server.csproj"); content = HideCSProject(content, "Ignore.Hotfix.Server.csproj"); // ClientServer content = HideCSProject(content, "Ignore.Generate.ClientServer.csproj"); return content; } /// /// 自定义C#项目配置 /// 参考链接: /// https://zhuanlan.zhihu.com/p/509046784 /// https://learn.microsoft.com/zh-cn/visualstudio/ide/reference/build-events-page-project-designer-csharp?view=vs-2022 /// https://learn.microsoft.com/zh-cn/visualstudio/ide/how-to-specify-build-events-csharp?view=vs-2022 /// static string GenerateCustomProject(string content) { XmlDocument doc = new(); doc.LoadXml(content); var newDoc = doc.Clone() as XmlDocument; var rootNode = newDoc.GetElementsByTagName("Project")[0]; // 添加分析器引用 { XmlElement itemGroup = newDoc.CreateElement("ItemGroup", newDoc.DocumentElement.NamespaceURI); var projectReference = newDoc.CreateElement("ProjectReference", newDoc.DocumentElement.NamespaceURI); projectReference.SetAttribute("Include", @"..\Share\Analyzer\Share.Analyzer.csproj"); projectReference.SetAttribute("OutputItemType", @"Analyzer"); projectReference.SetAttribute("ReferenceOutputAssembly", @"false"); var project = newDoc.CreateElement("Project", newDoc.DocumentElement.NamespaceURI); project.InnerText = @"{d1f2986b-b296-4a2d-8f12-be9f470014c3}"; projectReference.AppendChild(project); var name = newDoc.CreateElement("Name", newDoc.DocumentElement.NamespaceURI); name.InnerText = "Analyzer"; projectReference.AppendChild(name); itemGroup.AppendChild(projectReference); rootNode.AppendChild(itemGroup); } // AfterBuild(字符串替换后作用是编译后复制到CodeDir) { var target = newDoc.CreateElement("Target", newDoc.DocumentElement.NamespaceURI); target.SetAttribute("Name", "AfterBuild"); rootNode.AppendChild(target); } using StringWriter sw = new(); using XmlTextWriter tx = new(sw); tx.Formatting = Formatting.Indented; newDoc.WriteTo(tx); tx.Flush(); return sw.GetStringBuilder().ToString(); } /// /// 编译dll文件后额外复制的目录配置 /// static string AddCopyAfterBuild(string content) { return content.Replace("", "\n" + $" \n" + $" \n" + $" \n" + $" \n" + " \n"); } /// /// 隐藏指定项目 /// static string HideCSProject(string content, string projectName) { return Regex.Replace(content, $"Project.*{projectName}.*\nEndProject", string.Empty); } } }