using System.Collections; using UnityEngine; using UnityEngine.UI; public class ChatBulletView : MonoBehaviour { [SerializeField] GameObject bulletPrefab; // 必须赋值预制体 [SerializeField] RectTransform bulletContainer; [SerializeField] float bulletSpeed = 150f; [SerializeField] float position1Y = 220f; [SerializeField] Vector2 randomYRange = new Vector2(200f, -200); [SerializeField] float safeSpacing = 20f; [SerializeField] Color defaultColor = Color.white; private ChatBulletItem lastItemOnPos1; private float screenWidth; private float screenLeftX; ChatManager manager { get { return ChatManager.Instance; } } private void Awake() { screenWidth = 750; screenLeftX = -screenWidth / 2; GameObjectPoolManager.Instance.CacheGameObject(bulletPrefab, 10, false); } private void Start() { ChatManager.Instance.OnUpdateTalkEvent += OnUpdateTalkEvent; } private void OnDestroy() { ChatManager.Instance.OnUpdateTalkEvent -= OnUpdateTalkEvent; } private void OnUpdateTalkEvent(ChatChannel channel, TalkData data) { if (!ChatManager.Instance.GetBulletSetting(channel)) return; // 0-系统 1-日期 2-自己 3-其他玩家 int type = manager.GetTalkDataType(data); if (type == 1) return; SpawnBullet(channel, type == 0, type == 0 ? data.Content : GetBulletContent(channel, data), data.InfoList); } private string GetBulletContent(ChatChannel channel, TalkData data) { switch (channel) { case ChatChannel.World: string serverName = ServerListCenter.Instance.GetServerName((int)data.ServerID); return Language.Get("Chat16", serverName, data.Name, data.Content); case ChatChannel.Guild: return Language.Get("Chat16", Language.Get("ChatTab1"), data.Name, data.Content); default: return data.Content; } } private void SpawnBullet(ChatChannel channel, bool isSys, string content, ArrayList infoList) { if (bulletPrefab == null || GameObjectPoolManager.Instance == null) return; // 【关键修改】从特定对象池获取对象 GameObject obj = GameObjectPoolManager.Instance.RequestGameObject(bulletPrefab); // 【重要】对象池管理器会把父节点设为null,这里必须重设回UI容器 obj.transform.SetParent(bulletContainer, false); obj.transform.localScale = Vector3.one; obj.SetActive(true); ChatBulletItem item = obj.GetComponent(); if (item == null) item = obj.AddComponent(); Color color = GetChannelColor(channel); float spawnY = CalculateSpawnY(); Vector2 startPos = new Vector2(screenWidth / 2, spawnY); item.Init(isSys, content, infoList, color, bulletSpeed, startPos, screenLeftX, bulletPrefab, OnBulletFinish); if (Mathf.Abs(spawnY - position1Y) < 1f) { lastItemOnPos1 = item; } } private float CalculateSpawnY() { bool pos1Available = true; if (lastItemOnPos1 != null && lastItemOnPos1.gameObject.activeSelf) { // 上一条弹幕还没完全离开右侧安全区 float spawnX = screenWidth / 2; if (lastItemOnPos1.GetRightEdgeX() > spawnX - safeSpacing) { pos1Available = false; } } if (pos1Available) { return position1Y; } else { return Random.Range(randomYRange.x, randomYRange.y); } } private void OnBulletFinish(ChatBulletItem item) { if (item == lastItemOnPos1) { lastItemOnPos1 = null; } } private Color GetChannelColor(ChatChannel channel) { if (!manager.chatChannelBulletColorDict.TryGetValue(channel, out var color)) return defaultColor; return color; } }