标签归档:Unity3D

Ludum Dare #26 极简RPG

第26届Ludum Dare 48小时游戏开发挑战赛于2013年4月27、28两日举行——恰逢共产国际劳动节,美国人民完全无视之,无奈我们还得周末上班只为那3天假期。最后搞得我只得在28号下班后利用最后的凌晨12小时来完成这次比赛。

主题“Minimalism”可谓正合我意,因为在此前我就有考虑过“简化RPG”的概念——大多数RPG对于现代人而言节奏显得过于缓慢、系统也过于复杂了,我希望能够简化RPG的外在并提纯其核心游戏乐趣,制作一款能够更适合现代人的“极简RPG”——而这次比赛的主题不仅能够让我有机会尝试此前的构想,而且“极简”的风格本身也能够弥补我时间上的不足,让我利用极为简陋的画面呈现一个“符合主题”的游戏作品。

虽然策划了多个游戏环节,包括战斗、开宝箱、升级、商店,但最后只是草草实现了战斗的部分。不过这个简陋的小游戏却让我玩的不亦乐乎,它的核心机制还是有一些趣味性的,不少评论者也提到了这一点。

画面风格借鉴的Windows 8,不过显然是没学到位。

游戏介绍、试玩、下载、源码

最后看看忙得不亦乐乎的开发视频吧:

One Game A Month二月战报

没想到2月还能顺利完成One Game A Month的挑战,由于春节的缘故,本月从10多号才开始游戏开发,加之年初工作非常紧张繁忙,周末和白天均无多余的时间可以支配,好在我在春节期间提前想好了对策——清晨早起的“独立时间”

6-30-am-beijing

每天6点出头儿起床对于北京的上班族而言是很正常的作息时间,但我自打不上高中以来就没再这样坚持早起过。这样的起床时间可以为我在每天上班前换来1个多小时的独立支配时间,大部分用于开发独立游戏,偶尔写写博客。去年没坚持下来,而这次能坚持下来的原因就是下定决心每天10点半之前睡觉——早睡早起不但对身体好(子午觉+最佳起床时间),而且早起的时间总能给我带来一种“众人皆睡我独醒”的满足感。

即便如此,本月总共用于游戏开发的时间也就30多个小时。

2月One Game A Month的灵感主题是“声音”,最开始想到的是学习做一首游戏音乐,按照独立星球论坛里的教程学了一阵子,发现势头不对,因为转眼已经二月中了,游戏还没动手做,遂只能放弃做音乐的想法……

由于春节前做了一个电子贺卡是音乐节拍游戏,所以想到了基于她进行改进。主要的想法是制作出一款可以“听着音乐随心所欲打着节拍”的游戏——我想这也是很多人在听自己喜欢的音乐时的状态。

实现的形式是玩家可以自己录制节拍,音乐一边播放一边点击屏幕打着拍子,不提供任何编辑功能,要的就是一次性的即兴创作——可以有瑕疵,当然也会出现绝妙的节拍组合,录制完以后就可以玩自己的节拍了。

发布到iOS上拿在手里玩感觉更好,关键是加入了自己喜欢的音乐,一边听着《无地自容》一边敲锣打鼓,不禁泪流满面。

1gam-2013-02-screenshot

网页版
Windows版
Mac版

爱上C#的理由 之 implicit隐式转换

写机器能够读懂的代码简单,写人类能够读懂的代码才是真功夫,而C#则提供了诸多优秀的语言特性来帮助你写出更加整洁、易读的代码。今天介绍的是implicit隐式转换

作为例子,我们定义了一个HsbColor结构(struct),它与Color类似,是对于色彩的一种数学表示,只是其色彩空间为HSB,而非Color采用的RGB色彩空间,因此你可以通过HsbColor.s来设置色彩的饱和度。下面这个函数可以调整当前物体材质颜色的饱和度:

可以看出,在创建hsbColor实例的时候,我们在构造函数中传入一个Color类型参数,最后在调整完hsbColor的饱和度后,又通过ToColor()函数将其转换为Color,并给material.color赋值。这段代码并无甚不妥,只是在implicit隐式转换的帮助下,我们可以让它变得更为简洁:

从上面的代码可以看到,我们可以使用Color直接为HsbColor赋值,同样的,我们还可以直接将HsbColor赋值给Color类型参数——这就是数据类型的隐式转换,在HsbColor中我定义了这样两个静态函数:

它们实现了HsbColor到Color之间的隐式转换。

需要注意的一点是,采用implicit隐式转换的一个首要原则是数据转换过程中没有丢失信息(如精度),HSB和RGB属于同一色彩的不同色彩空间表示,满足这一条件。而如果是float至int这类丢失数据精度的转换,我们则应该采用explicit显示转换:A = (A) B,这样可以在编译过程中就提示程序员转换非完全等价。

