247 lines
8.9 KiB
C#
247 lines
8.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
public class DanmuItemData
|
|
{
|
|
public bool isMe;
|
|
public string head;
|
|
public string content;
|
|
}
|
|
public class MyDanmuPlayer : MonoBehaviour
|
|
{
|
|
[SerializeField] private float _speed = 2.0f;
|
|
[SerializeField] private float _danmuSpacing = 100.0f;
|
|
[SerializeField] private float _trackSpacing = 30.0f;
|
|
[SerializeField] private float _wordWidth = 40.0f;
|
|
|
|
private GameObject _danmuItemTpl;
|
|
private Transform _danmuScreen;
|
|
private Transform _danmuPool;
|
|
private Queue<DanmuItemData> _contentQueue = new Queue<DanmuItemData>();
|
|
private Queue<DanmuItemData> _myselfContentQueue = new Queue<DanmuItemData>();
|
|
private Action _onPlayFinished;
|
|
private Action _onPlayNtf;
|
|
private List<Transform> _danmuPoolItems = new List<Transform>();
|
|
private List<List<RectTransform>> _trackDanmuItemsList = new List<List<RectTransform>>();
|
|
private int _lastPlayFinishCount = 0;
|
|
|
|
private void Awake()
|
|
{
|
|
}
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
_danmuItemTpl = transform.Find("DanmuItemTpl").gameObject;
|
|
_danmuScreen = transform.Find("DanmuScreen");
|
|
_danmuPool = transform.Find("DanmuPool");
|
|
var danmuHeight = _danmuItemTpl.GetComponent<RectTransform>().rect.height;
|
|
var screenHeight = _danmuScreen.GetComponent<RectTransform>().rect.height;
|
|
var screenRectTransform = _danmuScreen.GetComponent<RectTransform>();
|
|
Debug.Log("screenHeight: " + screenHeight);
|
|
int trackCount = (int)(screenHeight/(danmuHeight+_trackSpacing));
|
|
for (int i = 0; i < trackCount*5; i++)
|
|
{
|
|
var danmuItem = Instantiate(_danmuItemTpl, _danmuPool);
|
|
danmuItem.SetActive(false);
|
|
_danmuPoolItems.Add(danmuItem.transform);
|
|
}
|
|
|
|
}
|
|
|
|
IEnumerator StartTrack(List<RectTransform> currDanmuItems, Vector2 startPos, Vector2 endPos)
|
|
{
|
|
while (true)
|
|
{
|
|
float maxX = 0;
|
|
for (int i = 0; i < currDanmuItems.Count; i++)
|
|
{
|
|
currDanmuItems[i].anchoredPosition -= new Vector2(_speed, 0);
|
|
var x = currDanmuItems[i].anchoredPosition.x + currDanmuItems[i].rect.width/2;
|
|
if (x > maxX)
|
|
{
|
|
maxX = x;
|
|
}
|
|
}
|
|
|
|
if (currDanmuItems.Count > 0)
|
|
{
|
|
if (currDanmuItems[0].anchoredPosition.x + currDanmuItems[0].rect.width < endPos.x-20)
|
|
{
|
|
_FreeDanmuItem(currDanmuItems[0]);
|
|
currDanmuItems.RemoveAt(0);
|
|
if (_CheckPlayFinish() && _onPlayFinished != null)
|
|
{
|
|
Debug.Log("[MyDanmuPlayer] _onPlayFinished");
|
|
_onPlayFinished?.Invoke();
|
|
_onPlayFinished = null;
|
|
}
|
|
if (_contentQueue.Count < _lastPlayFinishCount && _onPlayNtf != null)
|
|
{
|
|
Debug.Log("[MyDanmuPlayer] _onPlayNtf");
|
|
_onPlayNtf?.Invoke();
|
|
_onPlayNtf = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (startPos.x - maxX > (_danmuSpacing + UnityEngine.Random.Range(0, 200)))
|
|
{
|
|
DanmuItemData danmuItemData = null;
|
|
if (_myselfContentQueue.Count > 0)
|
|
{
|
|
danmuItemData = _myselfContentQueue.Dequeue();
|
|
}
|
|
else if (_contentQueue.Count > 0)
|
|
{
|
|
danmuItemData = _contentQueue.Dequeue();
|
|
}
|
|
if (danmuItemData != null)
|
|
{
|
|
var danmuItem = _AllocDanmuItem();
|
|
var danmuItemRect = danmuItem.GetComponent<RectTransform>();
|
|
danmuItem.SetParent(_danmuScreen);
|
|
danmuItemRect.anchoredPosition = startPos;
|
|
danmuItemRect.sizeDelta = new Vector2(danmuItemData.content.Length*_wordWidth, danmuItemRect.sizeDelta.y);
|
|
danmuItem.Find("Text").gameObject.SetActive(!danmuItemData.isMe);
|
|
danmuItem.Find("Text").GetComponent<TextMeshProUGUI>().text = danmuItemData.content;
|
|
danmuItem.Find("MeText").gameObject.SetActive(danmuItemData.isMe);
|
|
danmuItem.Find("MeText").GetComponent<TextMeshProUGUI>().text = danmuItemData.content;
|
|
currDanmuItems.Add(danmuItemRect);
|
|
}
|
|
}
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
bool _CheckPlayFinish()
|
|
{
|
|
bool isAllPlayFinished = true;
|
|
if (_contentQueue.Count == 0 && _myselfContentQueue.Count == 0)
|
|
{
|
|
for (int i = 0; i < _trackDanmuItemsList.Count; i++)
|
|
{
|
|
if (_trackDanmuItemsList[i].Count > 0)
|
|
{
|
|
isAllPlayFinished = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isAllPlayFinished = false;
|
|
}
|
|
return isAllPlayFinished;
|
|
}
|
|
|
|
public void ResetPlayer()
|
|
{
|
|
Debug.Log("[MyDanmuPlayer] _ResetPlayer");
|
|
_contentQueue.Clear();
|
|
_myselfContentQueue.Clear();
|
|
for (int i = 0; i < _trackDanmuItemsList.Count; i++)
|
|
{
|
|
var trackDanmuItems = _trackDanmuItemsList[i];
|
|
for (int j = 0; j < trackDanmuItems.Count; j++)
|
|
{
|
|
_FreeDanmuItem(trackDanmuItems[j]);
|
|
}
|
|
trackDanmuItems.Clear();
|
|
}
|
|
_trackDanmuItemsList.Clear();
|
|
StopAllCoroutines();
|
|
StartCoroutine(_DelayReset());
|
|
}
|
|
|
|
IEnumerator _DelayReset()
|
|
{
|
|
yield return null;
|
|
_danmuItemTpl = transform.Find("DanmuItemTpl").gameObject;
|
|
_danmuScreen = transform.Find("DanmuScreen");
|
|
var danmuHeight = _danmuItemTpl.GetComponent<RectTransform>().rect.height;
|
|
var screenHeight = _danmuScreen.GetComponent<RectTransform>().rect.height;
|
|
var screenRectTransform = _danmuScreen.GetComponent<RectTransform>();
|
|
int trackCount = (int)(screenHeight/(danmuHeight+_trackSpacing));
|
|
int offset = (int)screenHeight % (int)(danmuHeight+_trackSpacing);
|
|
for (int i = trackCount-1; i >= 0; i--)
|
|
{
|
|
var danmuPosY = -offset/2 + (i+1) * (danmuHeight + _trackSpacing) - screenRectTransform.rect.height/2;
|
|
var startPos = new Vector2(screenRectTransform.rect.width, danmuPosY);
|
|
var endPos = new Vector2(0, danmuPosY);
|
|
Debug.Log("[MyDanmuPlayer] Start Track " + startPos.ToString());
|
|
List<RectTransform> currDanmuItems = new List<RectTransform>();
|
|
_trackDanmuItemsList.Add(currDanmuItems);
|
|
StartCoroutine(StartTrack(currDanmuItems, startPos, endPos));
|
|
}
|
|
}
|
|
|
|
public void Play(string[] contents, int lastPlayFinishCount, Action onPlayNtf, Action onPlayFinished)
|
|
{
|
|
StartCoroutine(_DelayPlay(contents, lastPlayFinishCount, onPlayNtf, onPlayFinished));
|
|
}
|
|
|
|
IEnumerator _DelayPlay(string[] contents, int lastPlayFinishCount, Action onPlayNtf, Action onPlayFinished)
|
|
{
|
|
yield return null;
|
|
yield return null;
|
|
for (int i = 0; i < contents.Length; i++)
|
|
{
|
|
_contentQueue.Enqueue(new DanmuItemData(){isMe = false, head = "", content = contents[i]});
|
|
}
|
|
_lastPlayFinishCount = lastPlayFinishCount;
|
|
_onPlayNtf = onPlayNtf;
|
|
_onPlayFinished = onPlayFinished;
|
|
}
|
|
|
|
|
|
public void PlayMySelf(string content)
|
|
{
|
|
_myselfContentQueue.Enqueue(new DanmuItemData(){isMe = true, head = "", content = content});
|
|
}
|
|
|
|
// [ContextMenu("TestPlayMySelf")]
|
|
// void TestPlayMySelf()
|
|
// {
|
|
// PlayMySelf("这是我的弹幕,哈哈哈哈哈!!!");
|
|
// }
|
|
//
|
|
// [ContextMenu("TestPlay")]
|
|
// void TestPlay()
|
|
// {
|
|
// var contents = new[] {"AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEEE", "FFFFFF", "AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEEE", "FFFFFF"};
|
|
// Play(contents, 0, () =>
|
|
// {
|
|
// Debug.Log("TestPlay Over");
|
|
// });
|
|
// }
|
|
|
|
Transform _AllocDanmuItem()
|
|
{
|
|
if (_danmuPoolItems.Count > 0)
|
|
{
|
|
var danmuItem = _danmuPoolItems[_danmuPoolItems.Count-1];
|
|
_danmuPoolItems.RemoveAt(_danmuPoolItems.Count-1);
|
|
danmuItem.gameObject.SetActive(true);
|
|
return danmuItem;
|
|
}
|
|
else
|
|
{
|
|
var danmuItemGo = Instantiate(_danmuItemTpl, _danmuPool);
|
|
danmuItemGo.SetActive(true);
|
|
return danmuItemGo.transform;
|
|
}
|
|
}
|
|
|
|
void _FreeDanmuItem(Transform danmuItem)
|
|
{
|
|
danmuItem.SetParent(_danmuPool);
|
|
danmuItem.gameObject.SetActive(false);
|
|
_danmuPoolItems.Add(danmuItem);
|
|
}
|
|
}
|