3D俯视角射击——用Unity还原东方弹幕(上)

作者:QXYO


前言

之前我们的专栏中介绍过2D的俯视角射击,这次就来试试在3D场景下的实现。移动射击的实现方法差不多,所以本次的主要目标是在3D场景下还原东方的符卡(弹幕)效果。

我们先来看看最终结果:

3D俯视角射击——用Unity还原东方弹幕(上)

可配置的弹幕样式

3D俯视角射击——用Unity还原东方弹幕(上)


本文主要内容:

1. 3D场景俯视角射击

2. 可配置化弹幕

3. 还原东方弹幕

注:为了提升表现效果而使用的模型动画、屏幕后效(PostProcessing)等方法不在本次教程范围内。同时本文只写出了部分关键代码,完整项目下载详见本文末尾。


一、3D场景俯视角移动

实现目标:键盘移动,鼠标射击。不射击时面向移动方向,射击时面向射击方向,转向有转向速度,射击方向为鼠标点击方向。

在之前2D俯视角射击中已经介绍过移动的方法,这里就不再赘述,想要了解的同学可参考:

【反向元气骑士 用unity实现俯视角射击是一种怎样的体验】:https://zhuanlan.zhihu.com/p/97169528


当然3D人物转向应需要转向速度,否则会显得很突兀,可用 Quaternion.LookRotation控制转向, Quaternion.Slerp控制转向速度。


二、弹幕可配置化

实现目标:通过修改Inspector面板中的参数,即可实现简单的弹幕样式。

本次主要实现两种弹幕样式,散射弹幕和平行弹幕。实现这两种样式需要的参数(BulletData)如下。

public int Count = 1; //一次生成的子弹的数量

public float LifeTime = 4f; //子弹生命周期

public float CdTime = 0.1f; //子弹间隔时间

public float Speed = 10; //子弹移动速度

public float Angle = 0; //相邻子弹间的旋转角度

public float Distance = 0; // 相邻子弹的间隔

public Color BulletColor = Color.white; //子弹的颜色

public Vector3 R_Offset = Vector3.zero; //初始旋转的偏移量

public Vector3 P_Offset = Vector3.zero; //位置的偏移量


首先创建个球体作为子弹预制体,OnEnable时,在FixedUpdate实现移动,当规定了子弹的位置和方向,子弹就会朝着正前方移动。

transform.position = transform.position + transform.forward * BulletSpeed * Time.fixedDeltaTime;

然后是通过设定的参数实现弹幕样式:散射弹幕,如下图所示,以角色正前方为初始方向,当单次弹幕数量为奇数或是偶数时,子弹旋转角度的逻辑是不一样的。

3D俯视角射击——用Unity还原东方弹幕(上)

奇数时,角色正前方会发射子弹,左右两侧的子弹角度为角色(当前角度+-旋转角度)

3D俯视角射击——用Unity还原东方弹幕(上)

偶数时,角色正前方不会有子弹,左右两侧的子弹角度为(当前角度+-旋转角度/2)

同理平行弹幕也不相同,下面给出代码,其实就是一个简单的数学运算。

代码中使用到了对象池相关知识,在本专栏之前文章中有详细介绍过对象池,详情可见:

【Unity】工具类系列教程——对象池!https://zhuanlan.zhihu.com/p/30575559


控制射击间隔时间可以用协程的方式达成,我这里用了一个偷懒的方法:因为在FixedUpdate中每秒是固定运行50次(可在Project Setting中修改),所以在FixedUpdate中可以用i++来控制时间

if (LimitI > CdTime * 50)

{

...

//执行射击方法

LimitI = 0;

}

三、还原弹幕效果


1.波与粒的境界

用简单的函数绘制成优美的弹幕,在文章开头大家应该已经看到了所实现的效果,这里再放上一张对比图。

3D俯视角射击——用Unity还原东方弹幕(上)

新建个空物体用来发射弹幕,除了之前提到的弹幕所需参数外,还需要

public float SelfRotation = 0; // 每帧自转角度

public float AddRotation = 0; // 每帧自转角度增量

实现其实非常简单,每次发射5发子弹,角度间隔为360/5°,然后发射子弹的物体每帧进行越来越快的旋转,弹幕就能形成上面的效果。

SelfRotation += AddRotation;

SelfRotation = SelfRotation >= 360 ? SelfRotation - 360 : SelfRotation;

//为了防止数值过大进行了限制。

var q = Quaternion.Euler(0, SelfRotation, 0);

transform.rotation = transform.rotation * q;

if (LimitI > CdTime * 50)

{

BulletManager.Instance.ShootConfig(bulletData, m_bullet1_pool);

LimitI = 0;

}

附上具体参数

3D俯视角射击——用Unity还原东方弹幕(上)

2.怨灵猫乱步

3D俯视角射击——用Unity还原东方弹幕(上)

可以看到子弹是从11个不同位置生成,每次生成4圈弹幕,每圈弹幕角度随机,经过一定时间后才开始移动。

子弹的延时还是通过记录一个DelayI来实现。

void FixedUpdate()

{

if (Shoot)

{

Shooting();

}

else if(DelayI > DelayTime * 50)

{

Shoot = true;

}

else

{

DelayI++;

}

}

private void OnEnable()

{

DelayI = 0;

Shoot = false;

}

同时还需要一个与发射中心距离的参数

public float CenterDis = 0; // 与发射点的距离


修改子弹位置到中心点前方

go.transform.position = go.transform.position + go.transform.forward * bulletData.CenterDis;

来看看效果

3D俯视角射击——用Unity还原东方弹幕(上)

详细参数可以下载本文末尾的项目自行查看。想要完美还原的话,剩下的就是将发射物体移动到指定位置、调整延迟时间等,可以使用Dotween等方式实现,本次就不再进行展示了。

由于篇幅原因本次只展示了这么多,有兴趣的同学可以自己尝试去实现其他符卡。

最后不要忘了这是在3D场景下的弹幕,所以这样也是能做到的。

3D俯视角射击——用Unity还原东方弹幕(上)

工程地址:https://pan.baidu.com/share/init?surl=JEXp9FsNswaihwSBkiHs-Q

提取码:mpik


对游戏开发学习感兴趣的盆友,欢迎访问:http://levelpp.com/

同时,也欢迎加入游戏开发群搅基:610475807


分享到:


相關文章: