DanmakuManager.cs 4.1 KB
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class DanmakuManager : MonoBehaviour
{
    public RectTransform danmakuPanel; // 弹幕pannel
    public GameObject danmakuPrefab;
    public float speed = 100f; // px/sec
    private int currentLine = 0;

    public void AddDanmaku(string text,int direction)
    {
        if (direction == 1)
        {
            StartCoroutine(SpawnDanmakuHorizontal(text));
        }
        else
        {
            StartCoroutine(SpawnDanmakuVertical(text));
        }
    }
    
    public void ClearDanmaku()
    {
        foreach (Transform child in danmakuPanel)
            Destroy(child.gameObject);
    }
    
    //批量弹幕,每条弹幕添加延迟
    //direction 1.横屏 2.竖屏
    public void AddDanmakuBatch(List<string> texts, float delay,int direction)
    {
        StartCoroutine(SendDanmakusWithDelay(texts, delay, direction));
    }

    private IEnumerator SendDanmakusWithDelay(List<string> texts, float delay,int direction)
    {
        foreach (var text in texts)
        {
            AddDanmaku(text,direction); // 使用你已有的发送函数
            yield return new WaitForSeconds(delay);
        }
    }

    

    IEnumerator SpawnDanmakuVertical(string text)
    {
        // 实例化
        GameObject obj = Instantiate(danmakuPrefab, danmakuPanel);
        var tmp = obj.GetComponent<TextMeshProUGUI>();
        tmp.text = text;
        
        Color color;
        if (ColorUtility.TryParseHtmlString("#F7C559", out color))
        {
            tmp.color = color;
        }

        

        // 获取 RectTransform
        RectTransform rt = obj.GetComponent<RectTransform>();

        // 获取弹幕面板高度与每行高度
        float panelHeight = danmakuPanel.rect.height;

        // 起始 Y 坐标(屏幕底部偏下)
        float y = -panelHeight;  // 起始点在面板下方
        // X 保持水平居中(或你可以自定义)
        float x = Random.Range(700f, 900f);

        // 设置初始位置
        rt.anchoredPosition = new Vector2(x, y);

        // 移动到屏幕顶端
        while (rt.anchoredPosition.y < panelHeight / 4)
        {
            rt.anchoredPosition += Vector2.up * speed * Time.deltaTime;
            yield return null;
        }

        // 移除弹幕
        Destroy(obj);
    }
    
    
    IEnumerator SpawnDanmakuHorizontal(string text)
    {
        // 实例化
        GameObject obj = Instantiate(danmakuPrefab, danmakuPanel);
        var tmp = obj.GetComponent<TextMeshProUGUI>();
        tmp.text = text;
    
        RectTransform rt = obj.GetComponent<RectTransform>();
        float panelHeight = danmakuPanel.rect.height;
    
        // 随机 Y 坐标(在整个 panel 高度范围内)
        // 获取随机 Y 坐标,确保与上次相差至少 30
        float randomY = GetRandomY(panelHeight, 30f);        
        rt.anchoredPosition = new Vector2(danmakuPanel.rect.width, randomY);
    
        float width = tmp.preferredWidth;
    
        // 向左移动直到超出屏幕
        while (rt.anchoredPosition.x > -width)
        {
            rt.anchoredPosition += Vector2.left * speed * Time.deltaTime;
            yield return null;
        }
    
        Destroy(obj);
    }
    
    // 记录最近的 4 个 Y 坐标
    Queue<float> lastYList = new Queue<float>();
    int maxTrackCount = 4; // 记录最近的 4 个 Y 坐标

    float GetRandomY(float panelHeight, float minDifference)
    {
        float randomY = Random.Range(-panelHeight / 2f, panelHeight / 2f);

        // 检查与历史记录中的 Y 坐标差是否小于 minDifference
        while (lastYList.Any(y => Mathf.Abs(randomY - y) < minDifference))
        {
            randomY = Random.Range(-panelHeight / 2f, panelHeight / 2f);
        }

        // 更新 Y 坐标历史记录
        if (lastYList.Count >= maxTrackCount)
        {
            lastYList.Dequeue(); // 移除最旧的 Y 坐标
        }
        lastYList.Enqueue(randomY); // 添加当前生成的 Y 坐标到队列

        return randomY;
    }

    
        


}