0%

复刻:挑战12小时做一款游戏

我真的是,想起一出是一出,终于也要对Unity下手了。前几天看到油管上有一个up主,挑战12小时做一款游戏,既然看到了就很想挑战一下,看看我和大佬的差距,也是保持每天编程的手感。
游戏下载传送门

大佬的12h即是从早到晚连续的12h,包括吃饭。我是绝对做不到了,毕竟我也不是大佬,而且每天也有其他的事情要做,于是采用离散计时法,随做随计。

4h59m:

把player controller这一大块完成了,包括slow motion,ball squeeze和tail这些花里胡哨的东西也还原了。球的运动使用addForce()来做,Slow motion通过改变timeScale实现,球的变形通过改变gameObject的scale,tail一开始想得复杂,后来发现unity自带就有tail renderer。然后用slider去实现了aim line。其实也不算复杂,比较麻烦的就是各种数字的设置,力和速度的大小,重力和阻力什么的。
这里有一个bug尚未解决,就是addForce之后,球的运动有时候会产生偏移,即便是关掉阻力和重力也是如此,尚不清楚原因。
然后做相机追踪,包括移动缓冲和自动缩放。此时就遇到了第一个大问题。
相机跟随时物体抖动,速度越快抖动越剧烈,查了很多方法,也看了Update、FixedUpdate、LateUpdate各种关系依然无解,终究还是在国外某不知名论坛看到了解决方法。(百度不给力啊,还是谷歌靠谱)解决办法是把rigidbody里的interpolation打开,插值之后就能够纵享丝滑。不过关于Update这方面还有很多值得深挖的内容,以后得好好学一下。

5h48m:

制作敌人的碰撞检测,又遇到了个问题。碰撞之后丝毫无反应,debug发现连碰撞函数都没有进去,但是程序也没给我报错呀。
后来发现,我做的是2D游戏,设了Collider2D,在程序里就不能只写Collider,不然啥反应都没有还不会报错的。妈耶。

6h50m:

particle system做击中效果, 最烦人的一个部分,美工从来不是我的强项,没办法一个一个参数去试效果。
击中敌人爆炸,击中后先让sprite和collider消失,等particle system播完了再销毁对象。Like:

1
2
3
4
5
6
7
8
9
10
11
12
void OnCollisionEnter2D(Collision2D other) 
{
if(other.gameObject.tag=="Player")
{
//print("hit");
explosionAudio.Play();
sr.enabled = false;
col.enabled = false;
ps.Play();
Destroy(gameObject,6);
}
}

7h24m:

post processing stack,看起来很厉害的东西,实际也很厉害,但是用起来没有想象中那么难。简单地说就是类似于相机滤镜一样的东西,不管你原来的场景做得多粗糙简陋,把它加进去之后简直化腐朽为神奇。这一块倒是没花很多时间,因为只是随便加了个效果,实在要达到大佬那样的视效还得仔细地去调参数,先放一放吧。

7h53m:

health bar & player health,做UI也很是繁琐,索性直接用个slider就完事了,美中不足是血条为0时会有一点残余,是由于这一点位置是原来slider的handle占着的,删掉handle就露出来了,留着后面想办法吧。

8h44m:

enemies spawn,既然大佬说是直接google的,那我也就直接借鉴大佬的了,只是参数还得再慢慢调。
这条公式具体如下:

1
float yPos = Mathf.Floor(Mathf.Abs(UnityEngine.Random.Range(0f,1f) - UnityEngine.Random.Range(0f,1f)) * (1 + 100 - (-2)) + (-2));

当然参数是我自己调得,公式的作用就是让敌人生成的位置尽量靠近底部。
公式确实很神奇而且有效,学到了。

9h22m:

玩家死亡游戏结束,说实话这里没想到什么好方法,试过各种方法都有一点不完美,姑且是先清空速度停止位移禁用script,后面看看能不能写成boardcast的形式。

9h49m:

完成计算分数UI,用public static int 来构造类变量使别的类可以调用。

11h34m:

