在Unity的所有免费资源里,如果只能推荐一个,那么我一定是毫不犹豫地选Fungus,这是一个超级无敌棒的插件,而且居然是免费开源的。
Fungus的主要功能是做剧情对话,如果是做传统的2D AVG游戏,这个插件基本上能够完成所有你需要的功能,比某些流氓软件功能多几倍还不会觊觎你作品的版权,当然,2D AVG的开源引擎其实比较多,除了Fungus以外,比较火的还有Ren’py、Twine等等,而后两者在写自定义插件时分别用的python和前端三件套语言比起Fungus需要的c#或者Lua还用得更广泛一点,但我更推荐Fungus的原因,是因为它在3D游戏中也有非常不错的应用空间,尤其如果你需要做一个重剧情轻任务的3D游戏时。
哪些情况适合用Fungus
1.2D的AVG游戏,这是Fungus最初也最本质的定位,自身功能非常强大,基本我能想到的传统2D AVG游戏里可能有的功能它都有直接提供,不需要自己额外写插件,非常适合擅长美术和编剧但编程苦手的人群,只要没有特别独特的需求,甚至可以零编程实现。而如果有特殊需求,也可以用Fungus来作为最基本的框架,然后对特殊需求部分自己写插件作为补充。
2.3D游戏中的剧情对话系统。Fungus支持Unity的3D碰撞检测,所以可以利用这个来做剧情触发,而Fungus的分支选项菜单、变量设置和条件触发、以及多样的文字呈现方式,基本能满足剧情对话的需要,而这样的功能如果完全自己来做,会多出几百行代码以及大量debug的工作量,而用Fungus的话,就只需要把自带的丑出天际且不适合3D的UI改一下就好。而且最棒的是,结合Unity的EventSystem和自定义c#脚本插件,你能用它做更多的事情,这个后面细讲。
3.Fungus不适用于做任务系统,因为它没有物品清单系统,如果只涉及到很少的物品,可以用里面的变量功能来实现,当然如果涉及物品多且复杂,也可以自己写插件添加进去,但这样就没必要用Fungus了,选一个任务类插件然后自己再在它的基础上修改更省力。
Fungus使用Tips
1.有必要一看的资源:
1.1.Fungus的包安装好后会发现它自带有一套example scene,可以挨个运行一下方便看都有哪些基本功能。
1.2.Fungus的官方指导视频,B站有较完整的英字搬运和不太完整的中字搬运。
1.3.Fungus的官方文档,
1.4.Fungus的非官方教程不多,质量高的更少,至少在没科学上网的情况下是这样,对我有帮助的主要就这一个。吐槽一下有些做教程的up主一定自己压根就不大用Fungus,按他的代码在他视频的场景里没问题,但只要他在场景里放第二个物体设第二个触发对话的trigger马上就会发现出bug,如果是刚接触Fungus和Unity的新人能给带沟里去。
1.5.Fungus的交流论坛入口,第一个进不去了,第二三个可以。
其中,
1.1和1.2建议在使用前看,可以二选一看就行了。
1.3和1.4建议在看了1.1或者1.2或者使用中遇到问题时再看,因为在对基本功能没有概念的时候,看它们会有点太抽象不知道在说什么,但如果对基本功能有概念后,尤其在带着使用中的问题时,看起来的收获就会比较大。
强烈建议在用了一段时间后拉通看一遍1.3,会发现好些用了很久但一直没发现但非常实用的功能,哪怕1.1和1.2都可以不看直接摸索着用,但1.3真的值得花一个下午通拉过去。要说它有什么不足之处,主要是Fungus一直在更新,但文档并非所有地方都同步更新,但可以通过对照其它章节来补足。比如在Document-Home-Blocks-Setting an Event Handler中,列举的触发对话的方式是非常古早的,后面更新的而且我们经常常用的触发对话方式都没有写进去,但在Document-EventHandlers页面中就分类列举了所有触发方式。
1.5适合在使用一段时间后遇到无法解决的问题时使用,我目前为止还没用过,但看到上面Fungus制作团队和一些热心使用者会回答问题,其中制作团队直到本月依然有活跃答疑。
2.Fungus在3D游戏中使用的注意事项:
想主要说一说3D,一是因为官方资源里基本是2D相关的,而3D的比较少;二是因为我自己主要是做3D的,在3D上踩过的坑和想到的点比较多。
1里列举的资料里有提到的就不赘述了,这里主要列一些实际使用中容易踩坑的地方和一些个人使用经验。
2.1.碰撞检测与触发对话的相关:
2.1.1.需要把flowchart作为组件挂在主控角色这个物体上,才能触发各种碰撞检测。千万不要直接tools-fungus-creat-flowchart,然后你会发现怎么都触发不了对话呢。
2.1.2.尽可能用trigger而不是collider来触发对话,这个主要是unity的锅,无论是fungus还是自制ui或者别的什么,collider平均3次里能成功触发1次就不错了,而trigger则很少bug。
2.1.3.一定一定要在trigger上设置tag,需要格外注意的是,不同的挂了trigger的物体,无论名字再八竿子打不着,距离多十万八千里,只要tag一样,那么触发一个就会导致所有的全被触发,所以,除非是打算几个物体触发任何一个都触发相同剧情,否则tag一定要分开,具体来说,不同叙事方法对tag的用法不同,这个在2.2里详细讲。
2.2.不同叙事逻辑的实现技巧:
2.2.1.线性叙事:一个tag即可,用好set active是关键。
在scene的hierarchy中,对所有的剧情触发物体,只有第一个设置为active,其它全都不勾选。然后在flowchart中,对于第一段剧情的block触发方式设定为trigger enter,触发后先把当前这个触发物体的set active给变成否,然后剧情走完后把第二个剧情触发点的物体给set active,接下来会按顺序进行到的每一个剧情触发点都以此类推,触发后把当前物品取消激活,同时给下一个触发点激活,直到最后一个剧情触发点。
2.2.2.主线-支线叙事:一条线一个tag,结合set active和variable来实现。
主线所有涉及到的触发点都共用一个tag就可以了,结合set active,按前面2.2.1的方法来实现。同时,对每一条支线需要设置一个tag和一个variable。
对所有variables的默认值都设为0,在主线进行到某个阶段可以触发某条支线剧情时,在主线的block里set variable设置支线甲int=1,然后在触发支线剧情的触发物体那里,除了用这条支线的特定tag去触发以外,还需满足if 支线甲int==1,这样就可以避免在主线没发展到可以接支线任务的时候就被提前触发了。支线任务如果有多段触发点,且多段出发点也是线性的,那么也可以结合set active来挨个激活每一个触发点,以保证每次是在正确的地方只触发下面一步的剧情。然后用同样的方法处理支线乙支线丙支线丁等等。
2.2.3.开放世界叙事:归类tag池,综合应用set active、variable、text variation。
因为不知道玩家会先去触发哪个,所以原则上来说,每一个线头都需要一个独立的tag,线头可能是一段持续好几个触发点的剧情,这个用前面2.2.1的方法结合set active来做就可以了,涉及到必须先触发这个线头并且走到哪一步,才有可能触发到那个线头的,用前面2.2.2的方法综合set active和variables来做,第三种线头是那种同类事物,接触任何一个都可能开展类似的对话,并且也许接触第一次第二次第N次触发的对话不一样的,这种共用一个tag,并且全部set active,用text variation来实现。对那种遇到第几次对话不一样而且有特定顺序的,用[1|2|3|...|n],对那种遇到任何一个都随机从一个对话池里选其中一句出来的,用[~1|2|3|...|n]。
2.3.结合Unity引擎的自身组件实现更多功能
2.3.1.前面提到过Fungus里有set active这个命令,也就是激活某个在hierarchy里处于未激活状态的物体,那么靠这个我们可以让Fungus里的剧情发展到某个地方时,激活某个特定的物体,这样直接实现某些功能,前面已经举出过例子了,不赘诉。
2.3.2.类似的功能还有spawn object以及destroy,前者可以利用它来生成一些hierarchy里没有但有预制在prefab里的物体,比如刷出小怪或者刷出资源等等;后者则是相反,销毁在hierarchy里现存的物品。
2.3.3.除此之外的大头是Invoke命令,可以直接对接调用Unity的Event System,实现里面所自带的或者自己写了挂上去的c#脚本所附加给它的特殊功能,这样让Fungus可以实现的功能边界一下扩展开了。
2.3.4.另外一个大头是UI命令,可以直接对接调用Unity的原生UI系统,这样一方面可以解决一些显示问题,比如根据剧情分支不同,某个游戏物体上的字显示不同,就可以通过这个来实现;另一方面也可以结合前面的Invoke命令结合Event System来实现菜单问题等等。