using TMPro; using UnityEngine; using UnityEngine.UI; public partial class GameFlowManager { private void ShowResult() { if(TryLoadFlowScene(ResultSceneName)) { return; } EnsureOverlay(); ClearOverlay(); SetOverlayVisible(true); BuildResultScreen(); } private void BuildResultScreen() { ApplyResultAirportBackground(); MapDefinition resultMap = completedMap != null ? completedMap : currentMap; int rewardMileage = lastResultCleared && resultMap != null ? resultMap.clearMileageReward : 0; int gainedMileage = Mathf.Max(0, lastResultMileage) + rewardMileage; int targetDistance = resultMap != null ? Mathf.FloorToInt(resultMap.targetDistance) : 0; int shownDistance = targetDistance > 0 ? Mathf.Clamp(Mathf.FloorToInt(lastResultDistance), 0, targetDistance) : Mathf.Max(0, Mathf.FloorToInt(lastResultDistance)); RectTransform passportRect = AddResultPassportPanel(); AddResultHeader(passportRect, resultMap); AddResultStats(passportRect, gainedMileage, shownDistance, targetDistance); AddResultTickets(passportRect, resultMap, rewardMileage); if(lastResultCleared) { AddResultActionButton("면세점으로", ShowDutyFreeShop, new Vector2(-166f, -282f), new Vector2(250f, 48f), true, LoadUiSprite("", DutyFreeIconAssetPath)); AddResultActionButton("다음 여행지 가기", ShowMapPreview, new Vector2(160f, -282f), new Vector2(292f, 48f), false, LoadUiSprite("", AirplaneTravelIconAssetPath)); } else { AddResultActionButton("다시 도전", RetryCurrentMap, new Vector2(-166f, -282f), new Vector2(250f, 48f), true, LoadUiSprite("", CheckpointIconAssetPath)); AddResultActionButton("다음 여행지 가기", ShowMapPreview, new Vector2(160f, -282f), new Vector2(292f, 48f), false, LoadUiSprite("", AirplaneTravelIconAssetPath)); } } private void ApplyResultAirportBackground() { if(overlayBackground != null) { overlayBackground.sprite = LoadUiSprite(ResultAirportBackgroundResourcePath, "Assets/Resources/Map_Tutorial_Incheon_Airport.png"); overlayBackground.preserveAspect = false; overlayBackground.color = overlayBackground.sprite != null ? Color.white : new Color(0.008f, 0.024f, 0.034f, 0.96f); } if(flowCamera != null) { flowCamera.backgroundColor = new Color(0.006f, 0.022f, 0.035f, 1f); } GameObject scrimObject = CreateUiObject("Result Airport Background Scrim", overlayRoot, typeof(Image)); RectTransform scrimRect = scrimObject.GetComponent(); scrimRect.anchorMin = Vector2.zero; scrimRect.anchorMax = Vector2.one; scrimRect.offsetMin = Vector2.zero; scrimRect.offsetMax = Vector2.zero; Image scrimImage = scrimObject.GetComponent(); scrimImage.color = new Color(0.005f, 0.015f, 0.020f, 0.30f); scrimImage.raycastTarget = false; } private RectTransform AddResultPassportPanel() { GameObject panelObject = CreateUiObject("Result Passport Page", overlayRoot, typeof(Image)); RectTransform panelRect = panelObject.GetComponent(); panelRect.anchorMin = new Vector2(0.5f, 0.5f); panelRect.anchorMax = new Vector2(0.5f, 0.5f); panelRect.pivot = new Vector2(0.5f, 0.5f); panelRect.anchoredPosition = new Vector2(0f, 38f); panelRect.sizeDelta = new Vector2(1092f, 330f); Image panelImage = panelObject.GetComponent(); panelImage.sprite = LoadUiSprite(ResultPassportPanelResourcePath, ResultPassportPanelAssetPath); panelImage.color = panelImage.sprite != null ? Color.white : new Color(0.95f, 0.91f, 0.80f, 0.98f); panelImage.preserveAspect = true; panelImage.raycastTarget = false; return panelRect; } private void AddResultHeader(RectTransform parent, MapDefinition resultMap) { Sprite rankSprite = LoadUiSprite("", ClearRankIconAssetPath); AddResultImage(parent, "Result Rank Badge", rankSprite, new Vector2(150f, -140f), new Vector2(48f, 48f), true, Color.white); string title = lastResultCleared ? "출국 성공" : "일정 실패"; Color titleColor = lastResultCleared ? new Color(0.05f, 0.17f, 0.27f, 1f) : new Color(0.52f, 0.08f, 0.07f, 1f); AddResultCenteredText(parent, "Result Title", title, new Vector2(244f, -140f), new Vector2(220f, 50f), 25f, FontStyles.Bold, titleColor, TextAlignmentOptions.Center); AddResultRouteBox(parent, "From", GetResultOriginAirportCode(resultMap), GetResultOriginCityName(resultMap), new Vector2(440f, -122f)); AddResultRouteBox(parent, "To", GetResultDestinationAirportCode(resultMap), GetResultDestinationCityName(resultMap), new Vector2(660f, -122f)); AddResultBoardingField(parent, "Flight", "항공편", GetResultFlightName(resultMap), new Vector2(400f, -253f)); AddResultBoardingField(parent, "Seat", "좌석", GetResultSeatName(resultMap), new Vector2(497f, -253f)); AddResultBoardingField(parent, "Boarding", "탑승", System.DateTime.Now.ToString("HH:mm"), new Vector2(595f, -253f)); AddResultBoardingField(parent, "Class", "클래스", lastResultCleared ? "일반석" : "대기", new Vector2(695f, -253f)); } private void AddResultStats(RectTransform parent, int gainedMileage, int shownDistance, int targetDistance) { AddResultStat(parent, "Mileage", LoadUiSprite("", MileageIconAssetPath), "마일리지", "+" + gainedMileage, new Vector2(812f, -140f)); AddResultStat(parent, "Time", LoadUiSprite("", TimerIconAssetPath), "도착 시간", lastResultTime.ToString("0.0") + "s", new Vector2(903f, -140f)); string distance = targetDistance > 0 ? shownDistance + "/" + targetDistance + "m" : shownDistance + "m"; AddResultStat(parent, "Distance", LoadUiSprite("", CheckpointIconAssetPath), "이동 거리", distance, new Vector2(993f, -140f)); } private void AddResultTickets(RectTransform parent, MapDefinition resultMap, int rewardMileage) { AddResultTicket( parent, "Destination", LoadUiSprite("", CheckpointIconAssetPath), "목적지", GetResultDestinationCityName(resultMap), new Vector2(812f, -251f)); AddResultTicket( parent, "Souvenir", lastResultCleared ? GetResultSouvenirSprite(resultMap) : LoadUiSprite("", SouvenirCollectionIconAssetPath), "보상", lastResultCleared ? GetResultSouvenirName(resultMap) : "다음 도전", new Vector2(900f, -251f)); AddResultTicket( parent, "Total Mileage", LoadUiSprite("", MileageIconAssetPath), "보유", saveData.totalMileage + " M", new Vector2(991f, -251f)); } private void AddResultStat(RectTransform parent, string objectName, Sprite iconSprite, string label, string value, Vector2 centerPosition) { AddResultImage(parent, "Result " + objectName + " Icon", iconSprite, centerPosition + new Vector2(0f, 5f), new Vector2(26f, 26f), true, Color.white); AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -17f), new Vector2(90f, 22f), 12f, FontStyles.Bold, new Color(0.05f, 0.17f, 0.25f, 1f), TextAlignmentOptions.Center); AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, -32f), new Vector2(90f, 16f), 8f, FontStyles.Bold, new Color(0.42f, 0.58f, 0.64f, 0.92f), TextAlignmentOptions.Center); } private void AddResultTicket(RectTransform parent, string objectName, Sprite iconSprite, string label, string value, Vector2 centerPosition) { AddResultImage(parent, "Result " + objectName + " Icon", iconSprite, centerPosition + new Vector2(0f, 27f), new Vector2(34f, 34f), true, Color.white); AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, -9f), new Vector2(110f, 18f), 11f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center); AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -35f), new Vector2(118f, 26f), 11f, FontStyles.Bold, new Color(0.05f, 0.18f, 0.27f, 1f), TextAlignmentOptions.Center); } private void AddResultRouteBox(RectTransform parent, string objectName, string code, string cityName, Vector2 centerPosition) { AddResultCenteredText(parent, "Result " + objectName + " Airport Code", code, centerPosition + new Vector2(0f, 7f), new Vector2(150f, 48f), 34f, FontStyles.Bold, new Color(0.05f, 0.17f, 0.27f, 1f), TextAlignmentOptions.Center); AddResultCenteredText(parent, "Result " + objectName + " City", cityName, centerPosition + new Vector2(0f, -30f), new Vector2(160f, 22f), 12f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center); } private void AddResultBoardingField(RectTransform parent, string objectName, string label, string value, Vector2 centerPosition) { AddResultCenteredText(parent, "Result " + objectName + " Label", label, centerPosition + new Vector2(0f, 13f), new Vector2(104f, 17f), 9f, FontStyles.Bold, new Color(0.43f, 0.58f, 0.64f, 0.96f), TextAlignmentOptions.Center); AddResultCenteredText(parent, "Result " + objectName + " Value", value, centerPosition + new Vector2(0f, -12f), new Vector2(108f, 28f), 14f, FontStyles.Bold, new Color(0.05f, 0.18f, 0.27f, 1f), TextAlignmentOptions.Center); } private void AddResultActionButton(string label, UnityEngine.Events.UnityAction action, Vector2 position, Vector2 size, bool primary, Sprite iconSprite) { GameObject buttonObject = CreateUiObject("Result Button " + label, overlayRoot, typeof(Image), typeof(Button)); RectTransform buttonRect = buttonObject.GetComponent(); buttonRect.anchorMin = new Vector2(0.5f, 0.5f); buttonRect.anchorMax = new Vector2(0.5f, 0.5f); buttonRect.pivot = new Vector2(0.5f, 0.5f); buttonRect.anchoredPosition = position; buttonRect.sizeDelta = size; Image buttonImage = buttonObject.GetComponent(); buttonImage.sprite = LoadUiSprite(ResultButtonResourcePath, ResultButtonAssetPath); buttonImage.color = buttonImage.sprite != null ? (primary ? Color.white : new Color(0.86f, 0.94f, 1f, 0.94f)) : primary ? new Color(1f, 0.82f, 0.28f, 0.98f) : new Color(0.82f, 0.91f, 0.96f, 0.90f); buttonImage.preserveAspect = false; buttonImage.raycastTarget = true; Button button = buttonObject.GetComponent