翻到十年前的贴

因为某些原因翻到了blog第一页,看到了十年前Google离开中国的时候,我发出过的感慨。那会儿我称Google是“伟大的公司”,对它的离开悲痛万分。这么多年过去了,作为深度Google用户经历了一些事情之后,就再也不好意思这么吹了。也可能是我变了,当然互联网肯定是变了。

和老婆讨论现在的生态,就说到当年原始人靠天吃饭,春天播种秋天收获。如果遇到天灾只能饿肚子,甚至有生命危险。然而老天为何发怒,降下灾厄,原始人无法解释,因此就诞生了各种天神崇拜。宗教固然无法解释根本原因,可是如果手法恰好有效,信仰就会得到加强。如果和事实相悖,大家定是不敢质疑天神,只能从自身寻找原因。

找不到原因只能乱来,比如杀个人祭天,穷尽用各种手法试图和混沌建立交流。然而天神自然不会响应,原始人也就只能靠结果来证实或证伪自己的猜测。还好随着文明的进步,人类逐渐可以控制和分析天象,神秘力量才渐渐边缘化。可能从杀人祭天变成杀羊,信仰也就不那么纯粹了。

我在想现如今互联网上也有神的存在,普通网民无法和神直接对话,只能自我审查。曾经作为先锋的Tech现在变成了Big Tech,人格逐渐丧失,神格倒是逐年增加了。这些万亿大厂就是赛博生态里的老大哥,掌管着网民的方方面面。普通人还有逃脱的机会吗?

我不打算爱老大哥,我想保留自己的独立人格。

2021新的沉迷

这次是Gunpla,我在2021年终于被疫情逼成了一个胶佬。

老婆问过我为什么把拼模型的人称为胶佬,不是塑料模型吗?我也说不上来,大概以前都叫塑胶模型吧。话说回来,小时候玩得模型还得用胶粘,现在都是榫卯结构,不需要任何胶水了。所以干嘛还叫胶佬呢,是模型人,模型人才对嘛。

Anyway,今儿我并不是想说这个,忙着拼胶的我只是想记录下自己收集的某系列钢普拉的演变史,也就是SD版的高达《BB战士》系列和《SDEX》系列之间的关系。

先说说SDEX这个系列。因为我从机战游戏入坑,并不反感SD比例的高达,而SDEX去年刚出了牛高达和沙扎比,还特别便宜,我就一口气都入了。从16年到现在,它包含了17个机体,收集的时候没遇到什么困难,价格基本都带折扣。

说到这儿就比较奇怪了,疫情开始之后各个钢普拉系列都涨价,最高级的PGU一机难求。为什么SDEX还能有折扣呢?当然,也并不是每台SDEX的机体都在折扣,系列中的10号和14号,巴巴托斯的第四形态和天狼座形态,我这儿就只有高价转卖屋的货。

起初我以为是巴巴托斯人气高,毕竟上一部还算有口碑的高达动画,也就是《铁血孤儿》了,主角机体自然人气高。但后来研究发现不对,价格高仅仅是因为缺货,缺货说明万代懒得生产。接下来我在dalong.net看机体截图的时候,才发现大龙的评测里写到(感谢谷歌翻译):SDEX的10号机就是BB战士401,而14号机是BB战士402。

根据这个信息我去查贩售网站,立刻就发现BB战士这俩完全不缺货,也是打折状态。于是代替SDEX我入了BB战士的这两款,也算是间接的避开转卖屋把这个系列收集齐全了。

SDEX的官方定位是价格低廉,可动性很好的SD般高达。做的时候发现SDEX的板件很简陋,而网上也有很多骂声。我个人感觉除了分色是硬伤,细节刻画和可动性确实不错,非常适合拿来练习涂装。涂装先按下不表,因为收全了这个系列,我就好奇了起来:SDEX真的像网上所说的那样吗?于是我决定考证以下两个问题:

  • SDEX的分色比BB战士差很多吗?
  • SDEX的可动性好于BB战士吗?

