将 Excel 表格导入 Unity 项目

在游戏开发过程中,策划往往会在 Excel 中配置游戏数据,比如物品、技能和 NPC 的属性等。因此如何将 Excel 里的数据导入到游戏中是游戏开发的重要课题。

朴实的方法:另存为 csv

比较朴实的方法是将 Excel 文件另存为 csv 文件,然后程序员写代码解析 csv 文件。可以将 csv 转换成游戏程序可以识别的格式,比如 Unity 的 ScriptableObject 或是一个硬编码的 C# 数组,即一份 cs 文件。甚至也可以在游戏运行时才读取 csv 文件。

这种方法的优点是要解析的文件格式(即 csv)很简单,不用引入第三方库,程序逻辑也就比较简单。缺点是每次编辑完 Excel 文件还要另存为 csv ,这对日常工作来说颇为繁琐,而且每次“另存为”也只能导出一份 Excel 文件,无法对多份文件执行批量导出。

继续阅读将 Excel 表格导入 Unity 项目

用 Animation 实现匀速旋转

年初参加 GGJ 的时候,我曾想偷懒用 Animation 实现物体的匀速旋转。思路很简单,只需要0度和360(或-360)度两个关键帧,然后将动画设为循环播放。当时以为这样事情就成了。谁知做出来的效果是下面这样,物体转完一圈后会停一下:

我知道问题就在动画曲线上:

只要把曲线弄成一条直线就行。

但是当时折腾了一会儿也没调出一条漂亮的直线,因此还是改用代码来实现匀速旋转。今天发现其实根本不用手调,只要右键单击,把起始关键帧的 Right Tangent 和结尾关键帧的 Left Tangent 改为 Linear (线性)就可以了:

完美:

其实以前也知道 Free、Linear 和 Constant 这几个选项,但从来没用上也没真正理解它们的用处。如今才知道是怎么回事,至少理解 Linear 了。

Unity 版本:2017.3.1f1

Aspect Ratio Fitter 和 Image

UGUI 里面 Aspect Ratio Fitter 的作用是保持一个 UI 控件的宽高比。然而 Image 自身就有一个 Preserve Aspect 属性用于保持自己的宽高比。因此起初我就想 Image 是不是就用不上 Aspect Ratio Fitter 了,或者说 Image 自身的 Perserve Aspect 的属性是不是多余的。后来发现并不完全是。

前段时间遇到一种情况必须要使用 Aspect Ratio Fitter 。

在下图中,Bubble、Text 和 Text (1) 是文字冒泡的 UI 控件。为了让文字冒泡的位置始终对准背景图片中的人物头顶,我给文字冒泡的各个控件设置了锚点。

Bubble 即冒泡框相对其父节点 Image(背景图片)设置了锚点,目的是不管 Image 大小如何变化,都要让冒泡框对准背景图片里面人物的头顶。

如果只是依靠 Image 的 Preserve Aspect 属性,那么文字冒泡是无法在 Image 大小改变的时候时刻对准背景图片里的人头的:

这是因为 Preserve Aspect 虽然能保持图片的宽高比,但却并不能保持 Image 的 Rect Transform 的宽高比。然而锚点却是基于父控件的 Rect Transform 的边界来定位的。

在这种情况下就必须给 Image 挂载 Aspect Ratio Fitter,此时 Preserve Aspect 勾不勾都是无所谓的。

Image 挂载了 Aspect Ratio Fitter 后就可以保持 Rect Transform 的宽高比,从而让文字冒泡时刻对准图片里的人头。

Preserve Aspect 的意义主要在于游戏开发者不用关心图片宽高比的具体数值,以及宽高比保持的方式。毕竟使用 Aspect Ratio Fitter 的话,开发者不但要填入具体的宽高比数值,而且要决定控件要如何保持宽高比——是高度固定,还是宽度固定,还是尽可能被包含在父控件区域内,等等。

Unity版本:2017.3.1f1

被NTFS的bug困扰了一个多星期

这篇文章其实写于2012年5月2日。原文是发表在我的CSDN博客上:《被NTFS的bug困扰了一个多星期》。昨天收到一条评论说文章写得太有趣了。于是把文章又读了一遍,感觉的确是一段宝贵有趣的回忆。因此不禁想把它搬到自己的个人站点上做个备份。珍贵的东西放在别人家里总是怕不知哪天就被丢掉了。其实我的CSDN博客上还有几篇我自认为更有趣的故障排除类的日志,有空时也会一篇篇搬过来。

原文发表的时候还是Windows 7的年代。当时微软也已经就文中提到的bug发布了补丁。如今已经是Windows 10的年代,虽然我没亲自验证,但这个bug在Windows 10上估计已经不存在了吧。

// ========= 一点也不华丽的分割线,以下是原文 =========

继续阅读被NTFS的bug困扰了一个多星期

主机无法访问后学到了一些东西

上周五突然发现我无法访问自己的博客了,但是国内的朋友可以访问。心里一惊:不会被封了吧?!

