欢迎光临散文网 会员登陆 & 注册

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

2020-04-13 17:59 作者:皮皮关做游戏  | 我要投稿

作者:QXYO


前言

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

我们先来看看最终结果:

可配置的弹幕样式

本文主要内容:

1. 3D场景俯视角射击

2. 可配置化弹幕

3. 还原东方弹幕

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


一、3D场景俯视角移动

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

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

【反向元气骑士】用unity实现俯视角射击是一种怎样的体验


当然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;

 

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

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

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

        int num = bulletData.Count / 2;

        for (int i = 0; i < bulletData.Count; i++)

        {

            GameObject go = pool.Get(bulletData.Position, bulletData.LifeTime);

            //从对象池中获取,对对象池不了解,不需要优化的话可以直接实例子弹的预制体

            Bullet bullet = go.GetComponent<Bullet>();

            go.GetComponent<Renderer>().material.SetColor("_EmissionColor",bulletData.color);//修改子弹外发光颜色

            bullet.BulletSpeed = bulletData.Speed;

            if (bulletData.Count % 2 == 1)

            {

                go.transform.rotation = bulletData.direction * Quaternion.Euler(0, bulletData.Angle * num, 0);

                go.transform.position = go.transform.position + go.transform.right * num * bulletData.Distance;

                num--;

            }

            else

            {

                go.transform.rotation = bulletData.direction * Quaternion.Euler(0, bulletData.Angle / 2 + bulletData.Angle * (num - 1), 0);

                go.transform.position = go.transform.position + go.transform.right * ((num - 1) * bulletData.Distance + bulletData.Distance / 2);

                num--;

            }

        }

 

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

【Unity】工具类系列教程——对象池!


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

        if (LimitI > CdTime * 50)

        {

            ...

            //执行射击方法

            LimitI = 0;

        }

 

三、还原弹幕效果


1.波与粒的境界

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

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

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;

        }

 

附上具体参数

2.怨灵猫乱步

可以看到子弹是从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;

 

来看看效果

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

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

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



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

提取码:mpik



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

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

3D俯视角射击——用Unity还原东方弹幕(上)的评论 (共 条)

分享到微博请遵守国家法律