TLDR,先说我的考证结论:两个答案都是否定的。SDEX系列应该算BB战士系列的延申。它按照更现代的审美重新设计机体比例,可动性没啥提高(都用PC-303连接件),分色水平也没降低(600日元的分色本来就是这么差)。BB战士的高达系列机体快6年没更新了,哪怕算上三国那些改编作,也近4年没发新货了。SDEX在21年下半年还在出新作品,可以说是BB战士秽土转生了。

硬要说区别的话,BB战士包含高价机体,有的产品能卖到1000日元甚至2000日元以上,而SDEX全部都在600日元的档次。同价位的BB战士和SDEX并没有任何区别,贴纸/连接件/分色都是差不多的水平。具体分析待我慢慢道来……


首先是时间上的关系。

BB战士系列的构成一直比较混乱,最后一款机体编号已经到了412号,比HG系列还要多。不仅是因为很多机体出过2次,还因为它包含了各种正统高达动画和高达衍生动画的机体。我估计万代最初是想诱导玩家搞收集,给各种SD比例的产品都加了个BB战士编号。一直出到18年2月的412号《三国传》貂蝉之后,新的SD三国动画《三国创杰传》终于和BB战士彻底割裂,这个古老的系列自此断更了(至少到2021年再没更新)。毕竟现在的小朋友恐怕都不知道BB战士这沙雕名字的来历,BB弹这种危险的玩具,也早就不让小朋友玩了。

只看正统的高达作品,BB战士保持着一定的更新频率,每年总要出一些。最后的两款机体是在16年动画《铁血孤儿》放映时同步推出的高达巴巴托斯,也正是和SDEX重复的那两个产品。出完这俩之后,BB战士的高达机体就停更了,距今快6年了。

再看SDEX,它是面向海外先展开的系列,其他国家15年就开始卖了。但是日本在16年才开始贩售这个系列,属于出口转内销。第一款在日本贩售的SDEX就是《巴巴托斯第四形态》。可以说从日本的角度来看,SDEX是BB战士的延续:16年以后就BB战士没有了,接替它的SDEX开始负责发布SD比例的高达。

考证到这里就很有趣了,16年出的SDEX巴巴托斯,说明书上印着SDEX-10。万代为了和动画放映同步,在海外跳过09号产品,先出了10号产品。在日本就更乱来了,居然第一款就是10号产品。所以日本市场上最早开始贩售SD比例铁血孤儿机体,是SDEX-10号巴巴托斯第四形态。

明明是10号,却率先发售了

在2个月之后,万代推出了《BB战士401巴巴托斯DX版》,和SDEX-10区别在于附送了1~6形态全套外甲。估计那会儿已经购买了SDEX-10的消费者都很崩溃,这也是该产品没有再版难以买到的原因之一吧……

DX就是deluxe的缩写,在日本一般表示豪华版,也就是多几套皮

同样的玩法在《铁血孤儿》第二季播出的时候又来了一遍:为了和动画播放进度同步,万代把中间的09/11~13全都跳过了,直接发售了SDEX-14号。过几个月推出《BB战士402巴巴托斯天狼座DX》,依旧和SDEX-14一样,只是附带了可有可无的机动工兵小车等。

这就是为什么SDEX-10和SDEX-14现如今买不到:它们推出得最早,而万代后来只再版了BB战士401/402,毕竟这俩价格更贵更赚钱。600日元的SDEX是BB战士缩水版,肯定不好卖,也就懒得出了。

接下来说说板件上的关系。

前面我说了BB战士的401/402号,和SDEX的10/14号板件一模一样,那是字面意思上的一模一样,连板件的标签都是一样的,重复的板件都写着SDガンダムバルバトス。这个标题明显是BB战士系列的用法,并且DX字样只在多出来的板件上才有标记,说明一开始就是这么设计板件的。我猜测开发这俩系列的部门本来就是同一波人,当SDEX准备在日本发售的时间正好赶上《铁血孤儿》开播,BB战士又要上新,于是就让两个系列直接共享了板件。