可是我的博客一向老实本分啊。关键是,我买的是香港主机,IP是新加坡的,境外主机被封的话难道不应该是国内用户访问不了,国外用户可以访问吗?怎么现在反过来了?所以很可能是主机公园——也就是主机供应商方面的原因,大概线路故障什么的。更何况经过试验,即便从国内访问也无法登陆主机的cPanel管理界面,因此服务商方面故障的可能性很大。

我试着把自己的域名解析到别的网站IP,结果是我的域名可以正常指向别人的网站。因此看来域名没有问题,是IP已经不可用了。

联系主机公园几天都没收到回复,遂决定换主机服务商,搬家。

继续阅读主机无法访问后学到了一些东西

将git工作目录的改动应用到svn

之前在维护自己写的WordPress插件时,为了能够方便地同时向GitHub仓库和WordPress官方的svn仓库提交,我只在本地维护了一个git工作目录,然后用 git svn dcommit向svn仓库提交,用 git push向GitHub提交。(详见我之前写的日志。)

但可能是因为WordPress官方的svn仓库太大,历史记录太多,而git-svn的内部实现又有点问题,所以最近几次我用 git svn rebasegit svn dcommit都毫无反应。思来想去,为了不耽误时间,我还是决定老老实实用svn客户端了。

于是现在我本地就有了两个目录:一个git工作目录,用于向GitHub提交;一个svn工作目录,用于向svn提交。由于svn里的分支和标签实际上就是目录,因此svn工作目录下还有trunk、branches和tags子目录。trunk子目录里的内容才和git工作目录里的内容相同。

一般我是在git工作目录下写代码,因此思路是在git工作目录commit之后,用 git diff生成patch文件, git log输出提交日志到另外一个文件。然后用 patch命令将 git diff应用到svn工作目录。最后 svn commit的时候利用git log的输出,这样就可以做到svn trunk分支的提交和git master分支的提交一一对应。这个过程如下图所示:

继续阅读将git工作目录的改动应用到svn

EMwI插件启用失败的问题

有几名External Media without Import的用户向我反馈说插件启用失败,提示语法错误。其中还有一名用户就此问题在github上向我提了一个issue。具体的错误提示是Parse error: syntax error, unexpected T_STRING in …….external-media-without-import.php on line 25。

然而external-media-without-import.php的第25行仅仅是一个名字空间定义:

经过调查与沟通,发现原因是用户使用的PHP版本低于5.3.0,而PHP到了5.3.0才引入名字空间的特性,见PHP 5.3.0 Release Announcement。起初用户以为自己的PHP版本是5.6.30,但依据经验我猜测对方机器上可能有多个PHP版本,并且WordPress使用了较老的PHP。后来用户在自己的WordPress上安装了Display PHP Vesion插件,果然发现WordPress用的是PHP 5.2.17。

因此各位用户如果遇到这个启用失败的问题的话,请用Display PHP Vesion插件查看一下WordPress所用的PHP版本,确保PHP是5.3.0或更高的版本。

想不到那么老的PHP版本都还是有很多国内外用户在用啊。

用UGUI Slider做血条时遇到的一个小问题

前段时间想在小游戏中做一个血条UI,自然而然地想到了用UGUI的Slider。

在Unity中可以通过编辑器菜单一键创建一个Slider。这样的一个Slider里会包含Background、Fill Area和Handle Slide Area三个部分。其中Handle Slide Area就是滑块。血条不需要滑块,因此要将它删掉。

刚用编辑器菜单创建的Slider。需要将Handle Slide Area也就是滑块删掉。

我以为将滑块删掉就万事大吉不用改了,谁知却遇到一个问题。Value为0的时候,血条在表现上还有残留的血量:

Value为1的时候,血量却还没填满整个血条:

后来发现要将Fill Area及其孩子Fill的Left和Right都调成0才行。这样问题就解决了。

这里Left是指UI控件的左边缘相对于Anchors Min X的距离,Right是右边缘相对于Anchors Max X的距离。

EMwI插件更新:防XSS攻击

8月底的时候External Media without Import插件在github上收到一个pull request。对方指出我的代码存在XSS漏洞。惭愧,直到最近才腾出时间仔细研究他说的问题。插件的1.0.2版本合并了对方的pull request,修复了该漏洞。

在修复之前,我的插件中有如下代码(点击查看源文件):

这个函数将width 、height 和mime-type等信息通过 urlencode编码后设置为url的参数,然后重定向到该url。在url的响应函数中,我调用了 urldecode读取来这些信息: 继续阅读EMwI插件更新:防XSS攻击

理解Blender的表面细分修改器

以前一直不太理解Blender的表面细分修改器(Subdivision Surface Modifier,简称Subsurf)究竟是按什么规则来切割模型上的面。直到前段时间看了上篇文章提到Andrew Price的视频才理解。表面细分的规则是:给定三个顶点组成的两条相交线段,subsurf会构造一条曲线,使曲线和两条线段的中点相切,如下图所示。

不过因为模型中的线都是直线,所以Blender只能是用多条直线逼近这条曲线。细分次数越多,就越能逼近这条曲线。我们以一个四个顶点组成的平面模型为例,给这个平面添加一个表面细分修改器。细分次数为1是如下样子:

继续阅读理解Blender的表面细分修改器