unity自动添加宏定义工具(使用逻辑位运算)

article/2025/8/18 23:38:04

背景:

在游戏开发中不免需要加一些我们自己的功能宏定义比如DebugMod开发模式宏 方便进行gm开发,或者一些debugtool的开发,开发者一定要重视debugTool的开发

不然会面临很多测试上的难题,比如某个流程很长的功能一轮测试下来可能就要几分钟。

主类很简单其他忽略 但是我这边定义了一个逻辑位 DefineBit 这里主要可以学习到逻辑位操作的技巧。点击开启宏之后等待工程编译(使用接口CompilationPipeline.RequestScriptCompilation())

等菊花转完之后就好了,同时之前显示的开启宏会变为关闭宏 ,再次点击按钮取消该宏定义,点击关闭所有宏定义会取消所有defineArray数组定义的所有宏

1.main.cs

public class Main : MonoBehaviour
{#if UNITY_EDITORpublic int DefineBit; 
#endif
}

2.编辑器类MainEditor.cs

using System;
using System.IO;
using Launcher;
using Runtime.Core.Constants;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
using Application = UnityEngine.Application;
[CustomEditor(typeof(Main))]
public class MainEditor : Editor
{
bool SymbleDefine = true;
string[] defineArray = new string[]
{"",    "DebugMod","FRUIT_DEBUG","DEV_DEBUG_NET", // 网络调试   "VIP_DEBUG", // 测试vip   "UNITASK_DOTWEEN_SUPPORT", // DoTween UniTask"HOT_UPDATE_TEST", // 测试热更新   "DELIVERY_DEV_1_1_3",// 分包开发 "DEBUG_REDPACK",    "REMOTE_DEBUG", // 远程测试  "TEST_INPUT" , // 测试输入系统 "TEST_WELCOMEUI" , // 测试欢迎界面 "TEST_RANKMATCHEX" , // 测试排位赛"DEV_MODE",
};public BuildTarget buildTarget
{get{#if UNITY_ANDROIDreturn  BuildTarget.Android;#elif UNITY_WEBGLreturn BuildTarget.WebGL;#elif UNITY_STANDALONEreturn BuildTarget.StandaloneWindows;#endif}
}
private void OnEnable()
{int nBit = 0;if(defineArray.Length >= 32){Debug.LogError("警告位已经不够用了");}for(int i = 0; i < defineArray.Length; i++){if (string.IsNullOrEmpty(defineArray[i])) continue;if(EasyUseEditorFuns.HasDebugSymble(buildTarget,defineArray[i])){nBit |=  GetBit(nBit, i);}   }(target as Main).DefineBit = nBit;//c# read json }static int GetBit(int number, int bitPosition)
{// 检查位是否有效if (bitPosition < 0 || bitPosition >= sizeof(int) * 8){throw new ArgumentOutOfRangeException(nameof(bitPosition), "位位置无效");}// 生成掩码:将 1 左移 bitPosition 位,然后取反int mask = (1 << bitPosition);// 使用按位与操作干掉指定位return number | mask;
}
static int ClearBit(int number, int bitPosition)
{// 检查位是否有效if (bitPosition < 0 || bitPosition >= sizeof(int) * 8){throw new ArgumentOutOfRangeException(nameof(bitPosition), "位位置无效");}// 生成掩码:将 1 左移 bitPosition 位,然后取反int mask = ~(1 << bitPosition);// 使用按位与操作干掉指定位return number & mask;
}static bool HasBit(int number, int bitPosition)
{// 检查位是否有效if (bitPosition < 0 || bitPosition >= sizeof(int) * 8){throw new ArgumentOutOfRangeException(nameof(bitPosition), "位位置无效");}// 判断指定位是否为 1return (number & (1 << bitPosition)) != 0;
}
public override void OnInspectorGUI()
{base.OnInspectorGUI();GUILayout.BeginHorizontal();if(!Application.isPlaying &&  GUILayout.Button("启动", GUILayout.Height(50)) || Application.isPlaying && GUILayout.Button("退出", GUILayout.Height(50))){EditorBuildSettingsScene[] tempScenes = new UnityEditor.EditorBuildSettingsScene[1];tempScenes[0] = new EditorBuildSettingsScene("Assets/scenes/GameStart.unity", true);EditorBuildSettings.scenes = tempScenes;if (!Application.isPlaying){EditorApplication.isPlaying = true;}else{EditorApplication.ExecuteMenuItem("Edit/Play");}}if(GUILayout.Button("暂停", GUILayout.Height(50))){EditorApplication.ExecuteMenuItem("Edit/Pause");}if(GUILayout.Button("编译c#", GUILayout.Height(50))){EditorUtility.RequestScriptReload();}GUILayout.EndHorizontal();GUILayout.BeginHorizontal();if (GUILayout.Button("打开c#",GUILayout.Height(50))){UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(System.Environment.CurrentDirectory + "/Assets/Launcher/Main.cs",1);//Application.OpenURL(System.Environment.CurrentDirectory +  "/Assets/Launcher/Main.cs");   }if (GUILayout.Button("移除monohook插件", GUILayout.Height(50))){if(Directory.Exists(Application.dataPath + "/MonoHook")){EasyUseEditorFuns.DelFolderAllContens(Application.dataPath + "/MonoHook", true);if(File.Exists(Application.dataPath + "/MonoHook.meta")){File.Delete(Application.dataPath + "/MonoHook.meta");}}AssetDatabase.Refresh();}GUILayout.EndHorizontal();Main global = target as Main;SymbleDefine = EditorGUILayout.Foldout(SymbleDefine, new GUIContent("宏定义"));if (SymbleDefine){if(GUILayout.Button("关闭所有宏定义")){for (int i = 1; i < defineArray.Length; i++){if (global && HasBit(global.DefineBit, i)){global.DefineBit = ClearBit(global.DefineBit, i);EasyUseEditorFuns.SetUnitySymbleDefine(buildTarget, false, defineArray[i]);}}AssetDatabase.Refresh();//重新编译整个c#代码 CompilationPipeline.RequestScriptCompilation();}for(int i = 1; i < defineArray.Length; i++){if (global && HasBit(global.DefineBit, i) && GUILayout.Button($"关闭宏{defineArray[i]}")){global.DefineBit = ClearBit(global.DefineBit, i);EasyUseEditorFuns.SetUnitySymbleDefine(buildTarget, false, defineArray[i]);CompilationPipeline.RequestScriptCompilation();}if (global && !HasBit(global.DefineBit, i) && GUILayout.Button($"开启宏{defineArray[i]}")){global.DefineBit = GetBit(global.DefineBit, i);EasyUseEditorFuns.SetUnitySymbleDefine(buildTarget,true, defineArray[i]);CompilationPipeline.RequestScriptCompilation();}}}
}
}

 

EasyUseEditorFuns.cs

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System;
using System.Reflection;
using UnityEditor.Build;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor.SceneManagement;
using System.Linq;
using JetBrains.Annotations;
using GuideReplace;public static class EasyUseEditorFuns
{public static void SetUnitySymbleDefine(BuildTarget  target, bool isAddOrRemove, string symble){NamedBuildTarget nameBt;var symbles = GetScriptSymble(target,out nameBt);if (isAddOrRemove){if (!string.IsNullOrEmpty(symbles)){var symble_arr = symbles.Split(';');if (Array.IndexOf(symble_arr, symble) < 0){symbles += $";{symble}";}}else{symbles = symble;}}else{if (!string.IsNullOrEmpty(symbles)){var symble_arr = symbles.Split(';');var index = Array.IndexOf(symble_arr, symble);if (index >= 0){if (index == symble_arr.Length - 1){symbles = index > 0 ? symbles.Replace($";{symble}", "") : symbles.Replace(symble, "");}else{symbles = symbles.Replace($"{symble};", "");}}}}PlayerSettings.SetScriptingDefineSymbols(nameBt, symbles);AssetDatabase.Refresh();}public static string GetScriptSymble(BuildTarget target,out NamedBuildTarget nameBt){string symbles = "";NamedBuildTarget nameBuildTarget;if (target == BuildTarget.iOS){nameBuildTarget = NamedBuildTarget.iOS;}else if (target == BuildTarget.Android){nameBuildTarget = NamedBuildTarget.Android;}else if (target == BuildTarget.WebGL){nameBuildTarget = NamedBuildTarget.WebGL;}else{nameBuildTarget = NamedBuildTarget.Standalone;}symbles = PlayerSettings.GetScriptingDefineSymbols(nameBuildTarget);nameBt = nameBuildTarget;return symbles;}
}


http://www.hkcw.cn/article/fobpbQsmmf.shtml

相关文章

网络摄像机POE交换机选型指南:技术参数与场景适配深度解析

在安防监控系统建设中&#xff0c;POE(Power over Ethernet)交换机作为核心设备&#xff0c;承担着数据传输与电力供应的双重职责。其选型质量直接影响系统稳定性、扩展性及维护成本。本文结合主流厂商技术标准与实际应用场景&#xff0c;从供电协议、端口配置、网络性能及管理…

田径亚锦赛中国队再获1金2银3铜 继续领跑金牌榜

2025年田径亚锦赛在韩国龟尾继续进行,中国队昨日再添1金2银3铜,以12枚金牌的成绩领跑金牌榜。女子铁饼决赛中,冯彬以61米90的成绩夺冠,实现亚锦赛三连冠。男子铅球决赛,邢家梁以19米97的成绩获得银牌。男子110米栏决赛,刘俊茜以13秒31的成绩摘得银牌,秦伟搏则获得铜牌。…

女子跳江轻生获救 救人男友溺亡 悲剧引发深思

女子跳江轻生获救 救人男友溺亡 悲剧引发深思。近日,一则关于南通江边情侣生死瞬间的视频在社交媒体上引发热议。经家属和救援队证实,轻生女子被救上岸,而施救男友却不幸身亡,令人痛心。网传画面显示,江边人声嘈杂,救援场面紧张揪心。据报道,救人小伙本身不谙水性。溺亡…

今年全球PC出货量有望超过2.7亿台 三季度出货量预计最多 全年增长显著

今年全球PC出货量有望超过2.7亿台 三季度出货量预计最多 全年增长显著!近一段时间,多家机构发布了关于智能手机、PC等消费电子产品一季度的出货量报告,涵盖了全球及中国、欧洲等多个市场的情况。除了披露一季度的数据外,一些市场研究机构还对全年的出货量进行了预测。据报道…

一声巨响,夜空都被照亮了!官方回应茂名疑似出现火流星

5月28日晚,多位网友发布视频称当日晚上21点33分左右,广东茂名天空出现疑似“陨石坠落”现象:爆闪强光瞬间点亮夜空,瞬间黑夜宛如白昼。(瞬间黑夜被照亮得宛如白天)有目击者称不久后听到一声巨响:“突然一声巨响,天都被照亮了。”随后,#茂名巨响##火流星##茂名流星#等话…

端午假期湖北有较强降水 强对流天气来袭

新一轮强对流天气即将来袭。武汉市气象台发布了端午假期的气象预警信息,预计从5月30日夜间到6月2日白天,湖北省将迎来一次较强降水过程,部分地区伴有强对流天气。武汉将有大雨至局地大暴雨。此次降雨正值端午假期期间,请大家加强防范,合理规划出行时间和路线。这是继5月22…

广东省省考备考(第二十四天5.29)—言语(听课后强化训练)

错题 解析 文段开篇引出中国进入互联网相关话题&#xff0c;交代中国互联网技术有了突出成就&#xff0c;形成新业态&#xff0c;通过转折关联词“但”&#xff0c;强调中国和世界先进水平相比存在差距。最后尾句通过“必须”对前文提出总结性对策&#xff0c;强调面对当前互联…

不起火,不爆炸,高速摄像机、数字图像相关DIC技术在动力电池新国标安全性能测试中的应用

2026年7月1日&#xff0c;我国将正式实施GB38031-2025《电动汽车用动力蓄电池安全要求》——这项被称为“史上最严电池安全令”的新国标&#xff0c;首次将“热失控不蔓延、不起火、不爆炸”从企业技术储备上升为强制性要求&#xff0c;标志着电池安全进入“零容忍”时代&#…

起猛了龙舟都能蹦迪了 广东人专属DISCO

5月26日晚,2025红旗社区夜龙巡游活动在佛山市顺德区容桂街道举行。11支来自各坊社的龙舟身披罗伞、旗帜、彩灯,在装扮一新后齐聚河涌巡游。在端午节前,顺德容桂的人们会在“起龙”后进行“醒龙”仪式。参与者通过特定动作转动龙头,如昂首、绕圈,象征“唤醒”老龙,赋予龙舟…

美国留学梦变噩梦 留学禁令下中国留美学生何去何从

赴美政策朝令夕改,让无数中国学生和家长陷入茫然与焦虑。在接受深圳卫视直新闻林舒琪采访时,正在申请赴美实习的中国学生张张表示,三四个月的努力,就这么付之东流了。他还表示,也有人寄希望于政策的反转,“美国人现在一天一个样”。责任编辑:zx0002

女子观赏海边奇景时意外失踪 搜寻未果引发关注

5月26日傍晚,23岁的孙女士在浙江台州温岭市松门镇海边的大坑沙村徒步时失踪。警方和救援人员在山上和海里进行了搜寻,但至29日上午仍未找到她。孙女士生于2002年,平时与父亲一起在宁波生活。5月26日,她告诉父亲自己出去玩,当晚不回家,随后乘列车去了温岭市,并独自来到大…

尊界挑得起豪华重任吗 豪车之路道阻且长

尊界挑得起豪华重任吗 豪车之路道阻且长。尊界S800历经三场发布会后正式发售。这款车搭载了六大智能化技术,包括途灵龙行平台、天使座主动安全防护系统、华为星河通信等。此外,还具备凌波微步功能,能在坑洼路面保持平稳。这些配置引发了不少网友的调侃,认为其命名方式颇具山…

【科研绘图系列】R语言绘制森林图(forest plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图系统信息介绍 本文介绍使用R语言绘制森林图(forest plot)的方法。首先加载必要的R包(grid、forestploter、openxlsx、stringr),导入并预处…

UA集成第三方插件

UA开发过程中常用其它第三方插件&#xff0c;如甘特图或echarts等来满足客户需求&#xff0c;以甘特图插件dhtmlxGantt.js为例&#xff1a; 1、将插件放到scripts文件夹中 2、将样式文件放到styles文件夹中 3、将js和样式放到 Installer/ExternalDepdencies文件夹中 4、页面中…

4. 算法与分析 (1)

本节主要讲了算法分析和算法度量标准&#xff08;时间复杂度&#xff09;。 本文部分ppt、视频截图来自&#xff1a;[青岛大学-王卓老师的个人空间-王卓老师个人主页-哔哩哔哩视频] 1. 算法 1.1 算法定义 算法是对特定问题求解方法和步骤的一种描述&#xff0c;它是指令的有限…

【C++】SDL2环境安装及AI编码简单的俄罗斯方块游戏

AI时代编码及文档功能 SDL2环境安装 Windows系统安装方法 下载SDL2开发库从官网&#xff08;https://www.libsdl.org/download-2.0.php&#xff09;&#xff0c;选择SDL2-devel-2.0.x-mingw.tar.gz&#xff08;MinGW&#xff09;或SDL2-devel-2.0.x-VC.zip&#xff08;Visual…

美国政府关税政策面临激烈的司法博弈 裁决引发贸易策略调整

美国国际贸易法院28日裁定特朗普政府的一揽子关税政策非法,称联邦法律并未赋予总统“无限制的权力”对来自几乎所有国家的进口商品征税。这是对美国本届政府关税政策的首次重大法律挑战。在这种情况下,美国政府将不得不采取更缓慢的策略,启动更耗时的贸易调查,并依靠其他贸…

【深度学习新浪潮】什么是混合精度分解?

混合精度分解是大模型压缩领域的一项核心技术,通过将模型参数或计算过程分解为不同精度的子单元,在保持性能的同时显著降低存储和计算成本。其核心思想是对模型中敏感度高、信息量大的部分采用高精度表示,而对冗余度高、敏感度低的部分采用低精度表示,从而在精度损失与压缩…

Arbitrary Response Filter Design and Analysis--任意响应滤波器设计与分析(待完成)

Create Desired Absorption Filter创建所需吸收滤波器 任务一 &#xff08;注意&#xff1a;函数 absorption是用户我&#xff0c;定义好的.m文件需要放在工作路径下才可调用&#xff09; 以下是我定义的函数 function alpha absorption(f) % ABSORPTION 计算海水中声波的…

t013-集团门户网站设计与实现 [基于springboot+Vue 含材料及源码]

项目演示视频 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装集团门户网站软件来发挥其高效地信息处理的作…