作者归档:贺 利华

关于贺 利华

正在学习编程,享受编程 热爱文学,闲来读读《读库》 有思想,没理想 正在学会专注

如何在Unity3D中优雅的重命名脚本中字段名而不丢失其引用

在进行 Unity3D 开发的过程中,我们难免会碰到想要修改脚本中变量名的情况,可是呢,我们在代码编辑器或者 IDE 中对代码文件中使用到的变量进行 Refactor 之后呢,代码倒是好看了,也是不出错能编译通过了,但是到了实际运行的时候就发现出现各种空引用的问题了。

这是神马鬼啊?估计初学 Unity3D 开发的童鞋还会觉得尼玛简直不知道碰到什么鬼了,熟悉了 Unity3D 开发的童鞋呢,就会会心的一笑,尼玛的 Unity3D 简直不能再坑爹了,好吧,我再重新关联一下变量的引用吧。

这个问题的根源是啥呢?就是我们通常在脚本文件中使用了 Public 的变量,这些变量都会被 Serialized (序列化)保存到对应的 Prefab 文件并持久化到磁盘上,然后每次我们运行游戏的时候呢,Unity3D 会讲这些变量对应的资源引用加载到内存中来,这样我们就可以非常方便地在一个 Prefab 中愉快地使用另一个需要动态显示或者隐藏的 Prefab 或者 GameObject 了。这是我初次进行 Unity3D 开发时候,惊异于 Unity3D 的魔法之一。当然我现在每天都在施展这个魔法啦,不过有的时候呢,总会觉得有些不太爽,因为我有轻微的代码洁癖,只要我觉得这个字段命名的表意不准确,当我发现有更为准确的表意的变量名时,我一定会将变量名或者 Prefab/GameObject 的名称修改过来。修改 Prefab 和 GameObject 的名称倒是完全 OK,Unity3D 会自行帮你把事情做对,但是修改变量名就不一样了,例如在进行改名之后,GameControl.cs 文件中有一个名为 player 的 Public 变量,这个 player 变量指向一个场景中名为 Player 的 GameObject,此时我们的需求发生了改变,这个脚本需要控制两个 Player 了,原本名为 Player 的 GameObject 更名为 PlayerFemale 了,按照正常情况,我们的代码通常也是需要进行修改的,这样变量名和 GameObject 的名称就能保持一致了,方便阅读和理解代码,但是player变量一改名为playerFemale之后,再次运行游戏,就会得到一个空引用异常了,Unity3D 会提示你 playerFemale 变量的引用为空。

叨逼叨了这么多,那么怎么解决呢?尼玛我自己肯定解决不了,这个完全就依赖于 Unity3D 官方的解决方案了。原文链接在这里,大家直接前往围观。

我这里自己也备个忘,做法入下。

如果原先的变量名为 player,修改之后的变量名为 playerFemale,那么我们只需要在使用 Refactor 工具将 player 字段名重命名为 playerFemale,确保所有引用到该变量的代码文件中的 player 字段名称都修改过来了之后。在这个新的变量 playerFemale 上方一行,加入 [FormerlySerializedAs(“player”)] 即可。代码如下:

[FormerlySerializedAs("player")]
public GameObject playerFemale;

如果后续我们还要再将这个 playerFemale 字段名再修改为 playerAssassin 呢,那又肿么办?那就依顺序再加一行 [FormerlySerializedAs(“playerFemale”)] 在原有的 [FormerlySerializedAs(“player”)] 下方即可,代码如下:

[FormerlySerializedAs("player")]
[FormerlySerializedAs("playerFemale")]
public GameObject playerAssassin;

好了,奏是这个样子滴,好棒哒,希望 Unity3D 能变得越来越好用,省得被我们耀华一天到晚问候各种亲戚朋友,是吧。

【撒利学 Shader】之一 UV Mapping 的概念

UV Mapping就是UV贴图的意思,说白了就是将3D中的不规则多面体沿着某条线剪开之后,然后摊开到一个平面上,这样就可以将3D物体上的每个点映射到一张2D的平面贴图上了。

当然这个显然木有我说的这么简单,毕竟3D物体那么不规则,要将一张2D的贴图上的每个像素与3D物体上的各个顶点以及顶点之间映射上也不是件容易的事情,不过显然这个不是我能讨论和想讨论的事情了。我们只需要知道制作UV贴图是3D建模软件一个高级的基础功能就好了,Unity3D拿到这些UV贴图之后直接往模型上贴就好了,不过Unity3D又是如何读取2D贴图中的UV信息,并且能将这个贴图很好地贴到这个模型表面上捏?好吧,其实我也不知道,希望在这个学习Shader的过程中,我们最终能解答这个问题。

【撒利学Shader】写在前面的话

作为一个Unity3D开发者,我时常提醒自己并不是一个3D 游戏开发者,甚至都不是一个游戏开发者,更多的时候只是一个脚本程序员。这是我对自己的一个定位,也是一种现状的描述,我身边有不少做 Unity3D 开发的朋友,他们对于3D 程序开发实际上了解得并不多,但是貌似也能胜任他们正在做的工作。

