<Unity实战> 弹幕子弹效果--圆形,扇形,单螺旋

<Unity实战> 弹幕子弹效果–圆形,扇形,单螺旋

需求分析

弹幕其实就是指子弹,弹幕子弹效果是指发射出来的子弹不是单一的一条直线,而是有自己的轨迹或者自己的方向或形状

这里需要我实现的圆形和扇形比较类似,拿扇形为例,语言不太直观,这里放上本次实现的运行截图:

在这里插入图片描述
相信这样应该理解了我们需要实现的效果是怎样的,然后运行截图上的红色的线是我为了便于观看轨迹效果,使用OnDrawGizmos在Scene绘制的轨迹图。

圆形与扇形实现原理
圆形弹幕子弹效果

每次发射固定个数的子弹,这里便于讲解就规定为8个,那么这8枚子弹就是在圆周上均匀分布的,即任意两枚子弹的发射方向间的角度应该是 360/8=45 度,因为这里是以人物为圆点向四周发射,所以我们不需要设置圆的半径,子弹是通过预制体实现,他们运动速度相等,所以只要同时朝预设好的方向发射8枚子弹,就可以实现圆形弹幕子弹。

那么上面我们推出了任意两枚子弹间的角度,也可以得出在平面内8个点的发射角度,依次0,45,90,135,180,225,270,315,360,这样列出来就可以得到规律了,就是45*i(i是第几个点),所以对于任意数目固定的子弹,就是 (360/count)×i

扇形弹幕子弹效果

与圆形类似,只不过不是360,其它的其实都是一样,那么发射角度的公式就是 (设置好的扇形角度/count)×i

圆形与扇形代码实现
//圆形实现,部分代码,工程完整下载链接在文章最下面
//circularCount是输入的子弹数目
Vector3 beginDir = bulletPos.forward;
float angle = 360/circularCount;
for(int i=0;i<circularCount;i++){
    var outBullet = ShadowPool.Instance.GetBulletFromPool();
    Quaternion rotate = Quaternion.AngleAxis(angle*i,Vector.up);
    Vector3 rotateDir = rotate * beginDir;
    Quaternion endDir = Quaternion.LookRotation(rotateDir);
    outBullet.transform.rotation = endDir;
    outBullet.transform.position = bulletPos.position;
    outBullet.SetActive(true);
}
//扇形实现,部分代码,angle是输入的扇形角度,sectorCount是输入的子弹数目
var beginAngle = -(angle / 2);
var a = angle / (sectorCount - 1);
for (int i = 0; i < sectorCount; i++)
{
	var outBullet = ShadowPool.Instance.GetBulletFromPool();
	Quaternion bulletQ = Quaternion.AngleAxis(beginAngle+a * i, new Vector3(0,1,0));
	Vector3 bulletV = bulletQ * beginDir;
	Quaternion bullet = Quaternion.LookRotation(bulletV);
	outBullet.transform.rotation = bullet;
	outBullet.transform.position = bulletPos.position;
	outBullet.SetActive(true);
}

子弹预制体代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    //子弹存在时间,存在时间超过后就回收子弹
    public float existenceTime;
    //子弹移动速度
    public float speed;
    //私有变量,记录当前子弹开始出现的系统时间
    float beginTime;
    //私有变量,记录当前子弹的轨迹数组
    List<Vector3> pos = new List<Vector3>();

    //因为我通过对象池实现的子弹出现与消失,所以在OnEnable中进行初始化
    private void OnEnable()
    {
        beginTime = Time.time;
    }

    private void Update()
    {
        //在当前系统时间减去开始出现的时间大于存在时间时,回收子弹,并且清零其轨迹数组,便于下次绘制
        if((Time.time- beginTime) > existenceTime)
        {
            ShadowPool.Instance.ReturnPool(gameObject);
            pos.Clear();
        }
        else
        {
            //子弹朝自己的发射角度直线运动
            transform.position += transform.forward * speed * Time.deltaTime;
            //将经过的pos放入轨迹数组
            pos.Add(transform.position);
        }
    }

    //绘制轨迹数组
    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        //在Scene视图中绘制螺纹线
        for (int i = 0; i < pos.Count - 1; i++)
        {
            Vector3 from = pos[i];
            Vector3 to = pos[i + 1];
            Gizmos.DrawLine(from, to);
        }
    }
}

单螺旋形弹幕子弹效果
原理

单螺旋的感觉如图所示,我感觉看起来很像弹簧被拉开,所以我就想到了,绘制如图的单螺旋,相当于绘制一个不停绕z轴做圆周运动的点,不过圆心以恒定速度向z轴正方向运动,所以最后导致了这种螺旋形。

在这里插入图片描述

那么就很顺利了,绘制圆形可以通过Mathf.Cos和Mathf.Sin结合角度来求得圆周上点的坐标,然后给圆心某个方向的位移,就完成了单螺旋的绘制。

代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class sc : MonoBehaviour
{
    //螺旋轨迹圆心
    Transform origin;
    //螺旋轨迹半径
    public float radius;
    //螺旋圆心移动速度
    public float xSpeed;
    //移动速度
    public float speed;
    //轨迹数组,用于绘制轨迹
    List<Vector3> points = new List<Vector3>();
    //旋转角度,控制在360内
    float angle;

    public float time;
    float beginTime;

    private void Awake()
    {
        GameObject go = new GameObject("origin");
        origin = go.GetComponent<Transform>();
        //设置圆心在初始点z轴向后移动半径的位置
        origin.position = transform.position-new Vector3(-1,0,radius);
        origin.rotation = transform.rotation;
        //为了之后的螺旋,将原点朝向改为x轴正方向
        origin.forward = new Vector3(1,0,0);
        beginTime = Time.time;
    }

    private void Update() 
    {
        if(Time.time-beginTime > time)
        {
            Destroy(gameObject);
        }
        //原点每帧向x轴正方向运动
        origin.position += origin.forward*xSpeed*Time.deltaTime;
        //记录变化角度
        angle += (speed * Time.deltaTime) % 360;
        //根据角度计算当前的y和z坐标
        float y = radius * Mathf.Sin(angle*Mathf.Deg2Rad);
        float z = radius * Mathf.Cos(angle*Mathf.Deg2Rad);
        transform.position = new Vector3(0,y,z)+origin.position;
        points.Add(transform.position);
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        //在Scene视图中绘制螺纹线
        for (int i = 0; i < points.Count - 1; i++)
        {
            Vector3 from = points[i];
            Vector3 to = points[i + 1];
            Gizmos.DrawLine(from, to);
        }
    }
}

这里的子弹没有使用对象池实现,直接使用的Destroy和Instantiate实现

效果

在这里插入图片描述


完整工程下载地址:https://gitee.com/camellia-t/bullet.git

猜你喜欢

转载自blog.csdn.net/Charon_x/article/details/124304456
今日推荐