using UnityEngine; using UnityEngine.UI; // Image 컴포넌트를 조작하기 위해 필요! using UnityEngine.InputSystem; using Photon.Pun; using System.Collections.Generic; using TMPro; // Dictionary 사용 using Hashtable = ExitGames.Client.Photon.Hashtable; public class Gazuaa : MonoBehaviourPunCallbacks { private GazuaInput _gazuaInput; public GameObject map; public GameObject avatarPrefab; public TextMeshProUGUI logText; // [추가] 화면 오른쪽 로그 텍스트박스 연결 private int myAvatarCount = 0; public static bool isGameActive = false; // 핵심!: 각 플레이어(유저 번호)가 지금까지 '몇 개의 아바타를 화면에 그렸는지' 기억하는 사전 private Dictionary knownAvatarCounts = new Dictionary(); private List logMessages = new List(); private int maxLogLines = 15; // 텍스트박스 높이에 맞춰서 조절하세요! private void Awake() { _gazuaInput = new GazuaInput(); _gazuaInput.Enable(); _gazuaInput.Player.Gacha.performed += Gacha; if (logText != null) logText.text = ""; // ---- [추가된 부분: 재시작 시 데이터 초기화] ---- myAvatarCount = 0; knownAvatarCounts.Clear(); // 딕셔너리 비우기 isGameActive = false; // 게임 상태 초기화 // 서버에 기록된 내 아바타 개수도 0으로 덮어씌우기 Hashtable hash = new Hashtable(); hash["AvatarCount"] = 0; PhotonNetwork.LocalPlayer.SetCustomProperties(hash); // --------------------------------------------- } private void Gacha(InputAction.CallbackContext obj) { // 포톤 방에 없거나, 타이머가 끝나서 게임이 멈췄다면 입력 무시! if (!PhotonNetwork.InRoom || !isGameActive) return; var result = Randomizer.GetResult(); myAvatarCount += result; Hashtable hash = new Hashtable(); hash["AvatarCount"] = myAvatarCount; PhotonNetwork.LocalPlayer.SetCustomProperties(hash); } // 서버가 "누군가의 정보가 바뀌었어!" 라고 알려줄 때 실행됨 (나의 변경 사항도 포함됨) public override void OnPlayerPropertiesUpdate(Photon.Realtime.Player targetPlayer, Hashtable changedProps) { if (!this || !map) return; if (changedProps.ContainsKey("AvatarCount")) { int newTotalCount = (int)changedProps["AvatarCount"]; int actorNumber = targetPlayer.ActorNumber; string playerName = targetPlayer.NickName; // [핵심] 아까 로비에서 적은 닉네임 가져오기! int oldCount = 0; if (knownAvatarCounts.ContainsKey(actorNumber)) { oldCount = knownAvatarCounts[actorNumber]; } int avatarsToSpawn = newTotalCount - oldCount; // [추가] 새로 뽑힌 개수가 0개보다 크다면 로그 띄우기 if (avatarsToSpawn > 0) { AddLog($"{playerName}님이 {avatarsToSpawn}개 가챠에 성공했습니다!"); } for (int i = 0; i < avatarsToSpawn; i++) { GameObject newAvatar = Instantiate(avatarPrefab, map.transform); newAvatar.name = actorNumber.ToString(); if (GameManager.AvatarCache.ContainsKey(actorNumber)) { Image avatarImage = newAvatar.GetComponent(); if (avatarImage != null) { avatarImage.sprite = GameManager.AvatarCache[actorNumber]; } } } knownAvatarCounts[actorNumber] = newTotalCount; } } // [추가] 로그를 관리하고 텍스트박스에 띄워주는 함수 private void AddLog(string message) { if (logText == null) return; logMessages.Add(message); // 정해진 줄 수를 넘어가면 가장 오래된(맨 위의) 로그를 지움 if (logMessages.Count > maxLogLines) { logMessages.RemoveAt(0); } // 리스트에 있는 텍스트들을 줄바꿈(\n)으로 합쳐서 텍스트박스에 쏙! logText.text = string.Join("\n", logMessages); } // GameManager에서 호출할 함수 (이름도 같이 받도록 매개변수 추가) public void HighlightWinner(int winnerActorNumber, string winnerName) { StartCoroutine(RouletteRoutine(winnerActorNumber, winnerName)); } private System.Collections.IEnumerator RouletteRoutine(int winnerActorNumber, string winnerName) { string winnerNameStr = winnerActorNumber.ToString(); List allAvatars = new List(); List winnerAvatars = new List(); // [수정] 당첨자의 '모든' 아바타를 담을 리스트 for (int i = 0; i < map.transform.childCount; i++) { Transform child = map.transform.GetChild(i); allAvatars.Add(child); // 모든 아바타를 어둡게 만듭니다. child.GetComponent().color = new Color(0.4f, 0.4f, 0.4f, 1f); // 당첨자의 아바타라면 리스트에 싹 다 모아둡니다. if (child.name == winnerNameStr) { winnerAvatars.Add(child); } } // 아무도 없거나 에러 방지용 if (allAvatars.Count == 0 || winnerAvatars.Count == 0) yield break; // 2. 시간 기반 룰렛 회전 설정 float delay = 0.04f; // 초기 속도 int currentIndex = 0; float elapsedTime = 0f; // 흐른 시간 float spinDuration = 3.5f; // ★ [핵심] 정확히 3.5초 동안만 회전합니다! while (elapsedTime < spinDuration) { // 이전 아바타 원상복구 int prevIndex = (currentIndex == 0) ? allAvatars.Count - 1 : currentIndex - 1; allAvatars[prevIndex].localScale = Vector3.one; allAvatars[prevIndex].GetComponent().color = new Color(0.4f, 0.4f, 0.4f, 1f); // 현재 아바타 하이라이트 allAvatars[currentIndex].localScale = new Vector3(1.2f, 1.2f, 1.2f); allAvatars[currentIndex].GetComponent().color = Color.white; yield return new WaitForSeconds(delay); elapsedTime += delay; // 흐른 시간 누적 // 시간이 지날수록 속도를 살짝 늦춥니다. if (elapsedTime > spinDuration * 0.5f) delay = 0.08f; // 절반 지났을 때 if (elapsedTime > spinDuration * 0.8f) delay = 0.15f; // 거의 끝날 때쯤 // 다음 아바타로 이동 currentIndex = (currentIndex + 1) % allAvatars.Count; } // 회전이 끝났으므로 마지막으로 켜져 있던 아바타 끄기 allAvatars[currentIndex].localScale = Vector3.one; allAvatars[currentIndex].GetComponent().color = new Color(0.4f, 0.4f, 0.4f, 1f); // 3. ★ 정해진 시간이 끝나면, 당첨자의 '모든' 아바타를 동시에 하이라이트! foreach (Transform winner in winnerAvatars) { winner.localScale = new Vector3(1.5f, 1.5f, 1.5f); winner.GetComponent().color = Color.white; } FindObjectOfType().text.text = $"{winnerName} 당첨!!!"; FindObjectOfType().ShowRestartButtonIfMaster(); } public override void OnDisable() { base.OnDisable(); _gazuaInput.Disable(); } }