Unity防bug指南 从这里开始,我们将会讨论Unity游戏编程中一些常见的非预期情况,以及相应的防范与应对策略。 (本章对于有经验的Unity使用者而言可能太过简单了。如果你认为没有什么值得注意的,可以直接前往下一章。) 1.1 获取游戏组件 在Unity中,相信大家都了解一个极为常用的方法: GetConponent<T> 此方法用于查找并返回游戏物体上指定类型的组件。 例如: Animator anim = gameObject.GetConponent<Animator>(); 此语句将会查找当前游戏物体上挂载的Animator动画组件,并用Animator anim指代之; GetConponent<Text>().fontsize = 25; 此语句将会找到当前游戏物体上挂载的Text文字组件,并直接将其字号设置为25。 在脚本中,我们可以用GetConponent<T>对任意的Unity组件进行操作,或者用于找到挂载在物体上的另一个MonoBehaviour组件,实现代码间的通讯。 不过,作为一个十分常用的方法,GetConponent<T>本身是很不安全,很容易引发异常的。如果你有一定的Unity编程经验,相信一定都经历过组件查找失败的困扰。 首先讲解一下最基础的常识。(非新手同学先跳过这里往下看) 在Unity中,GetConponent<T>方法有以下特性: (1)如果成功查找到了类型为T的组件,则此方法的返回值就是该组件; (2)如果没能成功查找到组件,则此方法的返回值为null; (3)*此方法得到了对bool运算符的重载,这使得它始终可以被看成一个布尔变量。当此方法成功查找到组件时,该方法返回true;反之则返回false. *Unity官方文档中似乎并未提到过特性(3),所以不能排除有很多新手都不知道这一点。 1.2 情境:找不到血条的医疗兵 下面我们模拟一个简单的游戏情境,来探究有关组件查询的安全性问题。 假设我们控制一名游戏人物Z进行战斗。Z身上挂载着HitPoint组件,用于记载其生命值信息;拥有100的生命值上限,但当前生命值为30,急需治疗。Z身上同时挂载着Healing组件,此组件定义了一个自我治疗技能,玩家可以按下H键进行自我治疗。 HitPoint组件: Healing组件: 新建一个场景,创建一个Capsule物体来代表游戏角色,然后为其挂载上HitPoint和Healing组件,运行游戏。 (出于文章美观的需要,这里采用了一个人类角色Cattleya) 运行游戏,按下键盘上的H键,可以从UI文字上看到,Cattleya的生命值恢复了10点。 在上面这个例子中,游戏角色Cattleya上挂载了执行治疗所必须的HitPoint和Healing组件。但在复杂的游戏项目中,我们不一定始终能够对物体上的组件进行正确配置。 假设我们在开发过程中,不慎遗漏了Cattleya身上的生命值(HitPoint)组件。此时我们调用治疗(Heal)指令,但是人物身上没有生命值可供治疗,会发生什么情况呢? 我们将HitPoint组件从Cattleya身上移除,再运行一次游戏并按下H键。 不出所料,Console面板中出现了异常提示。双击跳转到异常位置,可以看到异常出现在GetConponent<HitPoint>()的所在行。 此时或许你会说,报错了又怎么样?这个报错看起来无关痛痒,并没有导致游戏崩溃或者产生其它灾难性后果。 Unity确实具有这样的稳定性,使得许多轻微的异常在游戏中出现时,不会导致崩溃、闪退或其它严重后果。然而,就像运行一般的程序一样,在Unity中,一旦某行代码遇到异常,出现在异常后面的语句都不会执行。现在,我们在Heal组件中写入一些Debug检测点。 再次运行并观察Console面板: 我们发现,在异常所在语句后面的所有Debug指令都没有执行。 这一实验结果可以给我们足够的提示:在Unity中,放任可能出现的异常不管,是一种不安全的行为。代码中的一处异常可能会导致更多语句被意外丢弃,从而产生不可预知的后果。 因此,我们必须引入适当的异常处理机制。 1.3 安全地查找并获取组件 要解决组件丢失的问题,最简单的办法就是利用GetConponent<T>作为bool型返回值的特性。一旦GetConponent<T>的返回值为false,说明未能成功查找到所需的组件;此时就不应该针对这个“不存在的组件”执行进一步的操作。 修改Healing组件中的Heal方法如下: 再试一次,仍然在没有HitPoint组件的情况下运行游戏。 这次我们看到,程序不再报出异常或者发生意外中断。 在上面的例子中,我们在试图通过GetConponent<T>调取HitPoint组件之前,首先*检查了此方法的bool型返回值;如果返回值为true,说明成功查到组件,之后我们就可以放心地对该组件进行操作。 当然,你完全可以针对未查到组件的情况,写入一些Debug提示,或者更多的异常处理指令,使你的程序逻辑更加完善。 *Tips: 如果觉得不习惯,你也可以选择不使用GetConponent<T>()具备布尔返回值的特性。 因为,if ( GetConponent<T>() == null ) 与 if (!GetConponent<T>()) 是等效表述; 同理,if (GetConponent<T>() != null ) 与 if (GetConponent<T>() 也是等效表述。 1.4 RequireConponent与AddConponent 经过一点小小的努力,我们成功避免了HitPoint组件丢失时可能出现的报错。能否更进一步呢?现在,我们来尝试自动修复“组件丢失”这一小问题。 在一段代码的头部标注RequireConponent属性,即可实现组件依赖。修改组件Healing如下图。 修改后,当你为某一物体挂载Healing组件时,会自动挂载HitPoint组件;且在组件Healing被移除前,HitPoint无法移除。 如果在Healing组件存在的情况下尝试移除组件HitPoint,会收到提示: 这下,你就不必担心开发中会忘记添加或意外移除必要的HitPoint组件了。 此外,你可以在任何时候使用AddConponent<T>方法,来为物体挂载上任意类型的组件。 下面展示了一种采用AddConponent方法的Healing组件修改方案。 注意:如果用AddConponent方法在游戏中实时挂载组件,那么必须确保被挂载的组件本身具备完善的自我初始化能力,或者自行写入指令来对新生成的组件进行初始化。 1.5 组件的隐藏与保护 有些时候,开发者不希望某些组件或某些物体在Unity界面中被意外编辑;特别是当该组件或物体是由脚本代码进行全自动生成与管理的时候。在此类情形下,你可以通过编辑物体或组件的Hideflags属性,来实现对物体或组件的隐藏。 下面的图展示了Hideflags属性的部分常见用法。 注意: (1)如果你希望Hideflags的各种功能在编辑器中(而非游戏运行时)生效,可以考虑为组件标注[ExecuteInEditMode]属性;但是可能需要处理一些比较麻烦的继发问题。 (2)谨慎使用Hideflags功能。特别强调一点,如果你的项目将由另外的人阅览,那么HideFlags的存在会给他人造成极大的困惑。如果你需要将自己的项目交给他人进行学习、研究或编辑,那么强烈建议停用Hideflags相关功能。一. 【我血条呢??】——组件查找与组件依赖
using UnityEngine; public class HitPoint : MonoBehaviour { public int HitPointLimit = 100; public int Hitpoint = 30; public void ChangeHitPoint(int hp) { Hitpoint = Mathf.Clamp(Hitpoint + hp, 0, HitPointLimit); } private void OnGUI() { GUIStyle style = new GUIStyle(); style.fontSize = 35; GUI.Label(new Rect(50, 50, 200, 100), "当前生命值:" + Hitpoint.ToString(),style); } }
using UnityEngine; public class Healing : MonoBehaviour { void Update () { if(Input.GetKeyDown(KeyCode.H)) { Heal(gameObject, 10); } } public void Heal(GameObject Unit,int HealingHitPoint) { Unit.GetComponent<HitPoint>().ChangeHitPoint(HealingHitPoint); } }
public void Heal(GameObject Unit,int HealingHitPoint) { if (!GetComponent<HitPoint>()) { return; }//如果没有找到生命值组件,直接开溜!后面的指令不要了 Unit.GetComponent<HitPoint>().ChangeHitPoint(HealingHitPoint); }
using UnityEngine; [RequireComponent(typeof(HitPoint))] public class Healing : MonoBehaviour { void Start() { if (!GetComponent<HitPoint>()) { gameObject.AddComponent<HitPoint>();//如果没有发现HitPoint组件,则立即添加之 } } void Update () { if(Input.GetKeyDown(KeyCode.H)) { Heal(gameObject, 10); } } public void Heal(GameObject Unit,int HealingHitPoint) { Unit.GetComponent<HitPoint>().ChangeHitPoint(HealingHitPoint); } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算