implicit和explicit属于C#的一个很小的语言特性,介绍的文章也很多在此不再赘述,附上实例中用到的HsbColor脚本,除了提供通过HSB属性定义颜色的功能外,还提供了HsbColor.Lerp函数,使你可以在HSB色彩空间内进行颜色转换,比起RGB空间的Color.Lerp更加符合人眼色彩变化的观感:

One Game A Month一月战报

一月在年底的忙碌中转眼即逝,我在最后关头完成了“每月一游戏”的一月挑战,只是很多预先设计的内容都没能实现,只是完成了一个可以自己控制两队人马互相对砍的日式RPG基本雏形,玩起来是没有什么乐趣,不过我依然感到很欣慰,终于做RPG了啊!

在线试玩
OneGameAMonth页面

游戏的灵感来自于Ludum Dare上一届的参赛作品,我记得是第1名和第4名,都是讲地下城主率领大军迎战贪婪、野蛮、不讲礼貌的冒险者的(这是本届Ludum Dare的热门创意之一),一个用的是类似塔防的模式,另一个是类似踩地雷。而这次我的目标是做一个更简化的RPG游戏,删减与战斗和策略无关的内容。选择Evil Lord的视角一个是有趣味性,另一个重要目的是不需要制作怪物的形象——这真的很划算!

预先计划但没有实现的内容包括:

  • 通用三维角色——三维真的很耗时,这件事我还是准备拉长战线,慢慢筹备。
  • NPC(冒险者)的AI
  • Evil Lord不断挑战冒险者的回合机制——怪物被灭后,Evil Lord恢复一定Evil Points,然后可以选择召唤怪物出来迎战(消耗Evil Points),或者送给冒险者宝箱、恢复MP HP神像(恢复自己的Evil Points)
  • 简化的游戏系统——做着做着好像就不那么简化了!
  • 早上6点起床——睡觉前我的起床意志很坚定,早上的时候意式很模糊
  • TimeLapse——碎片时间总是忘记开软件

参加OneGameAMonth(每月一游戏)的感受:

  • 时间看似有一个月,但对于我而言碎片时间并不多,独自奋战的话我觉得和一个Game Jam差不多。
  • 有DeadLine的感觉真好
  • 有来自世界各地的很多人陪你一起疯狂做游戏的感觉更好
  • OneGameAMonth的网站真不错,我已经Lv4(450xp)了

总的来说我觉得1月的1GAM虽然有太多遗憾,游戏也完全不像样,但这是我第一次尝试制作我最喜欢的游戏类型,此前的Game Jam我都因为RPG的复杂度较高而没有选择它……因此我感觉还是很值得的。这个游戏我会继续从“简化外围”“强化核心”的角度继续下去,OneGameAMonth的规则很宽松,在后面的某个月我将会发布他的后续版本。

Ludum Dare 25经验总结

Ludum Dare 25游戏草图

游戏在线试玩(Unity WebPlayer)Unity工程文件下载(百度网盘)LudumDare游戏展示页

Ludum Dare第25届48小时挑战赛于12月15-16日举行,吸取了上次比赛的经验教训,此次我可谓有备而来,在比赛开始前对自己提出了几点要求:

  • 更好的时间管理
  • 更简单的GamePlay
  • 更丰富的音乐音效
  • Timelapse
  • 更充分的睡眠
  • 一只喷火龙

经过努力上述目标在本次比赛中都已顺利达成,下面是详细的得失分析:

做对的事:

先实现Game Play和游戏流程,然后制作美术音乐素材

吸取上次比赛的惨痛教训,为了保证游戏最终能够具备足够完整的流程和玩法,本次比赛中我将美术音乐素材的制作放到了最后阶段,而在第一天的工作中着力完善游戏原型和游戏流程。实时证明这样是非常明智的:因为最后阶段你的时间一定会不够用,因此你不得不熬夜,进而你的精神状态必然非常萎靡、烦躁、焦虑——而在这样身心俱疲的时候,你认为搞“编程”和“艺术”哪个更合适呢?显然无需复杂逻辑思维的“艺术”工作更适合后期的身体状态,而且更重要的是,你心里清楚即便美术音乐素材做得不够多不够好,顶多最后提交的是一个丑陋的游戏,而不会丢掉“游戏性”这一游戏的精髓。

音乐和音效

我始终认为音乐是更加直指人心、更容易让人产生心理共鸣的艺术形式,之前在游戏音乐上吃过亏,所以这次比赛中我将美术素材和音效素材一同制作,确保二者齐头并进,不会过于偏袒美术方面。并且在素材制作初期我便为每个游戏场景选择了一段背景音乐——虽然花费的时间还不到15分钟,但是它所带来的回报显然是巨大的,这可以算是一笔非常划算的时间投资,在收到的评论中有多人提到对游戏音乐的赞赏——显然音乐对整个游戏起到了不小的提升与完善作用。

