现在的公司在做一个VR影院的项目,需要实现弹幕聊天功能。在借鉴其它博主的实现思路上,做了一些改编,希望能为大家提供参考。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using DG.Tweening;
using System.Collections.Generic;
using System;
using TMPro;
/*
* Author:W
* 弹幕系统
*/
public class BulletMsgShowPanel : MonoBehaviour
{
/// <summary>
/// 弹幕信息父对象
/// </summary>
public Transform BulletMsgParent;
/// <summary>
/// 弹幕预设
/// </summary>
public GameObject BulletMsgPrefab;
/// <summary>
/// 弹幕物体的队列
/// </summary>
private Queue BulletMsgQueue = new Queue();
/// <summary>
/// 生成弹幕的时间间隔
/// </summary>
[SerializeField]
[Tooltip("弹幕生成的时间间隔")]
private float Timer;
[SerializeField]
[Tooltip("弹幕的在屏幕上的行数以及对应的Y坐标值")]
private int[] RowArr = new int[] {560, 500, 440, 380 };//四行弹幕的位置
private int Row_PosY;
[SerializeField]
[Tooltip("弹幕的生成位置的X坐标")]
private float PosX_Max = 1200;
[SerializeField]
[Tooltip("弹幕运动目标位置的X坐标")]
private float PosX_Min = -1300;
/// <summary>
/// 弹幕移动的时长
/// </summary>
[SerializeField]
[Tooltip("弹幕运动时长")]
private float BulletMsgMoveTime = 20;
private Vector3 BulletMsgRefPositon;//生成弹幕位置
private Quaternion BulletMsgRefRotation;//生产弹幕角度
void Start()
{
RowArr = new int[] { 560, 500, 440, 380 };
Row_PosY = RowArr[0];//默认弹幕生产在第一行
BulletMsgRefPositon = new Vector3(PosX_Max, Row_PosY, 0);
BulletMsgRefRotation.eulerAngles = new Vector3(0,0, 0);
Timer = 2f;
}
void Update()
{
Timer -= Time.deltaTime;
if (Timer <= 0f)
{
int i = UnityEngine.Random.Range(0, DanMuStrings.Length);//弹幕的随机内容
//调用生成弹幕方法
CreateBulletMsgObj(DanMuStrings[i]);
Timer = 2f;//每隔2秒生成一个弹幕
}
#region 判断应该在第几行
ComputeNewBulletMsgObjPos();
#endregion
//检查移出屏幕的弹幕,销毁处理
if (BulletMsgQueue.Count > 0)//退出队列方法一(节省资源开销)
{
GameObject go = (GameObject)BulletMsgQueue.Peek();
if (go.transform.localPosition.x <= PosX_Min)//当弹幕位置移出屏幕
{
BulletMsgQueue.Dequeue();//移出队列
Destroy(go);//销毁弹幕
//Debug.Log("save===" + BulletMsgQueue.Count);
}
}
}
/// <summary>
/// 计算下1条生成的弹幕能在那一行生成
/// </summary>
private void ComputeNewBulletMsgObjPos()
{
int index = 0;
foreach (GameObject tex in BulletMsgQueue.ToArray())
{
for (int i = 0; i < RowArr.Length; i++)
{
if (tex.transform.localPosition.y == RowArr[i])
{
if (i < RowArr.Length - 1)
{
index = i + 1;
}
else
{
index = 0;
}
}
}
}
Row_PosY = RowArr[index];
}
#region 弹幕内容(测试用)
public string[] DanMuStrings =
{
"<sprite=0>这个剧情也太雷人了吧!<sprite=0>",
"还是好莱坞的电影经典啊,<sprite=0>这个太次了还是好莱坞的电影经典啊",
"是电锯惊魂的主角,尼玛<sprite=0>",
"这个游戏还是很良心的么<sprite=0>",
"卧槽还要花钱,这一关也太难卧槽还要花钱,这一关也太难了卧<sprite=0>",
"这个游戏好棒偶<sprite=0>",
"全是傻逼<sprite=0>",
"求约:13122785566<sprite=0>",
"最近好寂寞啊,还是这个游戏好啊是胸再大点<sprite=0>",
"难道玩游戏还能撸<sprite=0>",
"办证:010- 888888<sprite=0>",
"为什么女主角没有死?<sprite=0>",
"好帅呦,你这个娘们儿<sprite=0>",
"欠揍啊,东北人不知道啊<sprite=0>",
"我去都是什么人啊,请文明用语还是好莱坞的电影经典啊,<sprite=0>",
"这个还是不错的<sprite=0>",
"要是胸再大点就更好了<sprite=0>",
"这个游戏必须顶啊<sprite=0>",
"还是好莱坞的电影经典啊,这个太次了还是好莱坞的电影经典啊 <sprite=0>",
"好吧,这也是醉了!<sprite=0>",
"他只想做一个安静的美男子!<sprite=0>"
};
#endregion
/// <summary>
/// 生成弹幕和移动弹幕
/// </summary>
public void CreateBulletMsgObj(string content)
{
GameObject bulletMsgObj;
bulletMsgObj = (GameObject)(Instantiate(BulletMsgPrefab, BulletMsgRefPositon, BulletMsgRefRotation));//生成弹幕
bulletMsgObj.SetActive(true);
if (bulletMsgObj != null)
{
bulletMsgObj.transform.SetParent(BulletMsgParent);//设置父物体
bulletMsgObj.transform.localScale = new Vector3(1, 1, 1);
bulletMsgObj.transform.localRotation = BulletMsgRefRotation;
//Debug.Log("Row_PosY================"+ Row_PosY);
bulletMsgObj.transform.localPosition = new Vector3(PosX_Max, Row_PosY, 0);//--弹幕移动的起始位置X
bulletMsgObj.transform.GetComponentInChildren<TextMeshProUGUI>().text = content;//弹幕内容
//移动弹幕(20秒移动到-1300的位置)
bulletMsgObj.transform.DOLocalMoveX(PosX_Min, BulletMsgMoveTime);
}
//生成的弹幕添加到队列
BulletMsgQueue.Enqueue(bulletMsgObj);
}
}