这是 Unity3D 带来的一种效应,有其积极的一面,同样也有其消极的一面。积极的一面是,更多原本对3D 编程敬而远之却对游戏编程怀有兴趣的人,可以就着 Unity3D 直接开工,上手去做一些有趣的事情了,降低了整个3D 游戏开发的门槛,让游戏编程更加的亲民了;消极的一面呢,这部分半路出家杀到 Unity3D 开发圈子里头来的童鞋们呢,由于 3D 编程基础几乎为 0,所以在涉及到 3D 图形技术领域很可能直接就抓瞎了,整半天完全摸不着头脑的并不是啥奇事。我就是这半天摸不着头脑的人之一,为了让自己能摸着头脑,那么就只能从零开始,一点点琢磨了。

3D 编程中诸多的技术问题,Unity3D 通过它那万能的 Editor 实际上已经解决了很多 3D 编程中需要去面对的问题了,例如摄像机、坐标运算和坐标系转换、光照、投影,渲染等等等等。而在 Unity3D 开发过程中,可能让我这种非正规 3D 游戏开发者最为头疼的可能就是对 Shader 的一知半解了,而在一个 3D 开发者的成长之路上,这个问题早晚得是我们需要直接面对并且勇敢翻过去的一座山,唯有如此我们才能看到更加美丽的风景,如果我们有女朋友的话,还可以带着女朋友一起看。

作为一个 Shader 小白,我们最好的学习方法是啥?当然是看书咯,不过貌似这方面的书真心不多,曾经有一本《GPU 编程精粹》如今依然绝版,今天在网上搜寻了一番,最近貌似新出了两本 Shader 相关的图书,直接立刻下单《Unity 3D ShaderLab 开发实战详解(第 2 版)》和《Unity 着色器和屏幕特效开发秘笈 [Unity Shaders and Effects Cookbook],买回来看看先。

不过作为程序员的我们,在碰到问题之后的第一反应通常都是找文档,第二反应就是找 Google,对吧。不过相信所有 Unity3D 的开发者都会有一个这样的感受,Unity3D 的开发文档跟翔的区别可能都没有半毛钱那么多,所以我们也就能从官方文档中获得有限而又可怜的帮助了。剩下的我们就交给 Google 吧,Google 了一番之后,我倒是发现了两个比较不错的教程。

一个是猫大@onevcat的猫都能学会的 Unity3D Shader 系列文件两篇:

另一个是90后大神@浅墨_毛星云的【浅墨 Unity3D Shader 编程】系列文章了:

感谢两位非常棒的分享,让我能快速地理解了 Shader 的基础用法,用了差不多3天时间消化了一下这几篇文章,现在已经能对着各种 Shader 插件中提供的 Shader 逐句分析其用意和用途了。

不过本着记录和分享,以及锻炼一下自己技术写作能力,敦促自己继续学习的目的,我想把我自己持续学习 Shader 的整个历程记录下来。所以这个系列并不会像浅墨_毛星云或者 onevcat 的文章一般抽丝剥茧地从头细说 Shader 的学习路线,而是会以一个对 Unity3D 开发已经较为熟悉,但是对 Shader 不是那么了然的程序员的视角来记录学习过程中遇到的小问题,以及在解决这些问题的过程中获得的信息以及其相应的延伸内容。

突然想写点什么

今天是锤子的新手机“坚果”手机的发布会,由于技术故障,发布会延迟了一些时间,有网友戏称“罗永浩重新定义了7:30”。

我并没有完整地看完整个发布会,我也不是锤粉,也不是罗永浩的粉丝,得知罗永浩的一些相关事情大多是从《读库》的老六那儿偶尔听到一些花边新闻啥的,自己貌似看过老罗哪一年在海淀剧院的一个演讲,那会儿他的公司名叫“老罗和他的朋友们”,还是在做英语培训。

有一些感概主要是来自于看到锤子一步步地从零开始到现在这么不错的一个体量,成长为一家健康的企业,创造出来让大家喜欢的产品,很羡慕,当然也有一些唏嘘。

说得好听一点,我跟着之前公司的老板一起进入移动互联网创业的时候,老罗还在张罗着给自己的培训学校找教室呢。用我前老板的话说“我们起了个大早,赶了个晚集”,从2010年5月18日,进入Android开发这个圈子,从一款单机小游戏《黄金矿工——喜讯特别版》,到个人日程管理APP《喜讯天天》,到移动互联网照片分享社区《画说》/《MARK》,一个人扛着整个公司Android开发的大旗横冲直撞,锤炼了自己的手艺,淬炼了自己的筋骨,拓展了自己的视野,长膘了自己的腰围。

随着公司在移动互联网社交领域的失败——前老板如此下的结论,公司集体转型到手游,开始担任项目经理,当然更多的角色还是主力客户端程序和救火队员,产品最终如期发布,事情也做得越来越顺手,但是由于期望过高,让《铁血战神》背负了太多,最终未能撑起让整个公司崛起的大旗,反而成为了我在前任东家的告别项目,今天还有玩家反馈说是《铁血战神》没法登录了,以前的同事在群里还感慨了好一阵子。

