十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unity基础:public变量与Inspector面板——脚本与编辑器的数据交互

Unity基础:public变量与Inspector面板——脚本与编辑器的数据交互 Unity基础public变量与Inspector面板——脚本与编辑器的数据交互大家好欢迎回到Unity教程系列。前面我们写了不少脚本也注意到在脚本中使用public关键字声明的变量会自动出现在Inspector面板中。今天这篇文章我们要深入理解代码和Inspector之间的数据交互机制。这个机制是Unity开发工作流的核心之一——它让策划和美术可以在不修改代码的情况下调整游戏参数让脚本变得灵活可配置。理解了这套机制你就能写出既强大又好用的脚本组件。一、变量如何在Inspector中显示1.1 序列化Serialization Unity编辑器能够识别和保存脚本中的变量靠的是一种叫做序列化的机制。序列化就是把内存中的对象转换为可存储的格式如二进制数据反序列化则是逆过程。Unity自动序列化以下类型的变量并在Inspector中显示public访问修饰符的变量标记了[SerializeField]特性的private变量1.2 public变量自动显示publicclassPlayerSettings:MonoBehaviour{// 以下所有public变量都会在Inspector中显示publicfloatmoveSpeed5f;publicintmaxHealth100;publicstringplayerNamePlayer;publicboolcanFlyfalse;publicGameObjectprojectilePrefab;publicTransformspawnPoint;publicColorplayerColorColor.white;publicVector3spawnPositionVector3.zero;}1.3 [SerializeField]——private变量也能在Inspector中显示使用public暴露变量有一个问题破坏了封装性。其他类可以不经控制地修改这些变量。更好的做法是使用private [SerializeField]usingUnityEngine;publicclassPlayerSettings:MonoBehaviour{// private变量 SerializeField 在Inspector可见但外部代码不可直接访问[SerializeField]privatefloatmoveSpeed5f;[SerializeField]privateintmaxHealth100;[SerializeField]privateGameObjectprojectilePrefab;// 如果外部需要读取提供public的getterpublicfloatMoveSpeedmoveSpeed;publicintMaxHealthmaxHealth;} 我个人的习惯是大部分可配置的变量用private [SerializeField]只将确实需要被其他脚本直接访问的变量设为public。1.4 [HideInInspector]——隐藏public变量如果你想让一个public变量不被Inspector显示但保持对外的public访问使用[HideInInspector]// 这个变量是public的外部代码可访问但不在Inspector中显示[HideInInspector]publicintinternalId;二、可序列化的数据类型2.1 Unity可序列化的类型⚠️ 并非所有C#类型都能被Unity序列化。能被序列化并在Inspector中显示的类型包括基本类型int, float, doubleboolstringenum枚举Unity内置类型Vector2, Vector3, Vector4QuaternionColor, Color32Rect, RectIntBounds, BoundsIntLayerMaskAnimationCurveGradientGameObject, Transform, ComponentMaterial, Texture, Sprite, AudioClipScene通过SceneAssetScriptableObject集合类型数组T[]List需要using System.Collections.Generic2.2 不能序列化的类型以下类型不能在Inspector中显示Dictionary字典Stack栈、Queue队列HashSet自定义类除非标记[System.Serializable]接口类型抽象类多维数组T[,]2.3 让自定义类可序列化为自定义类添加[System.Serializable]特性usingSystem;usingUnityEngine;[System.Serializable]publicclassEnemyStats{publicstringenemyName;publicinthealth;publicfloatspeed;publicColorenemyColor;}publicclassEnemySpawner:MonoBehaviour{// 自定义可序列化类在Inspector中以折叠面板显示publicEnemyStatsbasicEnemyStats;publicEnemyStatseliteEnemyStats;}2.4 让字典在Inspector中可见虽然Unity原生不支持字典序列化但你可以通过以下方式变通实现usingSystem;usingSystem.Collections.Generic;usingUnityEngine;[System.Serializable]publicclassSerializableKeyValuePairTKey,TValue{publicTKeykey;publicTValuevalue;}publicclassDictionaryDisplay:MonoBehaviour{// 在Inspector中显示为键值对列表[SerializeField]privateListSerializableKeyValuePairstring,intconfigList;// 运行时转换为字典使用privateDictionarystring,intconfigDict;voidAwake(){configDictnewDictionarystring,int();foreach(varpairinconfigList){configDict[pair.key]pair.value;}}}三、Inspector美化特性3.1 [Header]——分组标题在Inspector中用标题分组变量让面板更加清晰publicclassPlayerController:MonoBehaviour{[Header(移动设置)]publicfloatwalkSpeed5f;publicfloatrunSpeed10f;publicfloatjumpForce8f;[Header(生命值设置)]publicintmaxHealth100;publicfloathealthRegenRate1f;[Header(攻击设置)]publicintattackDamage25;publicfloatattackRange2f;publicfloatattackCooldown0.5f;[Header(引用)]publicGameObjectweaponPrefab;publicTransformfirePoint;}3.2 [Range]——数值范围滑块用滑块替代数值输入框直观且防止输入非法值[Range(0f,10f)]publicfloatspeed5f;[Range(1,100)]publicintmaxHealth50;[Range(0f,1f)]publicfloatvolume0.8f;3.3 [Tooltip]——鼠标悬停提示添加提示文字帮助使用者理解变量的用途[Tooltip(角色的移动速度单位米/秒)]publicfloatmoveSpeed5f;[Tooltip(最大跳跃高度值越大跳得越高)][Range(1f,20f)]publicfloatjumpForce8f;3.4 [Space]——添加间距在Inspector中添加垂直间距以视觉方式分隔不同组的变量publicfloatmoveSpeed5f;publicfloatjumpForce8f;[Space(10)]// 添加10像素间距publicintmaxHealth100;[Space(20)]// 添加20像素间距publicGameObjectweaponPrefab;3.5 [TextArea]——多行文本输入[TextArea(3,10)]// 最小3行最大10行publicstringdescription在这里输入描述文字...;[TextArea]// 使用默认行数publicstringnotes;3.6 [Multiline]——多行字符串[Multiline(5)]// 5行高度的多行文本框publicstringdialogueText;3.7 [ColorUsage]——高级颜色选择器// 普通颜色publicColorplayerColor;// 支持HDR颜色亮度可以超过1[ColorUsage(true,true)]publicColorhdrEmissionColor;// 不支持Alpha的颜色[ColorUsage(false,false)]publicColorbasicColor;3.8 完整的特性组合示例usingUnityEngine;publicclassCharacterConfig:MonoBehaviour{[Header(基础属性)][Tooltip(角色名称在UI中显示)]publicstringcharacterNameHero;[Tooltip(角色的移动速度单位米/秒)][Range(1f,20f)]publicfloatmoveSpeed5f;[Tooltip(最大生命值)][Range(1,9999)]publicintmaxHealth100;[Space(10)][Header(战斗属性)][Tooltip(基础攻击力)][Range(1,999)]publicintattackPower10;[Tooltip(暴击率0到1之间)][Range(0f,1f)]publicfloatcriticalChance0.1f;[Space(10)][Header(外观)][Tooltip(角色主要颜色)]publicColormainColorColor.white;[Tooltip(自发光颜色HDR)][ColorUsage(true,true)]publicColoremissionColorColor.black;[Space(10)][Header(描述)][TextArea(3,10)][Tooltip(角色的背景故事描述)]publicstringbackstory;}四、Inspector中的特殊控件4.1 GameObject/Transform引用——拖拽槽// 在Inspector中显示为可拖拽赋值的槽位publicGameObjecttargetObject;publicTransformfirePoint;publicMaterialcharacterMaterial;publicTexture2DiconTexture;publicSpriteuiSprite;publicAudioClipshootSound;publicAnimationClipidleAnimation;4.2 枚举——下拉选择框publicenumDifficulty{Easy,Normal,Hard,Nightmare}publicclassGameSettings:MonoBehaviour{// 枚举在Inspector中自动显示为下拉菜单publicDifficultydifficultyDifficulty.Normal;}4.3 数组与List——可编辑列表publicclassLevelManager:MonoBehaviour{// 数组在Inspector中显示为可折叠的列表// 可以添加、删除、重排序元素publicGameObject[]enemyPrefabs;publicTransform[]spawnPoints;[SerializeField]privateListstringlevelNames;[SerializeField]privateListGameObjectactiveEnemies;} 在Inspector中操作数组/List点击添加新元素点击-删除最后一个元素拖拽元素调整顺序点击三角展开/折叠数组4.4 AnimationCurve——曲线编辑器// AnimationCurve在Inspector中显示为可编辑的曲线图publicAnimationCurvejumpCurveAnimationCurve.EaseInOut(0,0,1,1);publicAnimationCurvedamageFalloffAnimationCurve.Linear(0,1,10,0);4.5 Gradient——渐变编辑器publicGradientskyColornewGradient();publicGradienthealthBarGradient;五、初始化顺序——代码默认值 vs Inspector值5.1 初始化优先级 理解代码默认值和Inspector值的优先级很重要脚本中声明的默认值先被应用Inspector中保存的值会覆盖代码默认值Awake/Start中的代码赋值会覆盖Inspector值publicclassInitOrder:MonoBehaviour{publicintmyValue10;// ① 默认值为10voidAwake(){// ② 如果Inspector中修改了myValue这里读取的是Inspector的值Debug.Log($Awake中的值{myValue});}voidStart(){// ③ 可以在此覆盖Inspector的值// myValue 20; // 取消注释会覆盖Inspector设置}}5.2 Reset方法——重置到默认值实现Reset方法可以让Inspector中有个重置功能publicclassConfigurableComponent:MonoBehaviour{publicfloatspeed5f;publicinthealth100;// 在Inspector中点击组件菜单的Reset时会调用此方法voidReset(){speed5f;health100;}}六、运行时Inspector调试6.1 Play模式下修改值在Play模式下所有Inspector中的变量值都是实时可修改的修改speed → 角色立即改变移动速度修改health → 生命值立即变化拖一个新的prefab到引用槽 → 立即生效这个功能让游戏参数的调整变得极其高效——你可以边玩边调直到手感满意为止。但记住⚠️ Play模式下的修改在停止后会被重置。6.2 保留Play模式的修改① 在Play模式下找到满意的参数值② 右键点击组件 → “Copy Component”③ 停止Play模式④ 右键点击同一组件 → “Paste Component Values”⑤ 所有在Play模式下调整的值都被保留下来了6.3 Debug模式下的Inspector切换到Debug模式Inspector右上角三点菜单 → Debug后你可以看到所有字段——包括private字段和Unity内部维护的状态值。这在排查Bug时非常有用。七、最佳实践7.1 变量职责清晰一个脚本的public变量应该都是它的配置参数——影响行为但不改变逻辑。如果一个变量需要被其他脚本频繁读写考虑使用属性Property或事件机制。7.2 合理的默认值为每个可配置变量设置合理的默认值。策划或美术在使用你的脚本时不需要调整每个参数就能让组件正常工作。7.3 良好的分组和文档使用Header、Tooltip、Space等特性让Inspector面板清晰有序。复杂的组件尤其需要良好的组织。八、本篇总结✅ 本文核心知识点回顾public变量和[SerializeField] private变量在Inspector中显示[HideInInspector]隐藏public变量[Header]、[Range]、[Tooltip]、[Space]、[TextArea]等特性美化InspectorAnimationCurve、Gradient提供可视化编辑器自定义类需标记[System.Serializable]才能在Inspector中显示Inspector值覆盖代码默认值Play模式修改停止后重置Copy/Paste Component Values保留Play模式的调试结果 下一篇文章将学习MonoBehaviour的完整生命周期——Awake、OnEnable、Start、Update的执行顺序。动手任务① 创建一个配置脚本使用所有学到的Inspector美化特性② 尝试用[SerializeField]替代public变量③ 在Play模式下调整参数并用Copy Component保留关于作者拥有多年Unity开发经验的游戏开发者专注Unity系统化教学与最佳实践分享。
返回列表