大概BB战士的大头形象已经过时了,新的SD比例更纤细,符合现代审美。而且新技术下的组件细节会更多,刻线丰富。所以我猜BB战士本来就要进化,进化的结果就是以SDEX的招牌重新包装。而401/402可能就是最后的BB战士了……(希望未来的更新打我脸)

玩家嘲讽SDEX分色差,官方吹嘘SDEX可动性高,看板件就知道这俩说法都是错的。BB战士系列一直存在600日元的廉价产品,随着通货膨胀的加剧,600日元能承受的板件数量越来越少,这价位的分色早就变差了。而BB战士包含更高价格的版本,导致一些玩家脑海中只记得高价产品的优良分色。如果放到同一个价位,近几年的产品分色水平很相近——所以要怪就只能怪日元贬值了。

BB战士398号,一样得靠贴纸补色,600日元要什么自行车!

再说可动性,早在2011年,BB战士推出366号飞翼高达EW的时候,开始使用全新的编号为PC-303的连接件,用于活动的关节部分。后续几年所有的BB战士高达产品,除了OO高达7剑/独角兽2号机/新吉翁等这种老机换皮产品,全都在用PC-303。而SDEX系列,所有机型也在使用PC-303,二者可动性上没什么显著的变化。

SDEX-01元祖高达继承了PC-303连接件,倒是偷胶更值得吐槽……

BB战士系列中,上一套被大量复用的连接件的编号为PC-300,最后一次露面是在365号新安州身上。可以说从这台机体之后,SD高达就全部都换PC-303了,大概比较省钱吧。直到18年万代又新开坑了SDCS这个系列,一台机体N套骨架用于骗钱,SD才有了可动性的提高,不过这就是其他话题了。再看更老一点的机体,360号的独角兽的可动连接件叫做PC-7,更加简陋。但是独角兽家族的重点在爆甲,可动性差一点也无妨。

BB战士在366号之后,万代陆续发布了很多使用PC-303的高价位产品。这类高价产品的可动性不会比SDEX的600元产品差,官方大概只是拿SDEX和同机体但是设计时间更老的BB战士做比较,例如329号元组高达等,才能得出可动性更强的结论。SDEX去年出了牛高达和沙扎比,BB战士系列中这俩机体用的也是PC-303,可动性(我猜)没太大区别,只是分色/价格有区别而已。


扯了这么多,还发在Blog里,是琢磨着万一有缘人搜到我这个贴,看完后可以放心的买SDEX。这系列很便宜,而且也没人买,八折以内就能搞定。因为是新货,刻线和细节都很足,手涂喷涂都很适合出效果。再说了,到手价四五百日元的东西,涂坏了不心疼,再怎么涂也比素组漂亮,极大的提升了我的涂装自信。

至于巴巴托斯,BB战士的402不如401好玩。但如果只是为了涂装,能买SDEX就买,像我一样买不到SDEX的话,用BB战士凑一套也挺好,抵制转卖屋从我做起。

之后如果还能想起来更新,就慢慢发一些自己涂装的SDEX上来,也算留个足迹吧。

