记人生第一次GameJam

CGJ2020参赛记录

Posted by GT on August 17, 2020

关于活动

活动时间是8月14 18:00 ~ 8月16 18:00,游戏、解说视频提交截止时间8月16 22:00。
今年采用线上合作模式,根据主办方赛后直播总结,今年的成品提交数有300+,成品率相当高。


今年的主题是一张图片,需要开发者自己去解读。
不少团队基于箱子、蚂蚁或裂痕做文章,也有不少团队解读出“讽刺过度消费主义”的思想,把箱子看成快递盒子,把蚂蚁看成对“蚂蚁花呗”类信贷产品的暗示。
我们将裂缝解读为人与社会之间的隔阂,由于外界因素需要长期隔离导致个体出现心理问题,裂缝实际上只存在人的心里。

团队

成员

小莫:程序
散童:美术+剧本
洛洛:美术+音乐+剧本
GT(我):程序

作品

https://www.youxibd.com/gamejam/cgjcyber2020/detail/572

制作过程

第一天

没有全职策划岗位,玩法是大家一起讨论确定的。
第一天大家脑暴了不少点子,包括消除类、冒险类、射击类等玩法,然后对各个方案进行时间评估。
但是由于评估工作本身花了不少时间,在讨论完第2个方案时已经深夜,所以第一天结束时就确定用了方案2,这个方案是比较能够表达思想的密室逃脱类文字推理玩法。第一天最后讨论确定了剧本结构,肝到3点多。

第二天

程序:美术输出之前用占位图实现界面和逻辑,第二天结束时已完成所有场景以及核心逻辑
剧本:下午输出两个关卡的剧本
美术:下午输出界面1的大背景图,凌晨迭代了1版

第三天

程序:整合美术、音乐音效以及bugfix
美术:上午输出界面1、2的美术,确定字体,下午输出开始界面以及其他细碎补充
音乐:上午输出所有音乐和音效

第三天16点前打了第一版,发现在推理流程上会卡关,因为无法获取某个关键物品导致推理链断开,进行了修补。之后又加入了credit页面。
测试时间非常紧张,在交互方面几乎没有时间做调优。
上传资料也花了不少时间,录屏、剪辑、声音合成、文案准备 & 表格填写等,晚上20点左右作品提交完成。
赛后观摩官方直播各位大佬作品到22点。

感想

这次制作游戏的过程比较辛苦,但是很能够感受到团队的激情。尤其美术 + 剧本的压力相对来说比较大,但是最后能成功产出非常不容易。关卡设计上规划了2关,包括音乐也制作了第2关的BGM,但是由于时间原因最后只实现了1关。

在主题解读方面可以看出美术同学是很有思想很文艺范儿的,但是在这么短的时间内要制作一个能引起情感共鸣的游戏难度很高,实在是敢想敢做。

对于我来说虽然自己不是文字推理类游戏的爱好者,但是由于这是GameJam,作为一次尝新的机会未尝不可。

非常感谢小莫能拉我参加这次GameJam,之前自己报名过两次线上的小型GameJam,但是因为Solo没动力 or 其他原因鸽掉了,这是我人生第一次成功完成的GameJam,值得纪念!

程序实现

引擎用了Unity。
小莫之前有开发文本类游戏的经验,在处理旁白对话框的时候使用了一套自研的预生成场景节点的方案。
我引入了DoTween做简单的缓动,主要用于过场fadeIn/Out。引入了TopDown Engine里的Feedback部分用于声音处理。
除了这些之外都是现撸的代码。

睁眼shader

最后分享一段模拟睁眼效果的shader(最后没有被采用,美术妹子做了一套效果更好的序列帧)。
主要思路是用拉长的sin函数模拟眼睛的边界,分时间段调整sin函数的振幅。
在制作这个shader过程中掌握了用分段函数控制动画效果的方法。
open_eye.gif

shaderToy版本

https://www.shadertoy.com/view/3tsfWB

Unity版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#define PI 3.141592653589793

float Band(float v, float start, float end, float blur) {
    float up = smoothstep(start - blur, start + blur, v);
    float down = smoothstep(end + blur, end - blur, v);
    return up * down;
}

fixed4 frag(v2f i) : COLOR {
    half2 uv = i.uv;
    uv = uv * 2.0 - 1.0;
    uv.x *= 1920. / 1080.;	// hardcode resolution

    fixed3 col = fixed3(0.0, 0.0, 0.0);
    float t = _CustomTime;

    // part1, 大幅上升
    float part1 = abs(sin(clamp(t, 0., PI) * 0.5));

    // part2,小幅上下波动,此时part1停止
    float part2 = -sin((clamp(t, PI, 2.*PI) - PI) * 2.0) * 0.05;

    // part3,大幅上升
    float part3 = sin((clamp(t, 2.*PI, 2.5*PI) - 2.*PI));

    // part3时候范围扩大
    float scale = 1.0 + sin(clamp(t, 2.*PI, 2.5*PI) - 2.*PI);

    // float amp = abs(sin(u_time * 0.500));
    float amp = part1 + part2 + part3;
    amp *= scale;

    float top = sin(uv.x / scale + PI / 2.0) * 0.5 * amp;
    float mask = Band(uv.y, -top, top, 0.01);
    col.rgb = fixed3(mask, mask, mask);

    return fixed4(col, 1.0 - mask);
}