我所制作的《多元窗口》大概率是一个前人未曾涉足的游戏领域,光是在代码方面就有着不小的开拓难度,更别说游戏内容本身的设计了。在机核Booom-lab做出这款游戏的原型时,就深感这套方案实现的不易,所以也将当时的版本开源并做了教程,希望有人能接替我的成果,那时的我是做不动了。不过后续我并没有发现有谁使用了这套方案,然后我还在某个比赛上拿了一个奖,所以我决定再次重启该项目,并且一切都按照我个人能承担的最低成本去做。
现在游戏已经在Steam上发布试玩版了,搜索《多元窗口》就可以找到。当然这个版本绝对算不上多么细致,完成度也很有限,我也想未来继续更新这个试玩版。不过眼下,这套程序实现方案已经极大的压榨了我的精力,能做到这样我也就暂且满意了。秉持着互联网的分享精神,也决定来机核社区向各位开发者分享一些很可能以前从来没有人研究过的“怪东西”。
与Godot的单一进程多窗口不同,我的游戏中需要玩家打开多个游戏进程,实打实的需要玩家启动多次游戏,而这与Steam的模式兼容性极差,经过我的研究,我找到了一些很怪的方案。
在开启游戏的时候,Steam会检测开启的进程与其所有子进程,这意味着在通过Steam开启的游戏中,直接利用代码去开启新游戏时,新开启的游戏会成Steam开启的游戏的子进程,也会被Steam管理。这一问题甚至还导致了即使游戏关闭,Steam也认为游戏在运行,必须重启才能解决,导致游戏时长异常(甚至突破50小时)。
关于这个问题,可能有人会想,通过CMD或者PowerShell运行是否可行,先运行一个其他的程序,再通过其他程序中转行不行。答案是行不通,即使是CMD、PowerShell还是其他的程序,只要这个进程是由当前游戏打开的,那么都会成为当前游戏的子进程,然后新开启的游戏一样会成为子进程,从而被Steam检测到。
问题的关键是“如何让一个进程创建一个不是子进程的进程”,这个问题估计AI都给不出答复,我最后是在stackoverflow上找到了一段相关代码。这段代码利用了ManagementClass,通过DETACHED_PROCESS这个标记去让系统创建新的进程。并且这个功能似乎不能在Unity中使用,我通过一个单独的C#项目复刻了这段C++代码,然后将编译后的文件放入我的游戏项目之中,在游戏中执行该文件,去创建不是子进程的新的游戏进程。
代码出处:https://stackoverflow.com/questions/12068647/creating-a-new-process-thats-not-a-child-of-the-creating-process
之前有朋友把游戏给某游戏大厂的员工试玩,对方还以为这个游戏的进程沟通是利用了共享内存或者管道通信之类的方法。对于操作系统来说,那些方法确实很管用,但是对于Unity引擎来说,使用进程通信还是太复杂了,对于开发的效率来说很难受。最终我使用了联网架构,通过现有的Netcode组件在127.0.0.1本地回环地址中进行联机,实现了多个窗口的信息传递。把复杂的进程沟通问题转化为简单的多人游戏制作(不过目前这套方案还存在一定的延迟,我不理解为什么本地自己联机还会有延迟,我还在研究如何优化)。
所以现在,游戏进程中有一个进程是主机,其他都是客户端。但是打开一个新进程的时候,要如何知道这个新进程该是主机还是客户端呢。我用了一个十分简单粗暴的方案,就是先作为客户端进行链接,如果连上了,那就作为客户端呆着吧。如果发现没连上,那就作为主机开启新的连接。现在想来还是挺变态的方案,其实也可以根据名字检测进程,根据当前进程数量来判断主机还是客户端,但是这样就会导致一个更变态的东西消失了——不同游戏之间的连接。经过我的测试,只要网络部分的架构一致,即使是不同版本的游戏甚至是完全不同的游戏,他们之间都是可以相连的。我还不确定这部分能做到什么份上,但起码我不想丢掉这份“可能性”,希望能在未来实现这样的玩法。
众所周知游戏应该只会检测在游戏中输入的按键,在游戏外输入的按键是不会被检测的,而这对于多窗口游戏来说可不是好事。为此,我找到了一个检测玩家全局按键输入的方案,注册了Windows系统的键盘钩子,通过更加底层的系统钩子来监听玩家的键盘。虽然这会导致即使玩家不在专注游玩游戏时,比如开着游戏但是切窗口聊天,也会触发我的游戏中的钩子事件,但这确实是一个解决多窗口之间按键交互的问题。
除了全局按键检测,其实我还实现了一个更加独特的东西,拦截并且模拟按键输入。也是键盘钩子,不过加上了一点额外的检测,如果我发现现在的输入是玩家的输入,就禁止这个输入在系统中被激活,然后利用keybd_event执行一个模拟输入。从某种意义上来说,这有点像是外挂程序的原理。而机核发行的S4U中,我看到这个游戏中输入的玩法感觉很有意思,我突然想到,其实我可以在玩家的电脑系统中实现这里的功能。
设想一下,一个玩家刚玩了我的游戏并关闭,但是我的游戏悄咪咪的留了一个“赛博嘴替.exe”进程没关,然后再利用一些比较复杂的黑科技,检测到了玩家正在和某人聊天。这时候程序激活,玩家按下按键时,打出来的字都不是他想要的,而是提前设计好的。等会,我是说,我在做的其实是一款联网游戏,不过是把联网部分改成本地而已。那如果我做了远程联网功能,并且由我这里担任服务器,我来决定玩家怎么骂(现实里的)公司领导,那么我不就可以真的在现实里玩游戏,成为人们的赛博嘴替了吗?
天哪,我都不敢想Steam会不会给我这个游戏过审了,这就是一个赤裸裸的伪装成病毒的游戏,而且我想谁会不愿意给一个Unity游戏开放管理员权限呢。所以在此警示各位,Unity游戏很有可能也不安全,甚至比你我想的都更有可能是一个木马病毒。(我本人还是想做正经游戏的,以上内容暂时还不会出现在《多元窗口》与其试玩版中,我保证)
还是收回刚才狂妄的病毒想法吧,如果游戏不做好玩,又怎么吸引玩家来下载这个病毒呢。额,我是说我要做一款好游戏,不应该去想什么病毒不病毒的。但,在Unity里做多窗口游戏就是纯纯的折磨。传统的游戏制作只需要点击一下播放按钮,就可以直接在编辑器里看到游戏预览了,但我做的可是多窗口、多进程游戏。每次修改调试,我都必须完全导出游戏,忍受这个该死的慢的要死的build过程(咬牙切齿),在新的窗口中检查游戏内容有没有bug。这也就是我开发进度缓慢的最大原因了,我现在一直都在用这样的土办法进行调试,鬼知道我到底导出了几百次还是几千次这个游戏。
我目前用到了《Cato》开发者分享过的 InGame Debug Console 插件,这确实很好用,完全符合我的游戏。不过我其实突然想起来,似乎HotReload插件也具有着远程连接的功能,我打算接下来研究下能不能不导出游戏,直接预览更改。
还有就是在Steam中预览更改,其实不需要上传、打包、再在Steam里更新,直接把导出的游戏拷入到本地的Steam游戏安装文件夹里覆盖,就可以直接测试了,也是“俺寻思”的简单有效做法。哦对了,我还给SteamAPI做了一个编辑器判断,如果是编辑器,则不激活SteamAPI,这样就不会在开发的时候导致Steam认为游戏正在运行了。
总而言之,言而总之,这里就是《多元窗口》试玩版中一小部分的怪东西了。我兜里还有更多更有趣的黑科技,不过现在还不是时候。若是各位感兴趣,还请务必打开Steam,搜索“多元窗口”,下载试玩版玩一玩,加个愿望单甚至给试玩版写点评测都是很好的。如果游戏反响不错,我也就有动力去研究更加有意思的东西,在未来为各位分享更多内容。
在电子游戏边界的开拓之路上,总有未曾有人见过的东西值得分享。
评论区
共 2 条评论热门最新