做了game over界面,你问我为什么这里用了将近两个小时,说来可笑,做完game over菜单其实也就十几分钟,然后打算加上游戏重新开始功能,其实用LoadScene()一行代码就可以搞定了,但是做完运行的时候发现restart按钮点第一下游戏重新开始了但是Game over界面还在,点第二下才消失,于是花式改代码花式查资料查api,心态崩了.jpg。就在大脑停止工作的前一秒,想到在start()的时候给判断游戏结束的参数重新赋值而不是在LoadScene()的时候重新赋值,就可以了窝。那一瞬间的心情,想必是悲喜交加的。
但是,anyway,游戏总算是能做出个完整的样子,此时距离12h的期限只有不到半小时。

12h13m:

虽然一直以来都是音乐苦手,但是碰撞爆炸音效什么的也大概是搞定了。顺便学会了用数组去获得object下的同类资源这么一个操作。Like this:

1
2
3
4
5
6
public AudioSource[] AudioClips = null;
void Start()
{
//...
shootingAudio = AudioClips[0];
}

即便本科的时候玩过一阵子FL studio, BGM也是真的搞不来,由衷佩服全能的大佬。

至此,大佬花了6小时包括吃饭上厕所以及构思。而我只能勉勉强强踩着12h的期限做出个仅仅是称之为“能玩”而不能称之为“游戏”的半成品。而且做的时间也是断断续续的。要说达到了大佬一半的功力怕是在侮辱大佬。
再往下做,就是一些细枝末节的东西了,优化游戏体验,更需要细心的去做,虽然内容不多,但是难度可不小哦。

12h40m:

撞击时相机抖动,这个地方搞了大佬一个小时多,我却意外的顺利【摊手】。撞击时给相机位置加个随机数,撞击过后再回到原来的位置就成了。于是可以得到完整的相机代码包括跟随与缩放功能如下:

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
39
40
41
42
43
void LateUpdate()
{
// camera follow
targetPos = player.transform.position + offset;


if (isHit)
{
//camera shake
if (shakeTime > 0)
{
transform.position = originalPos + Random.insideUnitSphere * shakeAmount;

shakeTime -= Time.deltaTime * decreaseFactor;
}
else
{
shakeTime = 0f;
transform.position = originalPos;
isHit = false;
shakeTime = 0.1f;
}
}
else
{
transform.position = Vector3.SmoothDamp (transform.position, targetPos, ref moveSpeed, dampTime); //player.transform.position + offset;
originalPos = transform.position;
}


// camera zoom
float desiredZoom = defaultZoom + Vector3.Distance(transform.position,player.transform.position);
if(desiredZoom>18)
{
desiredZoom = 18;
}
Camera.main.orthographicSize = Mathf.SmoothDamp(Camera.main.orthographicSize, desiredZoom, ref velZoom, zoomSpeed);

if(transform.position.y < yMin)
{
transform.position = new Vector3(transform.position.x,yMin,transform.position.z);
}
}

13h20m:

加了两种新的enemy类型,绿色的碰到就必死,紫色的碰到就给player来一个AddForce带你乱飞。

14h18m:

让镜头之外的物体在一段时间后自动销毁,避免占用太多资源,用这两个函数来判断:

1
2
3
4
5
6
7
8
9
private void OnBecameVisible() 
{
isVis = true;
}

private void OnBecameInvisible()
{
isVis = false;
}

然后加入combo机制,说实话,combo这个一开始想错方向,绕了好久的弯路。
最后加上一个esc键退出功能,就这么完结了吧。实在是累了肝不动了,而且也是超时了很多,在功能上面只能说尽力去模仿原作吧,然而bgm实在是搞不来,用别人的音乐又怕什么版权纠纷,虽然我这也不算用于商业用途。至于后来他还实现了黑洞,这个有考虑过也有了一点思路,但是做起来要花点心思,最近开始要渐渐忙起来了,所以就先搁置一下吧。

虽然一开始确实是兴趣使然地去做这个游戏,但其实稍微想想的话,这个游戏的可扩展性很强,还能搞出更多新的花样,比如排名机制,比如闯关机制,再比如更多的敌人和联机模式。说起来,简单的图形更能让玩家和游戏开发者都专注于玩法上,很多优秀的游戏从来都不是单凭画面拿下市场的,甚至画面粗劣却拥有一大票拥趸者的游戏比比皆是,像elona,像和班尼特福迪一起攻克难关….

不管怎么说,12小时的游戏开发挑战就先在这里画个休止符吧,毕竟也是一天一天的闲暇时间凑出来的12小时,也是蛮累的 XD