如今自己跟几个前同事自己立了一个摊子做手游,但是困难重重,有产品上的,有技术上的,更多还是人的困难,不当家不知柴米油盐贵啊。创业一年有余,方知世事皆艰难,唯有咬牙挺过去,兴许能有机会看到胜利的曙光。

回到感慨这个话题,感慨的是什么呢?感慨的是,“滴滴打车”和“锤子手机”已经从那个创业的死人堆里头爬出来了,而我可能又将再次被埋葬在这一波的寒冬。

记得首次在媒体上看到“滴滴打车”的报道时很不以为然,然后没过多久听到朋友说起自己打车有在使用“滴滴打车”(那是冬天,在北京这货很有用,可以让你不用在寒风中站在马路边等车),再没过几天被一个出租司机——张师傅推荐安装了”滴滴打车“,从此”滴滴打车”成为了我生活中必备的工具,因为当时每天加班都到23:30以后,大部分时间都是凌晨2点左右,这个时候“滴滴打车”每天让我能快速舒服地打到回家的车(那时我在北苑上班,住在天通苑,这个点这个路段几乎百分之九十的出租师傅都会选择拒载,因为路途短,就是个起步价,而且还是往城外方向走,回来肯定放空车),当时跟泰峰聊,移动互联网目前为止让我感觉到改变了我自己生活的有两个APP,一是微信,二是滴滴打车。放个马后炮啊,当时看到每天报道说滴滴的技术不够强什么的,甚至看到过滴滴的招聘文章,如果那个时候真的这么坚定的话,也许可以加入滴滴做个开发人员呢,是不是?

在罗永浩说要做手机之初,看到很多报道,看到他跟很多人打嘴仗,当时只是觉得这些人怎么都觉得自己能做手机,真的有那么简单吗?持一种怀疑的态度,并不看好。当时我的同事张树立已经从前东家离开了,有一次吃饭听他聊起过他还去锤子手机参加过面试呢,不过最终的结果是他并没有加入锤子科技,选择了人人网。当时听他谈到去锤子面试的时候,内心其实是有一些小触动的,这个小触动是心想“如果我去了,被录取了的话,会是神马情况呢”这样的一种情绪。对于罗永浩这号人物,内心是很佩服的,例如在条件允许的情况下,坚决支持正版,坚持做公益捐赠,支持有理想的人去坚持他们的理想,,碰到让自己不爽的东西会触发处女座属性,这些都是我自己很欣赏的特质,我也是这么做的,从人格上来说,简直完美契合,而且他的演讲技巧简直让我拜服,人生的轨迹也足够精彩。能够追随一个这样的人去做些事情,即便最终未能获得普遍意义上的成功,我想也是成功的。

但是,我们终归还是那只留在了井底的蛤蟆,我们有痴心妄想的权利和欲望,但是没有跳出井口的能力和远见。也许未来还有更加美丽的风景在井口出现,我想什么时候要是能老腰一拧,纵身一跃,跳出那井口,站到井沿儿上去看那风景,甚至成为那风景,那个时候再感慨一声“你也有今天啊”,多么美好啊。

Unity3D中CapsuleCollider碰撞挤压将对象挤到空中的问题

这几天一直在尝试着修改各种战斗中的Bug,优化一些战斗细节等等,然后发现了在某些怪和主角对抗的时候,有的时候主角会莫名其妙地被挤到空中去,有的时候是怪在攻击主角的过程中把自己给挤到空中去了。你说这能忍吗?显然不行,对伐。

然后就开始使劲浑身解数尝试着在不同的状态下,主动控制怪和主角不要离开地面(通过动态获取目标所在位置点的地表Y坐标值,然后设置为目标的Y坐标),可是这又谈何容易呢,先不说这么做合不合理,优不优雅了,这一眼看上去就不是啥好招啊,而且实际上并没有找到为神马会出现相互挤压就会把某一方给挤到空中去的原因,那么我们肯定不能善罢甘休的,对伐?

接下来我们来看两个图:capusle_collider_1动图1capsule_collider_2动图2

上方的动图1中,我们看到绿色的Capsule朝着红色的Capsule快速移动,并且在移动的过程中与其发生了碰撞,碰撞之后绿色和红色的Capsule错开,然后绿色Capsule继续运动了一段时间。从动图2中,我们能看到绿色的Capsule在与红色的Capsule碰撞之后继续运动的过程中,明显有被挤到空中的情况。咦,貌似我们已经发现什么了呢。

那我们再来对比一下这两个Capsule的设置值,到底是哪个参数导致的呢?

capsule_collider_inspector_1 capsule_collider_inspector_2

从上面的两张图对比中来看的话,其实只有一个Capsule的Scale调整了Y为2,同时Y坐标也因为Capsule变高了所以变高了。如此一来,这个绿色的高个子的Capsule在与红色的矮个子Capsule发生碰撞和挤压的时候就会因为质心过高而被挤到空中去。如果希望避免这种情况,可以考虑将所有的Capsule Collider的中心点值和高度值都统一设置。