弹幕其实就是指子弹,弹幕子弹效果是指发射出来的子弹不是单一的一条直线,而是有自己的轨迹或者自己的方向或形状
这里需要我实现的圆形和扇形比较类似,拿扇形为例,语言不太直观,这里放上本次实现的运行截图:
相信这样应该理解了我们需要实现的效果是怎样的,然后运行截图上的红色的线是我为了便于观看轨迹效果,使用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//扇形实现,部分代码,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; //私有变量,记录当前子弹的轨迹数组 Listpos = new List (); //因为我通过对象池实现的子弹出现与消失,所以在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; //轨迹数组,用于绘制轨迹 Listpoints = new List (); //旋转角度,控制在360内 float angle; public float time; float beginTime; private void Awake() { GameObject go = new GameObject("origin"); origin = go.GetComponent (); //设置圆心在初始点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