游戏情节和文字对话

在这次的游戏中,我首次尝试添加了一段简单的剧情以及一定量的文字对话,虽然中英双语的文字编辑工作占据了一定的制作时间,但它们如胶水般将游戏连接成了一个更紧密的整体,小小的开场故事创造出一定的吸引力和游戏动机,而穿插在游戏进程中的俏皮话可以强化游戏整体的幽默氛围——虽然文字功底(特别是英文)比较有限,但我依然认为这是一次成功的尝试——特别是在短短的48之内。

突击制作美术音乐素材时设置To-Do List

由于开始制作美术音乐素材时仅剩余12小时(算上睡觉时间),为了明确工作内容并督促自己的进度,我采用了在一般日常工作中一直坚持使用的To-Do List任务管理机制。我在RememberTheMilk上列出了剩下的所有工作条目,并划分了优先级,各个攻破。这样做大大提高了我的工作效率,促使我得以在最后有限的时间内对游戏进行了足够的完善和美化,并且非常明智地放弃了制作三维模型——因为长长的任务列表使我认识到制作三维模型在本次比赛中已经是不现实的了。

最好成绩记录功能

Ludum Dare开发出的游戏一般是“一次性”体验的,能玩一次通关就算成功了,但如果你希望能够给玩家一些“反复游戏”的动力,那我推荐“最好成绩记录功能”,既然游戏中往往包含分数统计的功能,为何不把每关的分数存储下来供玩家反复挑战自己的最好成绩呢?我在游戏中还特意列出了我打出的最好成绩,以此来鼓励玩家挑战游戏开发者——不过我看到的最绝的是有一个游戏中加入了在线排行榜的功能,你可以与全世界的玩家一决高下了。

LD25最好成绩记录功能

Timelapse

使用开源软件ChronoLapse来记录游戏开发过程非常简单,赛后做成Timelapse视频(见本文最后)不仅看起来很酷,而且也很有纪念价值,强烈推荐。

做错的事:

游戏原型制作阶段未设置To-Do List,进度拖沓

To-Do List在美术音乐素材阶段大幅提高了我的工作效率,因此我非常后悔没有在游戏比赛初期使用这种工作方式——游戏原型阶段由于没有明确工作内容,我总是处于一种“调试参数、运行、测试、调试参数……”的循环之中。虽然看似在调整游戏原型,但实则进度推进非常缓慢,忽略了许多更为重要的工作内容,也为后期艺术素材制作时间不足埋下了伏笔……在下次的比赛中我会尝试全程To-Do List,期待能带来更高的效率。

最后附上本次比赛的Timelapse视频,参加比赛须尽欢!

爱上C#的理由 之 Extension Method

在Unity3D提供的几种脚本语言中,有很多理由爱上C#,在我心目中Extension Method无疑是其中一个。

在使用Unity3D提供的类库书写脚本时,是否经常有类似这样的抱怨:“为什么就不能为AAA类写一个XXX方法呢?!明明很简单的一件事,现在却需要绕这么多圈子!”例如下面这3行代码:

明明很简单的三件事,但是代码写出来却不怎么简洁明了:

  • 设置X坐标为3
  • 设置等比缩放为(3,3,3)
  • Log一段话

对于Unity开发者,前两行代码估计都写过,而且很可能是需要常常写。第三行的Log代码我使用了string.Format——我喜欢更接近自然语言的Log输出,因为它会让那些调试信息看起来不那么烦人,但是每次都写一遍string.Format和一堆括号确实是又麻烦又冗长。

假如我们换一种写法:

是不是更加易懂而且代码也更加简洁了呢?我给Transform添加了两个梦寐以求”的方法:SetPositionX(float)以及SetUniformLocalScale(float),并且给所有继承自Object的类添加了一个Log(string, args)方法,可以直接传入string.Format的参数。

要实现这样的扩展无需破解Unity的类库,只需要使用C#的Extension Method即可。顾名思义,Extension Method允许你从外部为已有的类添加“扩展方法”——而且无需该类的任何代码。例如上面三个Extension Method的脚本是这样书写的:

从上面的代码不难看出,Extension Method要求必须使用静态类封装,且需要依据这样的格式为方法命名:

这里面this在函数传参中的使用也算是C#中this的一种特殊用法。

虽然Extension Method善加使用可以减少一定的重复工作量,让脚本更加简洁易读,但它也不是万灵药,在书写过于复杂的Extension Method之前也许你需要慎重考虑是否应该为该类增添一个新的接口,而不是“把代码写在外部”。另外struct是无法定义Extension Method的,例如Unity中的Vector3和Color。

最后附上两个我做的Extension Method脚本,分别针对Transform和Debug做了几个扩展方法,相信在看了这两个脚本后,你一定可以自己动手写出那些“梦寐以求”的扩展方法了。

点击下载示例脚本