(感谢dalong.net的丰富资料,有标记的图片都来自dalong.net

2020新的十年

乍一看缺了2019年的内容,其实因为大部分记录都留在了推上。

而因为大环境变得越来越难,所以并不想在公开场合讨论什么了,都是旧的牢骚,没有任何事情变得更好。

今年就不写游戏记录了,得空专门整一篇。

还是记录下年初debug的收获,抓取了pixi.js的的WebGL调用记录,发现做简单的2d游戏用不了几个函数,这里也就47个而已。

它们是:

gl.activeTexture, gl.attachShader, gl.bindBuffer, gl.bindFramebuffer, gl.bindTexture, gl.blendFunc, gl.bufferData, gl.bufferSubData, gl.clear, gl.clearColor, gl.compileShader, gl.createBuffer, gl.createFramebuffer, gl.createProgram, gl.createShader, gl.createTexture, gl.deleteShader, gl.disable, gl.disableVertexAttribArray, gl.drawElements, gl.enable, gl.enableVertexAttribArray, gl.framebufferTexture2D, gl.frontFace, gl.getActiveAttrib, gl.getActiveUniform, gl.getAttribLocation, gl.getExtension, gl.getParameter, gl.getProgramParameter, gl.getShaderParameter, gl.getUniformLocation, gl.isContextLost, gl.linkProgram, gl.pixelStorei, gl.scissor, gl.shaderSource, gl.texImage2D, gl.texParameteri, gl.uniform1f, gl.uniform1i, gl.uniform1iv, gl.uniform3fv, gl.uniformMatrix3fv, gl.useProgram, gl.vertexAttribPointer, gl.viewport

分分类的话,大概是这么几种。

查询设备状态或扩展接口

1
2
3
gl.getExtension
gl.getParameter
gl.isContextLost

操作和设置属性

1
2
3
4
5
6
gl.disable
gl.enable
gl.blendFunc
gl.frontFace
gl.scissor
gl.viewport

清屏和绘制

1
2
3
gl.clearColor
gl.clear
gl.drawElements

操作vertex属性数组

1
2
3
gl.vertexAttribPointer
gl.enableVertexAttribArray
gl.disableVertexAttribArray

操作各种texture对象

1
2
3
4
5
6
gl.activeTexture
gl.createTexture
gl.bindTexture
gl.pixelStorei
gl.texImage2D
gl.texParameteri

操作framebuffer对象

1
2
3
gl.bindFramebuffer
gl.createFramebuffer
gl.framebufferTexture2D

操作各种buffer对象

1
2
3
4
gl.createBuffer
gl.bindBuffer
gl.bufferData
gl.bufferSubData

关于shader的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
gl.createShader
gl.shaderSource
gl.compileShader
gl.getShaderParameter
gl.createProgram
gl.attachShader
gl.linkProgram
gl.getProgramParameter
gl.deleteShader
gl.useProgram
gl.getUniformLocation
gl.getAttribLocation
gl.uniformMatrix3fv
gl.uniform3fv
gl.uniform1f
gl.getActiveAttrib
gl.getActiveUniform
gl.uniform1i
gl.uniform1iv

除了shader部分比较繁琐以外,其他的都很简单,而shader相关的也可以很容易的封装起来。
但实际上由于opengl自带状态,从api调用的录制结果脑补当前场景,非常困难。
比如到底操作的是哪个buffer?究竟哪个texture是活动的?framebuffer的数据都是设置正确了吗?
再加上最好能自动合并渲染批次,所以pixi.js这样的库还是很有必要的。

说到多线程的Bug

刚才提到了多线程,想起来以前遇到的bug,记录下免得以后忘记了。

起因是一个小哥试图优化多线程的loading,在没看完其他代码的情况下,觉得应该在idle的时候把线程的priority降低,给其他更重要的革命工作让出CPU。

然后他没想到的是,loading会调用::Sleep(),结果就是idle之后常睡不醒,优先级太低了其他革命工作都忙得不行,哪有机会让loading出来说话。

他更没想到的是,其他革命工作是依赖于loading的结果的,毕竟革命也要吃饭,没有loading的数据啥也干不了。

所以结果就是loading被负优化,反而变得更慢了,整个游戏也变得更慢。老婆听我讲了这个bug之后做了个特别棒的比喻:

导游带一堆客人去景点,然后让客人自己排队入园。客人问导游你不进去么?导游说我去很多次了你们排着我在外面歇着。没想到门票都在导游手里,一堆人在门口嚷嚷半天谁也进不去,于是都等着了。

所以说优化要先做benchmark,脑补的优化基本都是负优化,没有benchmakr数据支持,你优化个毛线?这事儿我没少干过,就不多吐槽了。

但是必须强调下,文中的优化小哥可不是我,我是修bug的那个。俗话说的好,前人栽树后人乘凉,前人挖坑后人吃瘪。革命工作嘛,总是会有这样那样的问题,别抱怨了好好搬砖吧。

程序员的执念

昨天在看一个吉里吉里(krkr)Timer问题,开启Timer后,游戏会随机崩溃,报错说Timer已经被删除。

题外话,我个人是很讨厌Timer这种东西的。我见过很多糟糕的Timer设计,而且它容易被滥用。使用者会产生一种“我在做并行逻辑”的错觉,而且大部分设计者在设计有关Timer的逻辑时,并没有完全想明白。随口设计出诸如“延迟x秒发生这个,再延迟y秒发生那个”,当这些逻辑交织在一起的时候,无论是设计还是实现都会非常困难,edge case很多,最终导致产生不可预期的结果。

但Timer本身不复杂,对于krkr这样针对电子小说的游戏引擎更是如此。我随口说了句总不至于多线程吧?毕竟krkr内部的解释器是单线程的,所以Timer触发的逻辑肯定得在主线程里执行。但这样一来解释不了Bug的成因,为何会出现删除Timer后OnTimer函数仍然被调用,并且在OnTimer里面操作Timer的时候又说Timer已经被删除?我脑补了两个原因:

1、删除Timer不会终止它的OnTimer函数,这种设计是引擎缺陷。

2、OnTimer触发后就无法被取消了,这种设计也是有问题的。

脑补当然没用,看代码就好了。于是我翻出krkr的源码,找到Timer的实现,还真是多线程……然后就脑补了20种多线程的常见问题。等读完源码,发现逻辑虽然饶了几圈,但bug是没有的,大致上是这样的过程:

krkr首先启用一个单独的线程来处理Timer触发的逻辑,它通过::Sleep来控制Timer的等待(很不精确,但省CPU)。被触发的Timer通过PostMessage传递给隐藏Win32 HWND,然后在独立的UtilWndProc执行逻辑。因为UtilWndProc是由主线程创建的WindowProc callback,所以和解释器处在同一个线程。在这个消息处理函数中,Timer逻辑被丢给了自带的Event模块,Event模块执行实际的OnTimer。krkr保证了如果一个Timer被删除,它在Event中注册的所有OnTimer事件同时也会被删除。已经在等待队列的Timer,检查到自己被删了就直接return,什么都不会发生。

我个人觉得这个Timer实现的太复杂了,可能20多年前CPU宝贵,krkr没有一个持续tick的函数,只能通过多线程来实现吧。而windows里这样传递消息也是krkr固有的模式,其他人提到过:http://bbs.niratea.org/test/read.cgi/krkr/1323994344/389

总之我假设的两个问题都是不存在的。这样一来就是上层逻辑的问题了,于是仔细看了看,发现了真正的原因(WTF,为什么一开始不看?):

1、删除一个krkr对象,并不会自动把对象引用置为void。这个操作非常c++,但对于自带gc的脚本引擎来说还是挺猎奇的。这个错误的假设造成了一些逻辑问题。

2、Timer被多次创建,且保存在parent的成员变量上。这样新创建的Timer会导致旧的Timer引用丢失,而gc并不会第一时间删除这些timer。一旦新的Timer被删除,旧的OnTimer函数被触发的时候,旧的OnTimer函数里通过成员变量访问的“自身”已经是新的Timer,所以会出现问题。

修复很简单,每次创建新Timer前记得删除旧的即可。

这个问题其实可以通过引擎的设计来避免,毕竟用户可能会犯错。OnTimer如果能传入自己,用户就没有必要通过额外的方式保存Timer的引用,这样OnTimer可以保证操作的timer对象肯定是有效的。用户即使重复创建Timer,造成的结果也无非是Timer被重复触发,而不是抛出异常。另外带gc的脚本引擎提供删除功能真的好么?20年前内存大概也非常宝贵吧。

当然,正确的使用Timer才是解决问题的根本。不过我之前就说过,Timer是个容易被误用的模块。尤其是游戏,大部分基于Timer的设计逻辑都是经不起推敲的(个人看法),能少用就少用吧。

Unity的美好与绝望

先说好的吧。可能目前最令我满意的就是IMGUI这部分API的定义,写Editor Plugin和In-game Debug Menu爽到飞起,很快就能出效果。

UI一向是很麻烦的东西,要保存状态,还要异步,还要同步View和Model的数据。很多框架动不动就是MVC,各种模式,用起来都痛苦的一比。这个IMGUI非常简单粗暴,反正也不能用来开发更复杂的玩意儿,设计和使用契合度非常高。

目前用到的其他特色的设计,比如Component Based,和别的商业引擎比起来大同小异。当然从价格和可用性的角度,Unity更胜一筹,以后有机会再多扯点。

主要还是吐槽,就说点看似美好其实比较坑的东西吧。

官方文档

全还是比较全的,这个我主要吐槽两点。

第一是组织方式,有些很重要的东西(比如对象的生命周期),或者说Unity和其他引擎比很不一样的东西(例如特殊目录,Editor/Resources/),隐藏在犄角旮旯等着你来发现。基本上都是在别处找到更直接的教程,然后拿到关键字,再到官方来看细节。

第二是官方真喜欢视频教程啊,不能搜还看得慢,动不动20分钟说点屁事。不能写点图文教程吗?比如IMGUI的各种用法,第三方写的比官方好用多了。

资源加载

三种方式,内在逻辑截然不同。

以Editor内操作为主,基于Reference的这套可能比较适合小游戏,或者非程序员开发的游戏。只要一切资源都是经过Editor操作和绑定的,那么后续过程也都是自动的。官方强力推荐这种,美术和策划友好的东西。

所有不能在Editor上绑定的数据,都需要Load-on-demand。一但牵扯到Load-on-demand,需要动态加载数据,事情就来了。

其实加载资源(Loading)是非常简单粗暴的操作。储存方面就是打个包,把数据和标识存起来。读取方面,只要给定一个标识(比如路径或者id),然后决定是同步加载还是异步即可。同步立刻返回结果,异步就给个handle或者允许callback。这样的底层设计几乎可以满足所有基本需求,其他花哨的玩意儿再上面继续包装即可。

但Unity的坑无处不在。首先是打包,Unity有两套截然不同的资源管理方式,分别对应Resources目录下的文件和Asset Bundle,姑且称为R和A。

R的打包是自动的,所有此目录下的文件都会在运行时打包,方便的很。这么好的东西,官方给出的Best Practice居然是“别用”。写文档的朋友,你以为自己很幽默吗?不能用的东西做出来吃屎呢……

A的打包是手动的,只不过没有现成UI可用,需要在Editor里调用API。但官方文档写的稀烂,打包和加载的过程同DLC的资料搅合在一起,还要牵扯到Cache和Server。乍一看仿佛要启动什么web service做host才能使用,打开还得从WWW下载。其实只要StreamingAssets目录一放,自己写脚本打包就好。

别忙,坑还没完。

R打包出来的资源是不带扩展名的,因为自动打包的时候就是根据扩展名来的,打好就全给删了。加载的时候遇到重名,请提供type。再出现重复我就不知道要怎么玩了……R的路径是相对于Resources的,这个倒还能理解。

A打包出来的资源,标识是写入的时候给定的数据,如果写的时候带了扩展,那就是有扩展名,目测不能重复。

所有“测试的时候想用R,发布的时候想用A”的同学,请自己写wrapper吧……真的好痛苦好痛苦。实际上更好的做法是,测试的时候直接读取Editor里面的AssetDatabase,并不需要使用Resources。官方说的“别用”就是字面意思,但您能提示下还有别的选择吗?直接介绍大家用AssetsBundle真的很不友好啊。

序列化和热更新 Hot-swapping

Unity一大特色就是各种自动,写个public直接就能在Editor上改了。而且改改c#,一回头自动把新的dll热更新上去,数据都还在。

听着很美好,实际情况是,改完代码出现大量Null Reference的异常……

https://gist.github.com/cobbpg/a74c8a5359554eb3daa5

这个小哥大概记录了一下,我踩了半天坑再补充一点:

1、首先是ISerializationCallbackReceiver,调用时机很诡异,Editor下如果你选中了带有这个接口的对象,Inspector会疯狂触发OnBeforeSerialize()。存起来很慢的东西就悲剧了。而OnAfterDeserialize()在Swap的时候会触发多次,目测Editor有创建多个实例,有些数据是没准备好的,还得自助检查。

2、在Editor里创建的各种引用,例如Component都会存下来。但如果动态AddComponent出来的玩意儿就悲剧了,在OnBeforeSerialize()之前就会被干掉,请自己重新动态创建。后来证明只要是Unity的Component,引用都会正确的保存下来,核心的混乱点还是Editor里有多个实例,初始化状态各不相同。

3、虽说需要动态创建,但特么的所有AddComponent这类方法,甚至GetTime都不允许在callback种调用。大概恢复数据的时候是多线程环境?所以只能自己搞个boolean做dirty check,然后在Update()里面实际恢复数据。实际上参考官方的例子,可以在OnEnable里面做恢复处理,比Update要省。

4、虽然官方号称大部分数据类型都可以自动保存,但“大部分”这种说法就意味着你需要被干很多次才能修复“少部分”的问题。比如标记为Serializable的数据,运行时可以为null,但Swap的时候会变成non-null状态。例如字符串变成了””,结构体变成了初始状态,最坑的是Array,里面的null元素会被填充。如果有逻辑依赖于null-check就悲剧了。

以后遇到新的再补充。

补充个新坑:打包的时候如果用BuildAssetBundleOptions.None这个option,看似人畜无害的默认选项居然是用LZMA压缩整个包,第一次开启会做解压缩操作,慢的一笔。最好的方式是使用ChunkBasedCompression,这个选项开包很快。港真我不知道None这个选项除了给网络下载几件衣服的DLC用以外还有什么应用场景,官方文档用这个名字(None是压缩的,咱还提供UncompressedAssetBundle选项哦~),并且用在代码范例真的好么?

2018第一篇总不能是忏悔吧

唉,还是得忏悔。

最近半年玩了600小时游戏的我实在太那啥了……当然代码也写了不少就是了,只能说肝功能严重受损吧。

命运2虽不是那么好玩,三个多月每天肝也搞了160小时。多人游戏果然有毒,凑起伙儿来就停不住。(为将来的MHW埋下伏笔)

后来120小时白了DQ11,感动得不行。DQ可是咱入坑游戏的系列,我要是有空真得写个千八百字的来诉诉衷肠。

华纳的中土世界不对胃口,强行玩了16个小时还是放弃了,还不如AC(这算夸奖么)

巫师3,Dishonored和地平线资料片都随便玩了一两个小时,权当填充空白。

值得一提的是,暗黑3的资料片终于让我给打穿了。前后花了将近20个小时,一路上各种捡暗金装备还是挺爽的。但剧情太弱了,关卡也很弱,有种自动生成的感觉(此处命运2的资料片可以一战)。打完发现我没选赛季人物,直接GG。

好了,最后要说的就是那个了。对的,就是那个。(BGM响起)

《怪物猎人世界》在1月26日发售了!

接下来的一切都发生得如此迅速,等我回过神的时候,已经是3月14日了。在这一天,我成为了苍蓝星,整个大陆的猎人都向我发来祝贺。

\(T__T)/

以后的日子大概需要加速填坑吧——如果岚龙崩霸煌黑没有DLC的话。

BTW,倒是真的弃用国内SNS了,不想打个字还得斟酌半天,累人。

日后尽量写点Unity的使用笔记,还有Javascript的踩坑记录,看时间和心情吧。

2017年底赶稿

一般来说这种事情不会发生,那就是我整整两年都没更新blog……

其实16年研究了不少新东西,17年也是。然而没写blog就导致没有记录,心得体会也就难以保存下来。脑子是个好东西,但时间的力量更加强大,上了年纪的我不能再靠记忆力啦。

这都怪weibo和wx这些碎片化的SNS黑洞(好像之前谁说要弃用SNS来着?)

总之,16年到17年的变化还是蛮大的,物理上移动了很长的距离,生活节奏也变得完全不同。16年玩得最多的居然是掌机,通关了火纹if和皇骑前传。主机方面,跟着太阳战士毫无意外的白了黑魂3之后就放下了,直到2017年PS4的爆发。仁王、地平线、FF12以及命运2吃掉了我大量的业余时间,都是值得一玩的作品,让我重燃了对AAA的信心。

悲剧的是因为办公室和家里各有侧重的缘故,PC平台被基本搁置了,勉强有命运2撑场面。好像随着生活方式的变化,主机+电视变得更加合适,至少可以一个人玩一个人看。

好多年不怎么动弹的我,因为这一圈跑动,主动见到了不少很久没见的朋友。也因为新居住地是旅游胜地,我被动的见了不少朋友。作为社交懒惰症患者,这也挺难得~

还能说啥呢?对2018(的怪物猎人世界)充满期待吧……

2016迟来的忏悔

根本没有弃用任何SNS,有没有!!整一年,什么都没写。

2015超级超级忙,项目的事情就不多说了,都是辛酸泪。但Steam上总算搞出点花样,感觉不错。年底各种折腾装机,Linux,跨平台编译,树莓派等等,玩得杂,忘得快。

当然,这些内容我慢慢补。历年的传统,先谈谈玩了什么游戏。

去年爹妈来过年,帮我稍了块3DS烧录卡,于是乎终于可以玩跨区和汉化的游戏了。通关《勇气默示录》和《逆转裁判》之后,本以为《怪物猎人4》是中文版,有希望继续玩下去,但马赛克太重还是放弃了。妄我买了两份卡带和两份主机。

后来忙得只有碎片时间,就主要攻略炉石传说了。AAA当然不会错过,巫师3让我换了GTX960,然而并没有通关。尝试了Bioshock Infinite,也没有通关。但同样是突突突的Call of Duty-MW3就很快通关,可见5个小时才是最合适的游戏长度。

接下来在华丽丽的九月,各路大作隆重登场,然后我基本上就沉迷了。

首先一口气通关了合金装备3、4、5,还看了各种历代回顾,写了万字长文。为此购买的豪华版游戏和主机简直让我大出血!但PS4绝对值回票价,因为后来玩了上百小时的Bloodborne,最近还白金了。人生第一白,献给这么重口的游戏,我觉得我的性格已经被改变了。

天涯明月刀有很多老同事参与,我也玩了玩,画面不错,其他不想多说。PC上的怪猎OL移植版终于公测,风评不好,不敢试,遂作罢。

去年没怎么多玩Indie。Her Story是个非常妙的作品,深得我心,5小时通关。BattleBlock Theater也不错,玩着挺逗的,然而并不能让我不停的玩下去。Transistor让人眼前一亮,可惜去年AAA攻势凶猛,都统统搁置了。PS4会员给了好多Indie,但只有个潜行的动作游戏我稍微玩了玩,关卡太难弃了。

今年会继续推Dark Souls,并不准备完美通关,太累人了。这种hardcore游戏,体验体验就好,不能耽搁填坑大业。

是的,今年一定要填坑,说什么也不能拖了。

心宽体胖

上午空着肚子研究了半天css和php,把blog的模板重新规划了一下:

  • 页面自适应各种分辨率,这样才对得起我的2k显示器。
  • Archives显示最近50年的文章链接,估计是够用了。
  • 时间显示精确到分钟,大幅缓解了我的强迫症。

最终感想:好饿。