超大量的更新 修复很多问题,gameplay特效初步
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
using System.Collections;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class UI_CharacterDialogController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private string requiredSceneName = "UI_UI";
|
||||
[SerializeField] private string characterObjectName = "Image_Character";
|
||||
[SerializeField] private string dialogObjectName = "UI_DIALOG";
|
||||
|
||||
[Header("Enter")]
|
||||
[SerializeField] private float enterDuration = 0.3f;
|
||||
[SerializeField] private float enterFromOffsetY = 60f;
|
||||
[SerializeField] private Ease enterEase = Ease.OutCubic;
|
||||
|
||||
[Header("Blink Out")]
|
||||
[SerializeField] private int blinkCount = 2;
|
||||
[SerializeField] private float blinkHalfTime = 0.05f;
|
||||
|
||||
[Header("Auto Hide")]
|
||||
[SerializeField] private float idleHideDelay = 5f;
|
||||
[SerializeField] private bool useUnscaledTime = true;
|
||||
|
||||
private RectTransform dialogRect;
|
||||
private CanvasGroup dialogGroup;
|
||||
private Vector2 dialogBasePos;
|
||||
private bool basePosCached;
|
||||
private RectTransform boundCharacterRect;
|
||||
private int bindAttemptToken;
|
||||
private bool isVisible;
|
||||
private Coroutine idleRoutine;
|
||||
private Coroutine bindRoutine;
|
||||
private Coroutine keepAliveRoutine;
|
||||
private Sequence dialogSequence;
|
||||
private UI_CharacterDialogClickProxy clickProxy;
|
||||
private Button characterButton;
|
||||
private bool initialHideDone;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
|
||||
SceneManager.activeSceneChanged += OnActiveSceneChanged;
|
||||
|
||||
RebindSoon();
|
||||
if (keepAliveRoutine == null)
|
||||
keepAliveRoutine = StartCoroutine(KeepBindingAliveRoutine());
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
|
||||
|
||||
KillTweens();
|
||||
if (characterButton != null)
|
||||
{
|
||||
characterButton.onClick.RemoveListener(OnCharacterClicked);
|
||||
characterButton = null;
|
||||
}
|
||||
if (idleRoutine != null)
|
||||
{
|
||||
StopCoroutine(idleRoutine);
|
||||
idleRoutine = null;
|
||||
}
|
||||
if (bindRoutine != null)
|
||||
{
|
||||
StopCoroutine(bindRoutine);
|
||||
bindRoutine = null;
|
||||
}
|
||||
if (keepAliveRoutine != null)
|
||||
{
|
||||
StopCoroutine(keepAliveRoutine);
|
||||
keepAliveRoutine = null;
|
||||
}
|
||||
|
||||
clickProxy = null;
|
||||
dialogRect = null;
|
||||
dialogGroup = null;
|
||||
boundCharacterRect = null;
|
||||
basePosCached = false;
|
||||
initialHideDone = false;
|
||||
}
|
||||
|
||||
public void RebindSoon()
|
||||
{
|
||||
bindAttemptToken++;
|
||||
if (bindRoutine != null)
|
||||
StopCoroutine(bindRoutine);
|
||||
bindRoutine = StartCoroutine(BindRoutine(bindAttemptToken));
|
||||
}
|
||||
|
||||
private IEnumerator BindRoutine(int token)
|
||||
{
|
||||
yield return null;
|
||||
TryBind();
|
||||
yield return null;
|
||||
if (token != bindAttemptToken)
|
||||
yield break;
|
||||
yield return null;
|
||||
TryBind();
|
||||
if (token != bindAttemptToken)
|
||||
yield break;
|
||||
yield return null;
|
||||
TryBind();
|
||||
if (token != bindAttemptToken)
|
||||
yield break;
|
||||
yield return new WaitForSecondsRealtime(0.2f);
|
||||
TryBind();
|
||||
if (token != bindAttemptToken)
|
||||
yield break;
|
||||
yield return new WaitForSecondsRealtime(0.6f);
|
||||
TryBind();
|
||||
bindRoutine = null;
|
||||
}
|
||||
|
||||
private void TryBind()
|
||||
{
|
||||
if (!IsAllowedScene())
|
||||
return;
|
||||
|
||||
Scene scene = gameObject.scene;
|
||||
if (!scene.IsValid() || !scene.isLoaded)
|
||||
scene = SceneManager.GetActiveScene();
|
||||
|
||||
Transform dialogTr = FindInSceneByName(scene, dialogObjectName);
|
||||
if (dialogTr == null)
|
||||
dialogTr = FindInSceneByName(SceneManager.GetActiveScene(), dialogObjectName);
|
||||
if (dialogTr != null)
|
||||
{
|
||||
RectTransform nextDialogRect = dialogTr as RectTransform;
|
||||
bool dialogChanged = dialogRect != nextDialogRect;
|
||||
dialogRect = nextDialogRect;
|
||||
if (dialogRect != null)
|
||||
{
|
||||
dialogGroup = dialogRect.GetComponent<CanvasGroup>();
|
||||
if (dialogGroup == null)
|
||||
dialogGroup = dialogRect.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
if (dialogChanged || !basePosCached)
|
||||
{
|
||||
dialogBasePos = dialogRect.anchoredPosition;
|
||||
basePosCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialHideDone)
|
||||
{
|
||||
HideImmediate();
|
||||
initialHideDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
Transform characterTr = FindInSceneByName(scene, characterObjectName);
|
||||
if (characterTr == null)
|
||||
characterTr = FindInSceneByName(SceneManager.GetActiveScene(), characterObjectName);
|
||||
if (characterTr != null)
|
||||
{
|
||||
boundCharacterRect = characterTr as RectTransform;
|
||||
clickProxy = characterTr.GetComponent<UI_CharacterDialogClickProxy>();
|
||||
if (clickProxy == null)
|
||||
clickProxy = characterTr.gameObject.AddComponent<UI_CharacterDialogClickProxy>();
|
||||
clickProxy.Bind(this);
|
||||
|
||||
// Ensure the image can receive click events.
|
||||
Graphic graphic = characterTr.GetComponent<Graphic>();
|
||||
if (graphic != null)
|
||||
graphic.raycastTarget = true;
|
||||
|
||||
// Also bind through Button click to avoid missing pointer callbacks.
|
||||
Button btn = characterTr.GetComponent<Button>();
|
||||
if (btn == null)
|
||||
{
|
||||
btn = characterTr.gameObject.AddComponent<Button>();
|
||||
btn.transition = Selectable.Transition.None;
|
||||
if (graphic != null)
|
||||
btn.targetGraphic = graphic;
|
||||
}
|
||||
|
||||
if (characterButton != null && characterButton != btn)
|
||||
characterButton.onClick.RemoveListener(OnCharacterClicked);
|
||||
characterButton = btn;
|
||||
characterButton.onClick.RemoveListener(OnCharacterClicked);
|
||||
characterButton.onClick.AddListener(OnCharacterClicked);
|
||||
}
|
||||
else
|
||||
{
|
||||
boundCharacterRect = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCharacterClicked()
|
||||
{
|
||||
if (!IsBindingValid())
|
||||
TryBind();
|
||||
|
||||
if (dialogRect == null || dialogGroup == null || !basePosCached)
|
||||
return;
|
||||
|
||||
if (isVisible)
|
||||
{
|
||||
BlinkOut(() => PlayEnter(), deactivateAtEnd: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayEnter();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayEnter()
|
||||
{
|
||||
if (dialogRect == null || dialogGroup == null)
|
||||
return;
|
||||
|
||||
KillTweens();
|
||||
dialogRect.gameObject.SetActive(true);
|
||||
dialogRect.anchoredPosition = dialogBasePos - new Vector2(0f, Mathf.Abs(enterFromOffsetY));
|
||||
dialogGroup.alpha = 0f;
|
||||
|
||||
dialogSequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
|
||||
dialogSequence.Join(dialogRect.DOAnchorPos(dialogBasePos, Mathf.Max(0.01f, enterDuration)).SetEase(enterEase));
|
||||
dialogSequence.Join(dialogGroup.DOFade(1f, Mathf.Max(0.01f, enterDuration)).SetEase(Ease.OutCubic));
|
||||
dialogSequence.OnComplete(() => dialogSequence = null);
|
||||
|
||||
isVisible = true;
|
||||
RestartIdleTimer();
|
||||
}
|
||||
|
||||
private void BlinkOut(System.Action onComplete, bool deactivateAtEnd)
|
||||
{
|
||||
if (dialogRect == null || dialogGroup == null)
|
||||
{
|
||||
onComplete?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
KillTweens();
|
||||
dialogRect.gameObject.SetActive(true);
|
||||
|
||||
dialogSequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
|
||||
int blinks = Mathf.Max(1, blinkCount);
|
||||
float half = Mathf.Max(0.01f, blinkHalfTime);
|
||||
for (int i = 0; i < blinks; i++)
|
||||
{
|
||||
dialogSequence.Append(dialogGroup.DOFade(0f, half).SetEase(Ease.OutQuad));
|
||||
dialogSequence.Append(dialogGroup.DOFade(1f, half).SetEase(Ease.OutQuad));
|
||||
}
|
||||
dialogSequence.Append(dialogGroup.DOFade(0f, half).SetEase(Ease.OutQuad));
|
||||
dialogSequence.OnComplete(() =>
|
||||
{
|
||||
dialogSequence = null;
|
||||
isVisible = false;
|
||||
if (deactivateAtEnd && dialogRect != null)
|
||||
dialogRect.gameObject.SetActive(false);
|
||||
onComplete?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
private void RestartIdleTimer()
|
||||
{
|
||||
if (idleRoutine != null)
|
||||
StopCoroutine(idleRoutine);
|
||||
idleRoutine = StartCoroutine(IdleHideRoutine());
|
||||
}
|
||||
|
||||
private IEnumerator IdleHideRoutine()
|
||||
{
|
||||
float delay = Mathf.Max(0.2f, idleHideDelay);
|
||||
float t = 0f;
|
||||
while (t < delay)
|
||||
{
|
||||
t += useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (isVisible)
|
||||
{
|
||||
BlinkOut(onComplete: null, deactivateAtEnd: true);
|
||||
}
|
||||
idleRoutine = null;
|
||||
}
|
||||
|
||||
private void HideImmediate()
|
||||
{
|
||||
if (dialogRect == null || dialogGroup == null)
|
||||
return;
|
||||
|
||||
KillTweens();
|
||||
dialogGroup.alpha = 0f;
|
||||
dialogRect.anchoredPosition = dialogBasePos;
|
||||
dialogRect.gameObject.SetActive(false);
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
private void KillTweens()
|
||||
{
|
||||
if (dialogSequence != null)
|
||||
{
|
||||
dialogSequence.Kill();
|
||||
dialogSequence = null;
|
||||
}
|
||||
if (dialogRect != null)
|
||||
dialogRect.DOKill();
|
||||
if (dialogGroup != null)
|
||||
dialogGroup.DOKill();
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (string.Equals(scene.name, requiredSceneName, System.StringComparison.OrdinalIgnoreCase))
|
||||
RebindSoon();
|
||||
}
|
||||
|
||||
private void OnActiveSceneChanged(Scene from, Scene to)
|
||||
{
|
||||
if (string.Equals(to.name, requiredSceneName, System.StringComparison.OrdinalIgnoreCase))
|
||||
RebindSoon();
|
||||
}
|
||||
|
||||
private IEnumerator KeepBindingAliveRoutine()
|
||||
{
|
||||
while (enabled)
|
||||
{
|
||||
if (IsAllowedScene() && !IsBindingValid())
|
||||
RebindSoon();
|
||||
yield return new WaitForSecondsRealtime(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsBindingValid()
|
||||
{
|
||||
if (!IsAllowedScene())
|
||||
return false;
|
||||
|
||||
if (dialogRect == null || dialogGroup == null || !basePosCached)
|
||||
return false;
|
||||
if (boundCharacterRect == null)
|
||||
return false;
|
||||
if (characterButton == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsAllowedScene()
|
||||
{
|
||||
if (string.IsNullOrEmpty(requiredSceneName))
|
||||
return true;
|
||||
|
||||
Scene own = gameObject.scene;
|
||||
if (own.IsValid() && string.Equals(own.name, requiredSceneName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
Scene active = SceneManager.GetActiveScene();
|
||||
return active.IsValid() && string.Equals(active.name, requiredSceneName, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private Transform FindInSceneByName(Scene scene, string objectName)
|
||||
{
|
||||
if (!scene.IsValid() || !scene.isLoaded || string.IsNullOrEmpty(objectName))
|
||||
return null;
|
||||
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null || t.gameObject.scene != scene)
|
||||
continue;
|
||||
if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class UI_CharacterDialogClickProxy : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
private UI_CharacterDialogController controller;
|
||||
|
||||
public void Bind(UI_CharacterDialogController owner)
|
||||
{
|
||||
controller = owner;
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
controller?.OnCharacterClicked();
|
||||
}
|
||||
}
|
||||
|
||||
static class UI_CharacterDialogControllerBootstrap
|
||||
{
|
||||
private const string SceneName = "UI_UI";
|
||||
private const string HostName = "__UICharacterDialogControllerHost";
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Init()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
if (!string.Equals(scene.name, SceneName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
GameObject host = FindHostInScene(scene, HostName);
|
||||
if (host == null)
|
||||
{
|
||||
host = new GameObject(HostName);
|
||||
SceneManager.MoveGameObjectToScene(host, scene);
|
||||
}
|
||||
|
||||
UI_CharacterDialogController controller = host.GetComponent<UI_CharacterDialogController>();
|
||||
if (controller == null)
|
||||
controller = host.AddComponent<UI_CharacterDialogController>();
|
||||
controller.RebindSoon();
|
||||
}
|
||||
|
||||
private static GameObject FindHostInScene(Scene scene, string hostName)
|
||||
{
|
||||
if (!scene.IsValid() || !scene.isLoaded)
|
||||
return null;
|
||||
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null || t.gameObject.scene != scene)
|
||||
continue;
|
||||
if (t.name == hostName)
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51eb8dcab528ffb46855652bbb8c71e9
|
||||
@@ -37,7 +37,7 @@ class UI_Panel_Character : MonoBehaviour
|
||||
}
|
||||
else if(canvasGroup == null)
|
||||
{
|
||||
//Debug.LogError("Error for getting canvas group!");
|
||||
// Documentation text normalized.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,4 +118,4 @@ class UI_Panel_Character : MonoBehaviour
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -274,8 +274,7 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
var so = Instantiate(item);
|
||||
data_List.Add(so);
|
||||
|
||||
// 每处理 5 个数据等待一帧,防止主线程卡死
|
||||
if (i > 0 && i % 5 == 0)
|
||||
// Documentation text normalized.
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
@@ -324,6 +323,13 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (panel == ui_Panel_Setting)
|
||||
{
|
||||
UI_SettingsPanelEnterAnim enterAnim = panel.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (enterAnim == null)
|
||||
enterAnim = panel.AddComponent<UI_SettingsPanelEnterAnim>();
|
||||
enterAnim.enabled = true;
|
||||
}
|
||||
panel.SetActive(true);
|
||||
return true;
|
||||
}
|
||||
@@ -334,7 +340,7 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
return;
|
||||
}
|
||||
selectScene_Loading = true;
|
||||
// 使用异步加载场景,防止 GUI 冻结
|
||||
// Documentation text normalized.
|
||||
StartCoroutine(LoadSelectSceneAsync());
|
||||
}
|
||||
|
||||
@@ -342,7 +348,7 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
{
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(ui_Select_Music_Scene_Name, LoadSceneMode.Single);
|
||||
|
||||
// 等待加载完成
|
||||
// Documentation text normalized.
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
@@ -362,6 +368,8 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
Setup_RightButtons_Hover();
|
||||
Setup_Jiantou_Hover();
|
||||
Fix_Button_Raycast();
|
||||
Ensure_Character_Dialog_Controller();
|
||||
StartCoroutine(Ensure_Character_Dialog_Controller_Delayed());
|
||||
if (play_Enter_OnEnable)
|
||||
{
|
||||
Start_Enter_Routine();
|
||||
@@ -371,6 +379,55 @@ public class UI_Panel_Main : Singleton_Mono<UI_Panel_Main>
|
||||
Start_Jiantou_Loop();
|
||||
}
|
||||
}
|
||||
IEnumerator Ensure_Character_Dialog_Controller_Delayed()
|
||||
{
|
||||
yield return null;
|
||||
Ensure_Character_Dialog_Controller();
|
||||
yield return null;
|
||||
Ensure_Character_Dialog_Controller();
|
||||
}
|
||||
void Ensure_Character_Dialog_Controller()
|
||||
{
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
if (!scene.IsValid() || !string.Equals(scene.name, "UI_UI", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject host = null;
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null || t.gameObject.scene != scene)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (string.Equals(t.name, "__UICharacterDialogControllerHost", StringComparison.Ordinal))
|
||||
{
|
||||
host = t.gameObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (host == null)
|
||||
{
|
||||
host = new GameObject("__UICharacterDialogControllerHost");
|
||||
try { SceneManager.MoveGameObjectToScene(host, scene); } catch { }
|
||||
}
|
||||
|
||||
UI_CharacterDialogController controller = host.GetComponent<UI_CharacterDialogController>();
|
||||
if (controller == null)
|
||||
{
|
||||
controller = host.AddComponent<UI_CharacterDialogController>();
|
||||
}
|
||||
|
||||
if (!controller.enabled)
|
||||
{
|
||||
controller.enabled = true;
|
||||
}
|
||||
controller.RebindSoon();
|
||||
}
|
||||
void Fix_Button_Raycast()
|
||||
{
|
||||
if (!fix_Button_Raycast)
|
||||
@@ -3234,15 +3291,17 @@ public class UI_RightButtonHover : MonoBehaviour, IPointerEnterHandler, IPointer
|
||||
float textFlashInterval = 0.02f;
|
||||
RectTransform imageRect;
|
||||
Vector2 imageBasePos;
|
||||
CanvasGroup imageGroup;
|
||||
readonly List<CanvasGroup> textGroups = new();
|
||||
Tween imageTween;
|
||||
readonly List<Tween> textTweens = new();
|
||||
|
||||
public void ApplyConfig(float idleOffsetValue, float finalOffsetValue, float moveTimeValue, Ease moveEaseValue,
|
||||
float textFlashTimeValue, int textFlashCountValue, float textFlashIntervalValue)
|
||||
{
|
||||
idleOffset = Mathf.Max(0f, idleOffsetValue);
|
||||
finalOffset = finalOffsetValue;
|
||||
// Keep icon inside the button frame: positive config means "shift left by this amount".
|
||||
// Use a softened offset so icon sits slightly more to the right.
|
||||
finalOffset = -Mathf.Abs(finalOffsetValue) * 0.75f;
|
||||
moveTime = Mathf.Max(0.01f, moveTimeValue);
|
||||
moveEase = moveEaseValue;
|
||||
textFlashTime = Mathf.Max(0.01f, textFlashTimeValue);
|
||||
@@ -3276,6 +3335,12 @@ public class UI_RightButtonHover : MonoBehaviour, IPointerEnterHandler, IPointer
|
||||
if (imageRect != null)
|
||||
{
|
||||
imageBasePos = imageRect.anchoredPosition;
|
||||
if (imageGroup == null)
|
||||
{
|
||||
imageGroup = imageRect.GetComponent<CanvasGroup>();
|
||||
if (imageGroup == null)
|
||||
imageGroup = imageRect.gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
textGroups.Clear();
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
@@ -3318,32 +3383,36 @@ public class UI_RightButtonHover : MonoBehaviour, IPointerEnterHandler, IPointer
|
||||
{
|
||||
if (imageRect != null)
|
||||
{
|
||||
imageRect.anchoredPosition = imageBasePos + Vector2.left * idleOffset;
|
||||
// Keep icon at its final position; only toggle visibility on hover.
|
||||
imageRect.anchoredPosition = imageBasePos + Vector2.right * finalOffset;
|
||||
}
|
||||
if (imageGroup != null)
|
||||
{
|
||||
imageGroup.alpha = 0f; // hidden until hover
|
||||
}
|
||||
for (int i = 0; i < textGroups.Count; i++)
|
||||
{
|
||||
if (textGroups[i] != null)
|
||||
{
|
||||
textGroups[i].alpha = 0f;
|
||||
// Text should always be visible (no flash-in).
|
||||
textGroups[i].alpha = 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
MoveImage(true);
|
||||
FlashTexts();
|
||||
FlashImage();
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
MoveImage(false);
|
||||
HideTexts();
|
||||
HideImage();
|
||||
}
|
||||
|
||||
void MoveImage(bool toFinal)
|
||||
void FlashImage()
|
||||
{
|
||||
if (imageRect == null)
|
||||
if (imageRect == null || imageGroup == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3352,69 +3421,42 @@ public class UI_RightButtonHover : MonoBehaviour, IPointerEnterHandler, IPointer
|
||||
imageTween.Kill();
|
||||
imageTween = null;
|
||||
}
|
||||
Vector2 target = toFinal
|
||||
? imageBasePos + Vector2.right * finalOffset
|
||||
: imageBasePos + Vector2.left * idleOffset;
|
||||
imageTween = imageRect.DOAnchorPos(target, moveTime)
|
||||
.SetEase(moveEase)
|
||||
.SetUpdate(true);
|
||||
}
|
||||
|
||||
void FlashTexts()
|
||||
{
|
||||
HideTexts();
|
||||
for (int i = 0; i < textGroups.Count; i++)
|
||||
{
|
||||
CanvasGroup group = textGroups[i];
|
||||
if (group == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
group.alpha = 0f;
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(true);
|
||||
for (int c = 0; c < textFlashCount; c++)
|
||||
{
|
||||
seq.Append(group.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
|
||||
seq.Append(group.DOFade(0f, textFlashTime).SetEase(Ease.InQuad));
|
||||
if (textFlashInterval > 0f)
|
||||
{
|
||||
seq.AppendInterval(textFlashInterval);
|
||||
}
|
||||
}
|
||||
seq.Append(group.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
|
||||
textTweens.Add(seq);
|
||||
}
|
||||
}
|
||||
// Ensure icon is at its final position (no translation anim).
|
||||
imageRect.anchoredPosition = imageBasePos + Vector2.right * finalOffset;
|
||||
|
||||
void HideTexts()
|
||||
{
|
||||
for (int i = 0; i < textTweens.Count; i++)
|
||||
// Flash-in (blink) on hover, then stay visible.
|
||||
imageGroup.alpha = 0f;
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(true);
|
||||
for (int c = 0; c < textFlashCount; c++)
|
||||
{
|
||||
Tween tween = textTweens[i];
|
||||
if (tween != null)
|
||||
seq.Append(imageGroup.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
|
||||
seq.Append(imageGroup.DOFade(0f, textFlashTime).SetEase(Ease.InQuad));
|
||||
if (textFlashInterval > 0f)
|
||||
{
|
||||
tween.Kill();
|
||||
}
|
||||
}
|
||||
textTweens.Clear();
|
||||
for (int i = 0; i < textGroups.Count; i++)
|
||||
{
|
||||
CanvasGroup group = textGroups[i];
|
||||
if (group != null)
|
||||
{
|
||||
group.alpha = 0f;
|
||||
seq.AppendInterval(textFlashInterval);
|
||||
}
|
||||
}
|
||||
seq.Append(imageGroup.DOFade(1f, textFlashTime).SetEase(Ease.OutQuad));
|
||||
imageTween = seq;
|
||||
}
|
||||
|
||||
void KillTweens()
|
||||
void HideImage()
|
||||
{
|
||||
if (imageTween != null)
|
||||
{
|
||||
imageTween.Kill();
|
||||
imageTween = null;
|
||||
}
|
||||
HideTexts();
|
||||
if (imageGroup != null)
|
||||
{
|
||||
imageGroup.alpha = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KillTweens()
|
||||
{
|
||||
HideImage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3603,7 +3645,7 @@ public class UI_StartButtonHover : MonoBehaviour, IPointerEnterHandler, IPointer
|
||||
char[] filler = new char[remain];
|
||||
for (int r = 0; r < remain; r++)
|
||||
{
|
||||
filler[r] = useDot ? '·' : randomChars[(i + r) % randomChars.Length];
|
||||
filler[r] = useDot ? '路' : randomChars[(i + r) % randomChars.Length];
|
||||
}
|
||||
suffix = new string(filler);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using DG.Tweening;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ui_Panel_Setting : MonoBehaviour
|
||||
{
|
||||
@@ -10,6 +12,19 @@ public class ui_Panel_Setting : MonoBehaviour
|
||||
[SerializeField] Toggle toggle_View;
|
||||
[SerializeField] Toggle toggle_View_Pie;
|
||||
[SerializeField] GameObject view_Content;
|
||||
|
||||
[Header("Enter Animation")]
|
||||
[SerializeField] bool playEnterAnimation = true;
|
||||
[SerializeField] float enterItemDuration = 0.24f;
|
||||
[SerializeField] float enterItemStagger = 0.03f;
|
||||
[SerializeField] float enterOffsetY = 28f;
|
||||
[SerializeField] Ease enterEase = Ease.OutCubic;
|
||||
|
||||
private readonly List<RectTransform> enterItems = new List<RectTransform>();
|
||||
private readonly List<CanvasGroup> enterGroups = new List<CanvasGroup>();
|
||||
private readonly List<Vector2> enterBasePos = new List<Vector2>();
|
||||
private Sequence enterSequence;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
button_Close?.onClick.AddListener(Close);
|
||||
@@ -36,6 +51,20 @@ public class ui_Panel_Setting : MonoBehaviour
|
||||
|
||||
toggle_Game.isOn = true;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (playEnterAnimation)
|
||||
{
|
||||
PlayEnterAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
KillEnterAnimation();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Escape))
|
||||
@@ -43,8 +72,79 @@ public class ui_Panel_Setting : MonoBehaviour
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayEnterAnimation()
|
||||
{
|
||||
KillEnterAnimation();
|
||||
CacheEnterItems();
|
||||
if (enterItems.Count == 0)
|
||||
return;
|
||||
|
||||
enterSequence = DOTween.Sequence().SetUpdate(true);
|
||||
for (int i = 0; i < enterItems.Count; i++)
|
||||
{
|
||||
RectTransform rt = enterItems[i];
|
||||
CanvasGroup cg = enterGroups[i];
|
||||
Vector2 basePos = enterBasePos[i];
|
||||
|
||||
if (rt == null || cg == null)
|
||||
continue;
|
||||
|
||||
rt.DOKill();
|
||||
cg.DOKill();
|
||||
|
||||
rt.anchoredPosition = basePos - new Vector2(0f, Mathf.Abs(enterOffsetY));
|
||||
cg.alpha = 0f;
|
||||
|
||||
float start = i * Mathf.Max(0f, enterItemStagger);
|
||||
enterSequence.Insert(start,
|
||||
rt.DOAnchorPos(basePos, Mathf.Max(0.01f, enterItemDuration))
|
||||
.SetEase(enterEase)
|
||||
.SetUpdate(true));
|
||||
enterSequence.Insert(start,
|
||||
cg.DOFade(1f, Mathf.Max(0.01f, enterItemDuration))
|
||||
.SetEase(Ease.OutCubic)
|
||||
.SetUpdate(true));
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheEnterItems()
|
||||
{
|
||||
enterItems.Clear();
|
||||
enterGroups.Clear();
|
||||
enterBasePos.Clear();
|
||||
|
||||
for (int i = 0; i < transform.childCount; i++)
|
||||
{
|
||||
Transform child = transform.GetChild(i);
|
||||
if (child == null || !child.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
RectTransform rt = child as RectTransform;
|
||||
if (rt == null)
|
||||
continue;
|
||||
|
||||
CanvasGroup cg = rt.GetComponent<CanvasGroup>();
|
||||
if (cg == null)
|
||||
cg = rt.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
enterItems.Add(rt);
|
||||
enterGroups.Add(cg);
|
||||
enterBasePos.Add(rt.anchoredPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private void KillEnterAnimation()
|
||||
{
|
||||
if (enterSequence != null)
|
||||
{
|
||||
enterSequence.Kill();
|
||||
enterSequence = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class UI_SettingsPanelEnterAnim : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private RectTransform moveTarget;
|
||||
[SerializeField] private CanvasGroup fadeTarget;
|
||||
[SerializeField] private bool playOnEnable = true;
|
||||
[SerializeField] private float enterDuration = 0.3f;
|
||||
[SerializeField] private float fromOffsetY = 32f;
|
||||
[SerializeField] private Ease enterEase = Ease.OutCubic;
|
||||
[SerializeField] private bool useUnscaledTime = true;
|
||||
|
||||
private Sequence enterSequence;
|
||||
private bool basePosCached;
|
||||
private Vector2 basePos;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
AutoWire();
|
||||
CacheBasePos();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (playOnEnable)
|
||||
Play();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
KillTween();
|
||||
ResetToBase();
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
AutoWire();
|
||||
CacheBasePos();
|
||||
|
||||
if (moveTarget == null || fadeTarget == null)
|
||||
return;
|
||||
|
||||
KillTween();
|
||||
|
||||
moveTarget.anchoredPosition = basePos - new Vector2(0f, Mathf.Abs(fromOffsetY));
|
||||
fadeTarget.alpha = 0f;
|
||||
fadeTarget.interactable = false;
|
||||
fadeTarget.blocksRaycasts = false;
|
||||
|
||||
enterSequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
|
||||
enterSequence.Join(moveTarget.DOAnchorPos(basePos, Mathf.Max(0.01f, enterDuration)).SetEase(enterEase));
|
||||
enterSequence.Join(fadeTarget.DOFade(1f, Mathf.Max(0.01f, enterDuration)).SetEase(Ease.OutCubic));
|
||||
enterSequence.OnComplete(() =>
|
||||
{
|
||||
fadeTarget.interactable = true;
|
||||
fadeTarget.blocksRaycasts = true;
|
||||
enterSequence = null;
|
||||
});
|
||||
}
|
||||
|
||||
private void AutoWire()
|
||||
{
|
||||
if (moveTarget == null)
|
||||
{
|
||||
moveTarget = transform as RectTransform;
|
||||
if (moveTarget == null)
|
||||
moveTarget = GetComponentInChildren<RectTransform>(true);
|
||||
}
|
||||
|
||||
if (fadeTarget == null)
|
||||
fadeTarget = GetComponent<CanvasGroup>();
|
||||
if (fadeTarget == null)
|
||||
fadeTarget = gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
private void CacheBasePos()
|
||||
{
|
||||
if (moveTarget == null)
|
||||
return;
|
||||
|
||||
if (!basePosCached)
|
||||
{
|
||||
basePos = moveTarget.anchoredPosition;
|
||||
basePosCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetToBase()
|
||||
{
|
||||
if (moveTarget != null && basePosCached)
|
||||
moveTarget.anchoredPosition = basePos;
|
||||
|
||||
if (fadeTarget != null)
|
||||
{
|
||||
fadeTarget.alpha = 1f;
|
||||
fadeTarget.interactable = true;
|
||||
fadeTarget.blocksRaycasts = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void KillTween()
|
||||
{
|
||||
if (enterSequence != null)
|
||||
{
|
||||
enterSequence.Kill();
|
||||
enterSequence = null;
|
||||
}
|
||||
|
||||
if (moveTarget != null)
|
||||
moveTarget.DOKill();
|
||||
if (fadeTarget != null)
|
||||
fadeTarget.DOKill();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 128b12802ff1c684abfc7da39a0deb5c
|
||||
@@ -313,6 +313,127 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &698142945755259558
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 664855366139876558}
|
||||
- component: {fileID: 6815741791543722666}
|
||||
- component: {fileID: 1445541171937349538}
|
||||
- component: {fileID: 1221776354986423673}
|
||||
m_Layer: 0
|
||||
m_Name: back
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &664855366139876558
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 698142945755259558}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 8436329948899178167}
|
||||
m_Father: {fileID: 4201371652593379150}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 97, y: 97}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6815741791543722666
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 698142945755259558}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &1445541171937349538
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 698142945755259558}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 6349329690924382296, guid: ff06dc687af02f74c8fbd98368463fc2, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &1221776354986423673
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 698142945755259558}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 1445541171937349538}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &794346939895717571
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -829,6 +950,7 @@ RectTransform:
|
||||
- {fileID: 1216734273723155318}
|
||||
- {fileID: 4507029859229390628}
|
||||
- {fileID: 3166511394318740470}
|
||||
- {fileID: 4201371652593379150}
|
||||
m_Father: {fileID: 4008714089197239054}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
@@ -1702,6 +1824,81 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &1883765842619825806
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8344488991073226701}
|
||||
- component: {fileID: 8707209540160881515}
|
||||
- component: {fileID: 3843922392991303629}
|
||||
m_Layer: 0
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8344488991073226701
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1883765842619825806}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5977557715898357349}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.6977236, y: 0.32699218}
|
||||
m_AnchorMax: {x: 0.6977236, y: 0.32699218}
|
||||
m_AnchoredPosition: {x: -19.179, y: 16.782}
|
||||
m_SizeDelta: {x: 53.555, y: 53.5554}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &8707209540160881515
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1883765842619825806}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3843922392991303629
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1883765842619825806}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: d0ef0c9be447e1f4296eb8a4b9195c8c, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &1934290382038477745
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1777,6 +1974,71 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &2123526779575187879
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4201371652593379150}
|
||||
- component: {fileID: 4595481187193100221}
|
||||
m_Layer: 0
|
||||
m_Name: New back
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4201371652593379150
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2123526779575187879}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 5.504588}
|
||||
m_LocalScale: {x: 0.51, y: 0.51, z: 0.51}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children:
|
||||
- {fileID: 6419923115795927302}
|
||||
- {fileID: 664855366139876558}
|
||||
- {fileID: 5977557715898357349}
|
||||
m_Father: {fileID: 5634981615641515618}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -329.2, y: 0.00002670288}
|
||||
m_SizeDelta: {x: 2410.4807, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &4595481187193100221
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2123526779575187879}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: -2040.77
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &2157369845151287564
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2238,6 +2500,127 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: -675.6, y: -0.00005340576}
|
||||
m_SizeDelta: {x: 128, y: 30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &2496832619426805493
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5977557715898357349}
|
||||
- component: {fileID: 7995155685421482441}
|
||||
- component: {fileID: 3428519051158734592}
|
||||
- component: {fileID: 4088529162781090059}
|
||||
m_Layer: 0
|
||||
m_Name: home
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5977557715898357349
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2496832619426805493}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 8344488991073226701}
|
||||
m_Father: {fileID: 4201371652593379150}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 97, y: 97}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7995155685421482441
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2496832619426805493}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &3428519051158734592
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2496832619426805493}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 6349329690924382296, guid: ff06dc687af02f74c8fbd98368463fc2, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &4088529162781090059
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2496832619426805493}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 3428519051158734592}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &2529537244873479850
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4040,6 +4423,11 @@ MonoBehaviour:
|
||||
userInfo_prefab: {fileID: 0}
|
||||
email_prefab: {fileID: 3756075665884320709, guid: 41f4ea31b64f18d48aeef21b79930a6c, type: 3}
|
||||
notice_prefab: {fileID: 8527835049849151044, guid: 06bb6d3a45697374ab4f5ff36356d138, type: 3}
|
||||
back_navButton: {fileID: 0}
|
||||
home_navButton: {fileID: 0}
|
||||
settings_navButton: {fileID: 0}
|
||||
homeSceneName: UI_UI
|
||||
backFallbackSceneName: Main_main
|
||||
--- !u!114 &2510911207525280717
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4436,6 +4824,85 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &5455887339197002951
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 94861546549908736}
|
||||
- component: {fileID: 185682819927651411}
|
||||
- component: {fileID: 8311074806369947263}
|
||||
m_Layer: 0
|
||||
m_Name: Text (Legacy)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &94861546549908736
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5455887339197002951}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6419923115795927302}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 7.1215, y: -0.0335}
|
||||
m_SizeDelta: {x: 56.838, y: 58.3341}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &185682819927651411
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5455887339197002951}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8311074806369947263
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5455887339197002951}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: cc180dff846d13a4d88ddaed6f77e5cd, type: 3}
|
||||
m_FontSize: 44
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 44
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: "\uFF1F"
|
||||
--- !u!1 &5745207992015071035
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5469,6 +5936,128 @@ MonoBehaviour:
|
||||
m_Spacing: {x: 20, y: 20}
|
||||
m_Constraint: 1
|
||||
m_ConstraintCount: 4
|
||||
--- !u!1 &7302066207285333480
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6419923115795927302}
|
||||
- component: {fileID: 1613315426306319868}
|
||||
- component: {fileID: 510332109012089948}
|
||||
- component: {fileID: 6945238783669072533}
|
||||
m_Layer: 0
|
||||
m_Name: question
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6419923115795927302
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7302066207285333480}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4789218457072247502}
|
||||
- {fileID: 94861546549908736}
|
||||
m_Father: {fileID: 4201371652593379150}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 97, y: 97}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1613315426306319868
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7302066207285333480}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &510332109012089948
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7302066207285333480}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 6349329690924382296, guid: ff06dc687af02f74c8fbd98368463fc2, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &6945238783669072533
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7302066207285333480}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 510332109012089948}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &7324940213527366140
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6128,7 +6717,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &2726789671155220641
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6345,6 +6934,81 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8339357190892337068
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8436329948899178167}
|
||||
- component: {fileID: 4450874966179245808}
|
||||
- component: {fileID: 6474466730584838898}
|
||||
m_Layer: 0
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &8436329948899178167
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8339357190892337068}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 664855366139876558}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -0.0000038147, y: 0.000049591}
|
||||
m_SizeDelta: {x: 36.928, y: 36.928}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4450874966179245808
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8339357190892337068}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &6474466730584838898
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8339357190892337068}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 1172102457425465809, guid: b48603b1f2d0d6f428723f0d89e4dafc, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8442525676262455151
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6935,6 +7599,81 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8891292652493349475
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4789218457072247502}
|
||||
- component: {fileID: 3389991985103273735}
|
||||
- component: {fileID: 2938340339765009532}
|
||||
m_Layer: 0
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!224 &4789218457072247502
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8891292652493349475}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6419923115795927302}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.6977236, y: 0.32699218}
|
||||
m_AnchorMax: {x: 0.6977236, y: 0.32699218}
|
||||
m_AnchoredPosition: {x: -19.179, y: 16.782}
|
||||
m_SizeDelta: {x: 42.5956, y: 40.1846}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3389991985103273735
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8891292652493349475}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2938340339765009532
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8891292652493349475}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -7462228084874713130, guid: cad5616c19ca266448fcf54f97fe766d, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &8926842291454856642
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6969,7 +7708,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 163.2, y: 0}
|
||||
m_AnchoredPosition: {x: 232.8, y: 0}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3583705284184792287
|
||||
@@ -7007,13 +7746,13 @@ MonoBehaviour:
|
||||
m_BestFit: 0
|
||||
m_MinSize: 10
|
||||
m_MaxSize: 61
|
||||
m_Alignment: 4
|
||||
m_Alignment: 3
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 114
|
||||
m_Text: player_rks
|
||||
--- !u!1 &9065634752865683599
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class btmandtopController : MonoBehaviour
|
||||
{
|
||||
@@ -31,12 +33,22 @@ public class btmandtopController : MonoBehaviour
|
||||
public GameObject email_prefab;
|
||||
public GameObject notice_prefab;
|
||||
|
||||
[Header("New Back Buttons")]
|
||||
[SerializeField] private Button back_navButton;
|
||||
[SerializeField] private Button home_navButton;
|
||||
[SerializeField] private Button settings_navButton;
|
||||
[SerializeField] private string homeSceneName = "UI_UI";
|
||||
[SerializeField] private string backFallbackSceneName = "Main_main";
|
||||
|
||||
private UnityAction instantiateSettings;
|
||||
private UnityAction instantiateUserInfo;
|
||||
private UnityAction instantiateStore;
|
||||
private UnityAction instantiateShowLevel;
|
||||
private UnityAction instantiateEmail;
|
||||
private UnityAction instantiateNotice;
|
||||
private UnityAction navBackAction;
|
||||
private UnityAction navHomeAction;
|
||||
private UnityAction navSettingsAction;
|
||||
|
||||
// cached reference to the settings instance to ensure only one exists
|
||||
private GameObject settingsInstance;
|
||||
@@ -46,10 +58,16 @@ public class btmandtopController : MonoBehaviour
|
||||
private CanvasGroup musicPicGroup;
|
||||
private Coroutine musicPicFade;
|
||||
private bool musicPicVisible = true;
|
||||
private bool navSceneLoading = false;
|
||||
|
||||
private static readonly List<string> sceneHistory = new List<string>();
|
||||
private static bool sceneHistoryHooked = false;
|
||||
private static string trackedCurrentScene = string.Empty;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
EnsureMusicPicRoot();
|
||||
InitializeSceneHistoryIfNeeded();
|
||||
}
|
||||
|
||||
void Start()
|
||||
@@ -85,6 +103,8 @@ public class btmandtopController : MonoBehaviour
|
||||
if (notice_display != null)
|
||||
notice_display.onClick.AddListener(instantiateNotice);
|
||||
|
||||
BindNewBackButtons();
|
||||
|
||||
EnsureMusicPicRoot();
|
||||
SetupMusicPicDefault();
|
||||
if (button_Music != null)
|
||||
@@ -112,6 +132,7 @@ public class btmandtopController : MonoBehaviour
|
||||
if (settingsInstance == null)
|
||||
{
|
||||
settingsInstance = Instantiate(settings_prefab, putPrefabsHere.transform);
|
||||
EnsureSettingsEnterAnimator(settingsInstance);
|
||||
settingsInstance.SetActive(false);
|
||||
|
||||
// try to set canvas camera now as in previous behavior
|
||||
@@ -135,6 +156,7 @@ public class btmandtopController : MonoBehaviour
|
||||
{
|
||||
// ensure it's parented correctly under putPrefabsHere
|
||||
settingsInstance.transform.SetParent(putPrefabsHere.transform, false);
|
||||
EnsureSettingsEnterAnimator(settingsInstance);
|
||||
settingsInstance.SetActive(false);
|
||||
}
|
||||
}
|
||||
@@ -309,6 +331,13 @@ public class btmandtopController : MonoBehaviour
|
||||
|
||||
if (button_Music != null)
|
||||
button_Music.onClick.RemoveListener(ToggleMusicPicLocal);
|
||||
|
||||
if (back_navButton != null && navBackAction != null)
|
||||
back_navButton.onClick.RemoveListener(navBackAction);
|
||||
if (home_navButton != null && navHomeAction != null)
|
||||
home_navButton.onClick.RemoveListener(navHomeAction);
|
||||
if (settings_navButton != null && navSettingsAction != null)
|
||||
settings_navButton.onClick.RemoveListener(navSettingsAction);
|
||||
}
|
||||
|
||||
private void ToggleSettingsPrefab()
|
||||
@@ -319,6 +348,7 @@ public class btmandtopController : MonoBehaviour
|
||||
if (settingsInstance == null)
|
||||
{
|
||||
settingsInstance = Instantiate(settings_prefab, putPrefabsHere.transform);
|
||||
EnsureSettingsEnterAnimator(settingsInstance);
|
||||
|
||||
// attempt to set canvas camera
|
||||
try
|
||||
@@ -341,6 +371,8 @@ public class btmandtopController : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureSettingsEnterAnimator(settingsInstance);
|
||||
|
||||
// Toggle active state
|
||||
bool active = settingsInstance.activeSelf;
|
||||
settingsInstance.SetActive(!active);
|
||||
@@ -445,4 +477,174 @@ public class btmandtopController : MonoBehaviour
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSettingsEnterAnimator(GameObject instance)
|
||||
{
|
||||
if (instance == null) return;
|
||||
|
||||
UI_SettingsPanelEnterAnim anim = instance.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (anim == null)
|
||||
anim = instance.AddComponent<UI_SettingsPanelEnterAnim>();
|
||||
anim.enabled = true;
|
||||
}
|
||||
|
||||
private void BindNewBackButtons()
|
||||
{
|
||||
ResolveNewBackButtons();
|
||||
|
||||
navBackAction = OnBackNavClicked;
|
||||
navHomeAction = OnHomeNavClicked;
|
||||
navSettingsAction = OnSettingsNavClicked;
|
||||
|
||||
if (back_navButton != null)
|
||||
{
|
||||
back_navButton.onClick.RemoveListener(navBackAction);
|
||||
back_navButton.onClick.AddListener(navBackAction);
|
||||
}
|
||||
|
||||
if (home_navButton != null)
|
||||
{
|
||||
home_navButton.onClick.RemoveListener(navHomeAction);
|
||||
home_navButton.onClick.AddListener(navHomeAction);
|
||||
}
|
||||
|
||||
if (settings_navButton != null)
|
||||
{
|
||||
settings_navButton.onClick.RemoveListener(navSettingsAction);
|
||||
settings_navButton.onClick.AddListener(navSettingsAction);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveNewBackButtons()
|
||||
{
|
||||
Transform navRoot = FindChildRecursive(transform, "New back");
|
||||
if (navRoot == null)
|
||||
{
|
||||
GameObject sceneRoot = FindByName("New back");
|
||||
if (sceneRoot != null)
|
||||
navRoot = sceneRoot.transform;
|
||||
}
|
||||
|
||||
if (back_navButton == null)
|
||||
back_navButton = FindButtonByName(navRoot, "back");
|
||||
if (home_navButton == null)
|
||||
home_navButton = FindButtonByName(navRoot, "home");
|
||||
if (settings_navButton == null)
|
||||
settings_navButton = FindButtonByName(navRoot, "settings");
|
||||
}
|
||||
|
||||
private static Transform FindChildRecursive(Transform root, string childName)
|
||||
{
|
||||
if (root == null || string.IsNullOrEmpty(childName)) return null;
|
||||
if (root.name == childName) return root;
|
||||
|
||||
for (int i = 0; i < root.childCount; i++)
|
||||
{
|
||||
Transform child = root.GetChild(i);
|
||||
Transform found = FindChildRecursive(child, childName);
|
||||
if (found != null) return found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Button FindButtonByName(Transform root, string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
if (root != null)
|
||||
{
|
||||
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
Button btn = buttons[i];
|
||||
if (btn != null && string.Equals(btn.gameObject.name, name, System.StringComparison.OrdinalIgnoreCase))
|
||||
return btn;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void InitializeSceneHistoryIfNeeded()
|
||||
{
|
||||
if (sceneHistoryHooked) return;
|
||||
sceneHistoryHooked = true;
|
||||
trackedCurrentScene = SceneManager.GetActiveScene().name ?? string.Empty;
|
||||
SceneManager.sceneLoaded += OnSceneLoadedTrackHistory;
|
||||
}
|
||||
|
||||
private static void OnSceneLoadedTrackHistory(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
string incoming = scene.name ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(trackedCurrentScene) &&
|
||||
!string.Equals(trackedCurrentScene, incoming, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (sceneHistory.Count == 0 ||
|
||||
!string.Equals(sceneHistory[sceneHistory.Count - 1], trackedCurrentScene, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sceneHistory.Add(trackedCurrentScene);
|
||||
if (sceneHistory.Count > 24) sceneHistory.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
trackedCurrentScene = incoming;
|
||||
}
|
||||
|
||||
private static string PopPreviousSceneName(string currentScene)
|
||||
{
|
||||
for (int i = sceneHistory.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string candidate = sceneHistory[i];
|
||||
sceneHistory.RemoveAt(i);
|
||||
if (string.IsNullOrEmpty(candidate)) continue;
|
||||
if (string.Equals(candidate, currentScene, System.StringComparison.OrdinalIgnoreCase)) continue;
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnBackNavClicked()
|
||||
{
|
||||
if (navSceneLoading) return;
|
||||
InitializeSceneHistoryIfNeeded();
|
||||
|
||||
string current = SceneManager.GetActiveScene().name ?? string.Empty;
|
||||
string target = PopPreviousSceneName(current);
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
target = string.IsNullOrEmpty(backFallbackSceneName) ? "Main_main" : backFallbackSceneName;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(target) &&
|
||||
!string.Equals(target, current, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
StartCoroutine(LoadNavSceneAsync(target));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHomeNavClicked()
|
||||
{
|
||||
if (navSceneLoading) return;
|
||||
string target = string.IsNullOrEmpty(homeSceneName) ? "UI_UI" : homeSceneName;
|
||||
StartCoroutine(LoadNavSceneAsync(target));
|
||||
}
|
||||
|
||||
private void OnSettingsNavClicked()
|
||||
{
|
||||
ToggleSettingsPrefab();
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator LoadNavSceneAsync(string sceneName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sceneName)) yield break;
|
||||
if (navSceneLoading) yield break;
|
||||
|
||||
navSceneLoading = true;
|
||||
Time.timeScale = 1f;
|
||||
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
|
||||
while (op != null && !op.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
navSceneLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -55,14 +55,16 @@ public class Music_Mgr : Singleton_Mono<Music_Mgr>
|
||||
for (int i = 0; i < rawData.Length; i++)
|
||||
{
|
||||
Music_Data_List.Add(rawData[i]);
|
||||
// 每 10 个数据等待一帧
|
||||
if (i > 0 && i % 10 == 0) yield return null;
|
||||
// Avoid a frame hitch if there are many clips in Resources.
|
||||
if ((i & 7) == 7) yield return null;
|
||||
}
|
||||
|
||||
if (Music_Data_List.Count > 0)
|
||||
{
|
||||
Play(Music_Data_List[0]);
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
public void Play(Music_Data data)
|
||||
{
|
||||
@@ -74,4 +76,4 @@ public class Music_Mgr : Singleton_Mono<Music_Mgr>
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
// 通过 PlayTween() 触发动画
|
||||
// Documentation text normalized.
|
||||
public class SimpleAxisTween : MonoBehaviour
|
||||
{
|
||||
public enum Axis { X, Y } // 轴向选项
|
||||
public enum Axis { X, Y } // Documentation text normalized.
|
||||
|
||||
[Header("Tween Settings")]
|
||||
public Axis axis = Axis.X; // 要缓动的轴
|
||||
public float from = 0f; // 起始值
|
||||
public float to = 100f; // 终点值
|
||||
public float duration = 1f; // 总时长(秒)——外部可调
|
||||
|
||||
public Axis axis = Axis.X; // Documentation text normalized.
|
||||
public float from = 0f;
|
||||
public float to = 0f;
|
||||
[Min(0.01f)] public float duration = 0.35f;
|
||||
|
||||
public AnimationCurve ease = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
||||
|
||||
@@ -41,15 +40,15 @@ public class SimpleAxisTween : MonoBehaviour
|
||||
elapsed += Time.unscaledDeltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
float easedT = ease.Evaluate(t);
|
||||
float current = Mathf.Lerp(from, to, easedT);
|
||||
|
||||
// 缓动插值
|
||||
float current = Mathf.LerpUnclamped(from, to, easedT);
|
||||
// Documentation text normalized.
|
||||
SetPosition(current);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// 强制落在终点
|
||||
// Documentation text normalized.
|
||||
SetPosition(to);
|
||||
tweenCo = null;
|
||||
}
|
||||
@@ -71,4 +70,4 @@ public class SimpleAxisTween : MonoBehaviour
|
||||
transform.localPosition = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,88 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Simple pause manager. Call Pause(true) to pause or Pause(false) to resume.
|
||||
/// - overlayRoot: GameObject that will be enabled when paused and disabled when resumed.
|
||||
/// - Pressing Escape toggles pause while the manager exists.
|
||||
/// Central gameplay pause manager.
|
||||
/// - ESC / top-right Pause button can pause only in gameplay scene.
|
||||
/// - Continue: hide pause panel, replay 3-2-1-Go, then resume chart + music.
|
||||
/// - Replay: reload current gameplay scene (with current selected song/difficulty if available).
|
||||
/// - Exit: return to selectYourSongFirst.
|
||||
/// </summary>
|
||||
public class PauseManager : MonoBehaviour
|
||||
{
|
||||
public static PauseManager Instance { get; private set; }
|
||||
|
||||
[Header("Overlay")]
|
||||
public GameObject overlayRoot; // object to enable/disable on pause
|
||||
public GameObject overlayRoot;
|
||||
[SerializeField] private float overlayFadeDuration = 0.2f;
|
||||
[SerializeField] private bool preferPausePrefabOverWhiteScreen = true;
|
||||
[SerializeField] private string legacyWhiteScreenRootName = "pauseWhiteScreen";
|
||||
|
||||
[Header("Gameplay Scope")]
|
||||
[SerializeField] private bool onlyInGameplayScene = true;
|
||||
[SerializeField] private string gameplaySceneName = "gamePlay_gamePlay";
|
||||
[SerializeField] private bool requirePlaybackStarted = true;
|
||||
|
||||
[Header("Buttons")]
|
||||
[SerializeField] private string pauseButtonScenePath = "artworks/NEW UI/zhuangshi (3)/Pause";
|
||||
[SerializeField] private Button pauseTriggerButton;
|
||||
[SerializeField] private Button continueButton;
|
||||
[SerializeField] private Button replayButton;
|
||||
[SerializeField] private Button exitButton;
|
||||
[SerializeField] private Button settingsButton;
|
||||
|
||||
[Header("Pause Entry Animation")]
|
||||
[SerializeField] private bool playPauseEntryAnimation = true;
|
||||
[SerializeField] private float pauseItemEnterDuration = 0.18f;
|
||||
[SerializeField] private float pauseItemEnterStagger = 0.016f;
|
||||
|
||||
public bool IsPaused { get; private set; } = false;
|
||||
|
||||
// ������ͣ״̬�ı��¼�
|
||||
public event Action<bool> OnPauseStateChanged;
|
||||
|
||||
private CanvasGroup overlayCanvasGroup;
|
||||
private RectTransform overlayPanelRoot;
|
||||
private CanvasGroup overlayPanelCanvasGroup;
|
||||
private Vector3 panelShownScale = Vector3.zero;
|
||||
private static readonly Vector3 PanelHiddenScale = Vector3.zero;
|
||||
private Coroutine overlayFadeCoroutine;
|
||||
private Coroutine continueCoroutine;
|
||||
private bool buttonsBound = false;
|
||||
private float nextBindRetryTime = 0f;
|
||||
|
||||
private const string ExitSceneName = "selectYourSongFirst";
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance == null) Instance = this;
|
||||
else Destroy(gameObject);
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (overlayRoot != null)
|
||||
overlayRoot.SetActive(false);
|
||||
ResolveOverlayRootForPausePrefab();
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
SetOverlayVisibleImmediate(false);
|
||||
TryBindButtons(force: true);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Delete = immediate quit (stop play in editor or quit app)
|
||||
if (!buttonsBound && Time.unscaledTime >= nextBindRetryTime)
|
||||
{
|
||||
TryBindButtons(force: false);
|
||||
}
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Delete))
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
@@ -50,54 +95,599 @@ public class PauseManager : MonoBehaviour
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Escape))
|
||||
{
|
||||
TogglePause();
|
||||
// User requested ESC as pause trigger in gameplay only.
|
||||
if (CanPauseFromInput() && !IsPaused)
|
||||
{
|
||||
Pause(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ��������ͣ״̬�Ұ��� Backspace ʱ����������
|
||||
// Keep existing Backspace quick-exit while paused.
|
||||
if (IsPaused && Input.GetKeyDown(KeyCode.Backspace))
|
||||
{
|
||||
// �ָ�ʱ�����������¼���Ȼ�����������
|
||||
Pause(false);
|
||||
// ȷ��������������Ŀ�е�������ƥ��
|
||||
StartCoroutine(LoadSceneAsync("Main_main"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause or resume the game. Call Pause(true) to pause.
|
||||
/// This implementation enables/disables overlayRoot and sets Time.timeScale.
|
||||
/// </summary>
|
||||
public void Pause(bool pause)
|
||||
{
|
||||
if (pause)
|
||||
{
|
||||
if (IsPaused) return;
|
||||
if (overlayRoot != null) overlayRoot.SetActive(true);
|
||||
Time.timeScale = 0f;
|
||||
IsPaused = true;
|
||||
Time.timeScale = 0f;
|
||||
OnPauseStateChanged?.Invoke(true);
|
||||
// Startup flows call Pause(true) before real gameplay starts.
|
||||
// In that phase we keep time paused but do not show pause UI.
|
||||
bool allowOverlay = CanPauseFromInput();
|
||||
if (allowOverlay)
|
||||
ShowOverlayAnimated(true);
|
||||
else
|
||||
SetOverlayVisibleImmediate(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (overlayRoot != null) overlayRoot.SetActive(false);
|
||||
Time.timeScale = 1f;
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
OnPauseStateChanged?.Invoke(false);
|
||||
ShowOverlayAnimated(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void TogglePause()
|
||||
{
|
||||
Pause(!IsPaused);
|
||||
if (!CanPauseFromInput()) return;
|
||||
if (!IsPaused) Pause(true);
|
||||
}
|
||||
|
||||
public void ContinueFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null) return;
|
||||
continueCoroutine = StartCoroutine(ContinueFromPauseCoroutine());
|
||||
}
|
||||
|
||||
public void ReplayFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null)
|
||||
{
|
||||
StopCoroutine(continueCoroutine);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
StartCoroutine(ReplayFromPauseCoroutine());
|
||||
}
|
||||
|
||||
public void ExitFromPause()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (continueCoroutine != null)
|
||||
{
|
||||
StopCoroutine(continueCoroutine);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
StartCoroutine(ExitFromPauseCoroutine());
|
||||
}
|
||||
|
||||
private bool IsGameplaySceneActive()
|
||||
{
|
||||
string sceneName = SceneManager.GetActiveScene().name ?? string.Empty;
|
||||
if (string.Equals(sceneName, gameplaySceneName, StringComparison.OrdinalIgnoreCase)) return true;
|
||||
if (sceneName.IndexOf("gameplay", StringComparison.OrdinalIgnoreCase) >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CanPauseFromInput()
|
||||
{
|
||||
if (onlyInGameplayScene && !IsGameplaySceneActive()) return false;
|
||||
if (!requirePlaybackStarted) return true;
|
||||
|
||||
var gm = FindAnyObjectByType<GameManager>();
|
||||
if (gm == null) return false;
|
||||
return gm.PlaybackStarted;
|
||||
}
|
||||
|
||||
private void EnsureOverlayCanvasGroup()
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
overlayCanvasGroup = overlayRoot.GetComponent<CanvasGroup>();
|
||||
if (overlayCanvasGroup == null)
|
||||
overlayCanvasGroup = overlayRoot.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
private void ResolveOverlayRootForPausePrefab()
|
||||
{
|
||||
if (!preferPausePrefabOverWhiteScreen) return;
|
||||
// Prefer the real pause prefab root (contains Continue/Replay/Exit).
|
||||
GameObject pauseRoot = FindPauseMenuRootInScene();
|
||||
if (pauseRoot != null)
|
||||
{
|
||||
overlayRoot = pauseRoot;
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlayRoot == null) return;
|
||||
|
||||
// Legacy setup fallback: PauseManager points to pauseWhiteScreen.
|
||||
if (!string.Equals(overlayRoot.name, legacyWhiteScreenRootName, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
GameObject candidate = FindPauseOverlayCandidate(overlayRoot.transform);
|
||||
if (candidate == null)
|
||||
candidate = FindPauseOverlayCandidate(null);
|
||||
if (candidate != null && candidate != overlayRoot)
|
||||
overlayRoot = candidate;
|
||||
}
|
||||
|
||||
private GameObject FindPauseOverlayCandidate(Transform searchRoot)
|
||||
{
|
||||
Canvas[] canvases = searchRoot != null
|
||||
? searchRoot.GetComponentsInChildren<Canvas>(true)
|
||||
: FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
Canvas canvas = canvases[i];
|
||||
if (canvas == null) continue;
|
||||
|
||||
GameObject go = canvas.gameObject;
|
||||
if (go == null || go == overlayRoot) continue;
|
||||
if (!HasPauseButtons(go)) continue;
|
||||
return go;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GameObject FindPauseMenuRootInScene()
|
||||
{
|
||||
var all = Resources.FindObjectsOfTypeAll<Transform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!t.gameObject.scene.IsValid()) continue;
|
||||
if (!string.Equals(t.name, "pause", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
||||
GameObject go = t.gameObject;
|
||||
if (HasPauseButtons(go))
|
||||
return go;
|
||||
}
|
||||
|
||||
// Fallback: any object that contains all three pause action buttons.
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!t.gameObject.scene.IsValid()) continue;
|
||||
GameObject go = t.gameObject;
|
||||
if (HasPauseButtons(go))
|
||||
return go;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool HasPauseButtons(GameObject root)
|
||||
{
|
||||
if (root == null) return false;
|
||||
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
||||
bool hasContinue = false;
|
||||
bool hasReplay = false;
|
||||
bool hasExit = false;
|
||||
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
Button b = buttons[i];
|
||||
if (b == null) continue;
|
||||
string n = b.gameObject.name;
|
||||
if (string.Equals(n, "Continue", StringComparison.OrdinalIgnoreCase)) hasContinue = true;
|
||||
else if (string.Equals(n, "Replay", StringComparison.OrdinalIgnoreCase)) hasReplay = true;
|
||||
else if (string.Equals(n, "Exit", StringComparison.OrdinalIgnoreCase)) hasExit = true;
|
||||
}
|
||||
|
||||
return hasContinue && hasReplay && hasExit;
|
||||
}
|
||||
|
||||
private void EnsureOverlayPanelRoot()
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
|
||||
if (overlayPanelRoot == null)
|
||||
{
|
||||
var canvases = overlayRoot.GetComponentsInChildren<Canvas>(true);
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
var canvas = canvases[i];
|
||||
if (canvas == null) continue;
|
||||
if (canvas.gameObject == overlayRoot) continue;
|
||||
|
||||
overlayPanelRoot = canvas.GetComponent<RectTransform>();
|
||||
if (overlayPanelRoot != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (overlayPanelRoot == null)
|
||||
{
|
||||
var rts = overlayRoot.GetComponentsInChildren<RectTransform>(true);
|
||||
for (int i = 0; i < rts.Length; i++)
|
||||
{
|
||||
var rt = rts[i];
|
||||
if (rt == null) continue;
|
||||
if (rt.gameObject == overlayRoot) continue;
|
||||
|
||||
overlayPanelRoot = rt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (overlayPanelRoot == null) return;
|
||||
|
||||
if (overlayPanelCanvasGroup == null)
|
||||
{
|
||||
overlayPanelCanvasGroup = overlayPanelRoot.GetComponent<CanvasGroup>();
|
||||
if (overlayPanelCanvasGroup == null)
|
||||
overlayPanelCanvasGroup = overlayPanelRoot.gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
if (IsScaleNearlyZero(panelShownScale))
|
||||
{
|
||||
Vector3 current = overlayPanelRoot.localScale;
|
||||
panelShownScale = IsScaleNearlyZero(current) ? Vector3.one : current;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsScaleNearlyZero(Vector3 scale)
|
||||
{
|
||||
return Mathf.Abs(scale.x) <= 0.0001f
|
||||
&& Mathf.Abs(scale.y) <= 0.0001f
|
||||
&& Mathf.Abs(scale.z) <= 0.0001f;
|
||||
}
|
||||
|
||||
private void SetOverlayVisibleImmediate(bool visible)
|
||||
{
|
||||
if (overlayRoot == null) return;
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
|
||||
overlayRoot.SetActive(visible);
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.alpha = visible ? 1f : 0f;
|
||||
overlayCanvasGroup.interactable = visible;
|
||||
overlayCanvasGroup.blocksRaycasts = visible;
|
||||
}
|
||||
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.alpha = visible ? 1f : 0f;
|
||||
overlayPanelCanvasGroup.interactable = visible;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = visible;
|
||||
}
|
||||
|
||||
if (overlayPanelRoot != null)
|
||||
{
|
||||
overlayPanelRoot.localScale = visible ? panelShownScale : PanelHiddenScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowOverlayAnimated(bool show)
|
||||
{
|
||||
if (overlayRoot == null)
|
||||
return;
|
||||
|
||||
EnsureOverlayCanvasGroup();
|
||||
if (overlayFadeCoroutine != null)
|
||||
{
|
||||
StopCoroutine(overlayFadeCoroutine);
|
||||
overlayFadeCoroutine = null;
|
||||
}
|
||||
overlayFadeCoroutine = StartCoroutine(FadeOverlayCoroutine(show));
|
||||
}
|
||||
|
||||
private IEnumerator FadeOverlayCoroutine(bool show)
|
||||
{
|
||||
if (overlayRoot == null)
|
||||
yield break;
|
||||
|
||||
EnsureOverlayCanvasGroup();
|
||||
EnsureOverlayPanelRoot();
|
||||
|
||||
if (show && !overlayRoot.activeSelf)
|
||||
overlayRoot.SetActive(true);
|
||||
// Pause entry animation helper may be unavailable in some compile targets.
|
||||
// Keep pause functionality independent from that optional visual effect.
|
||||
|
||||
float startA = overlayCanvasGroup != null ? overlayCanvasGroup.alpha : (show ? 0f : 1f);
|
||||
float startPanelA = overlayPanelCanvasGroup != null ? overlayPanelCanvasGroup.alpha : startA;
|
||||
float targetA = show ? 1f : 0f;
|
||||
Vector3 startScale = overlayPanelRoot != null ? overlayPanelRoot.localScale : panelShownScale;
|
||||
if (show && IsScaleNearlyZero(startScale))
|
||||
startScale = PanelHiddenScale;
|
||||
Vector3 targetScale = show ? panelShownScale : PanelHiddenScale;
|
||||
|
||||
float duration = Mathf.Max(0.01f, overlayFadeDuration);
|
||||
float t = 0f;
|
||||
|
||||
if (show)
|
||||
{
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.interactable = true;
|
||||
overlayCanvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.interactable = true;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (overlayCanvasGroup != null)
|
||||
{
|
||||
overlayCanvasGroup.interactable = false;
|
||||
overlayCanvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
{
|
||||
overlayPanelCanvasGroup.interactable = false;
|
||||
overlayPanelCanvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (t < duration)
|
||||
{
|
||||
t += Time.unscaledDeltaTime;
|
||||
float k = Mathf.Clamp01(t / duration);
|
||||
if (overlayCanvasGroup != null)
|
||||
overlayCanvasGroup.alpha = Mathf.Lerp(startA, targetA, k);
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
overlayPanelCanvasGroup.alpha = Mathf.Lerp(startPanelA, targetA, k);
|
||||
if (overlayPanelRoot != null)
|
||||
overlayPanelRoot.localScale = Vector3.Lerp(startScale, targetScale, k);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (overlayCanvasGroup != null)
|
||||
overlayCanvasGroup.alpha = targetA;
|
||||
if (overlayPanelCanvasGroup != null)
|
||||
overlayPanelCanvasGroup.alpha = targetA;
|
||||
if (overlayPanelRoot != null)
|
||||
overlayPanelRoot.localScale = targetScale;
|
||||
|
||||
if (!show)
|
||||
overlayRoot.SetActive(false);
|
||||
|
||||
overlayFadeCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator ContinueFromPauseCoroutine()
|
||||
{
|
||||
// Start hiding panel, but do not wait before countdown starts.
|
||||
ShowOverlayAnimated(false);
|
||||
|
||||
// Replay 3-2-1-Go immediately on continue click.
|
||||
var gm = FindAnyObjectByType<GameManager>();
|
||||
var ready = gm != null ? gm.readyLetsGo : FindAnyObjectByType<readyLetsGo>();
|
||||
float originalWaitingDuration = 0f;
|
||||
bool waitingDurationOverridden = false;
|
||||
if (ready != null)
|
||||
{
|
||||
// Remove extra idle delay before countdown visuals in continue flow.
|
||||
originalWaitingDuration = ready.waitingDuration;
|
||||
ready.waitingDuration = 0f;
|
||||
waitingDurationOverridden = true;
|
||||
|
||||
try { ready.ResetPlayState(); } catch { }
|
||||
try { ready.PlaySequence(); } catch { }
|
||||
|
||||
int imageCount = ready._321goImages != null ? ready._321goImages.Count : 0;
|
||||
float sequenceDuration = 0.25f
|
||||
+ 0f
|
||||
+ Mathf.Max(0f, imageCount * ready.oneImageDuration)
|
||||
+ 0.15f;
|
||||
if (sequenceDuration > 0f)
|
||||
yield return new WaitForSecondsRealtime(sequenceDuration);
|
||||
}
|
||||
|
||||
if (waitingDurationOverridden && ready != null)
|
||||
{
|
||||
ready.waitingDuration = originalWaitingDuration;
|
||||
}
|
||||
|
||||
// Resume chart + music.
|
||||
Pause(false);
|
||||
continueCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator ReplayFromPauseCoroutine()
|
||||
{
|
||||
SetOverlayVisibleImmediate(false);
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
try { OnPauseStateChanged?.Invoke(false); } catch { }
|
||||
|
||||
var bmm = FindAnyObjectByType<BeatmapManager>();
|
||||
if (bmm != null && bmm.assignedSongData != null)
|
||||
{
|
||||
int diff = bmm.assignedDifficulty;
|
||||
if (diff < 0) diff = 0;
|
||||
BeatmapManager.SetPendingSong(bmm.assignedSongData, diff);
|
||||
}
|
||||
|
||||
string current = SceneManager.GetActiveScene().name;
|
||||
yield return LoadSceneAsync(current);
|
||||
}
|
||||
|
||||
private IEnumerator ExitFromPauseCoroutine()
|
||||
{
|
||||
SetOverlayVisibleImmediate(false);
|
||||
IsPaused = false;
|
||||
Time.timeScale = 1f;
|
||||
try { OnPauseStateChanged?.Invoke(false); } catch { }
|
||||
|
||||
yield return LoadSceneAsync(ExitSceneName);
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneAsync(string sceneName)
|
||||
{
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private void TryBindButtons(bool force)
|
||||
{
|
||||
if (buttonsBound && !force) return;
|
||||
|
||||
if (onlyInGameplayScene && !IsGameplaySceneActive() && !force)
|
||||
{
|
||||
nextBindRetryTime = Time.unscaledTime + 1f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pauseTriggerButton == null)
|
||||
{
|
||||
var pauseGO = GameObject.Find(pauseButtonScenePath);
|
||||
if (pauseGO == null)
|
||||
pauseGO = FindByNameInScene("Pause");
|
||||
if (pauseGO != null)
|
||||
pauseTriggerButton = pauseGO.GetComponent<Button>();
|
||||
}
|
||||
|
||||
if (overlayRoot != null)
|
||||
{
|
||||
if (continueButton == null) continueButton = FindButtonInOverlay("Continue");
|
||||
if (replayButton == null) replayButton = FindButtonInOverlay("Replay");
|
||||
if (exitButton == null) exitButton = FindButtonInOverlay("Exit");
|
||||
if (settingsButton == null) settingsButton = FindButtonInOverlay("settings");
|
||||
}
|
||||
|
||||
if (pauseTriggerButton != null)
|
||||
{
|
||||
pauseTriggerButton.onClick.RemoveListener(OnPauseButtonClicked);
|
||||
pauseTriggerButton.onClick.AddListener(OnPauseButtonClicked);
|
||||
}
|
||||
|
||||
if (continueButton != null)
|
||||
{
|
||||
continueButton.onClick.RemoveListener(ContinueFromPause);
|
||||
continueButton.onClick.AddListener(ContinueFromPause);
|
||||
}
|
||||
|
||||
if (replayButton != null)
|
||||
{
|
||||
replayButton.onClick.RemoveListener(ReplayFromPause);
|
||||
replayButton.onClick.AddListener(ReplayFromPause);
|
||||
}
|
||||
|
||||
if (exitButton != null)
|
||||
{
|
||||
exitButton.onClick.RemoveListener(ExitFromPause);
|
||||
exitButton.onClick.AddListener(ExitFromPause);
|
||||
}
|
||||
|
||||
if (settingsButton != null)
|
||||
{
|
||||
settingsButton.onClick.RemoveListener(OnSettingsButtonClicked);
|
||||
settingsButton.onClick.AddListener(OnSettingsButtonClicked);
|
||||
}
|
||||
|
||||
buttonsBound = pauseTriggerButton != null && continueButton != null && replayButton != null && exitButton != null;
|
||||
nextBindRetryTime = Time.unscaledTime + (buttonsBound ? 9999f : 1f);
|
||||
}
|
||||
|
||||
private void OnPauseButtonClicked()
|
||||
{
|
||||
if (!CanPauseFromInput()) return;
|
||||
if (!IsPaused) Pause(true);
|
||||
}
|
||||
|
||||
private void OnSettingsButtonClicked()
|
||||
{
|
||||
if (!IsPaused) return;
|
||||
if (TryOpenExistingSettingsPanel()) return;
|
||||
|
||||
var topController = FindAnyObjectByType<btmandtopController>();
|
||||
if (topController != null)
|
||||
{
|
||||
topController.SendMessage("OnSettingsNavClicked", SendMessageOptions.DontRequireReceiver);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[PauseManager] Settings button clicked, but no settings panel source was found.");
|
||||
}
|
||||
|
||||
private bool TryOpenExistingSettingsPanel()
|
||||
{
|
||||
var settingsPanels = Resources.FindObjectsOfTypeAll<ui_Panel_Setting>();
|
||||
for (int i = 0; i < settingsPanels.Length; i++)
|
||||
{
|
||||
ui_Panel_Setting panel = settingsPanels[i];
|
||||
if (panel == null) continue;
|
||||
GameObject go = panel.gameObject;
|
||||
if (go == null || !go.scene.IsValid()) continue;
|
||||
|
||||
go.SetActive(true);
|
||||
go.transform.SetAsLastSibling();
|
||||
|
||||
CanvasGroup cg = go.GetComponent<CanvasGroup>();
|
||||
if (cg != null)
|
||||
{
|
||||
cg.interactable = true;
|
||||
cg.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
UI_SettingsPanelEnterAnim enterAnim = go.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (enterAnim != null) enterAnim.Play();
|
||||
return true;
|
||||
}
|
||||
|
||||
GameObject byName = FindByNameInScene("ui_Panel_Setting");
|
||||
if (byName != null)
|
||||
{
|
||||
byName.SetActive(true);
|
||||
byName.transform.SetAsLastSibling();
|
||||
UI_SettingsPanelEnterAnim enterAnim = byName.GetComponent<UI_SettingsPanelEnterAnim>();
|
||||
if (enterAnim != null) enterAnim.Play();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Button FindButtonInOverlay(string buttonName)
|
||||
{
|
||||
if (overlayRoot == null || string.IsNullOrEmpty(buttonName)) return null;
|
||||
|
||||
var buttons = overlayRoot.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
var b = buttons[i];
|
||||
if (b == null) continue;
|
||||
if (string.Equals(b.gameObject.name, buttonName, StringComparison.OrdinalIgnoreCase))
|
||||
return b;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private GameObject FindByNameInScene(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
var all = Resources.FindObjectsOfTypeAll<Transform>();
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
var t = all[i];
|
||||
if (t == null) continue;
|
||||
if (!string.Equals(t.name, name, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (t.gameObject.scene.IsValid())
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public static class UI_OrderedEntryAnimator
|
||||
{
|
||||
public static Sequence Play(
|
||||
Transform root,
|
||||
float itemDuration,
|
||||
float itemStagger,
|
||||
Vector2 fromOffset,
|
||||
bool useUnscaledTime,
|
||||
Predicate<RectTransform> includePredicate = null)
|
||||
{
|
||||
if (root == null) return null;
|
||||
|
||||
List<RectTransform> targets = CollectTargets(root, includePredicate);
|
||||
if (targets.Count == 0) return null;
|
||||
|
||||
targets.Sort(CompareByTopThenLeft);
|
||||
|
||||
float duration = Mathf.Max(0.01f, itemDuration);
|
||||
float stagger = Mathf.Max(0f, itemStagger);
|
||||
Sequence sequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
|
||||
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
RectTransform rt = targets[i];
|
||||
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
|
||||
|
||||
CanvasGroup group = rt.GetComponent<CanvasGroup>();
|
||||
if (group == null) group = rt.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
rt.DOKill();
|
||||
group.DOKill();
|
||||
|
||||
Vector2 basePos = rt.anchoredPosition;
|
||||
float baseAlpha = group.alpha <= 0f ? 1f : group.alpha;
|
||||
|
||||
rt.anchoredPosition = basePos + fromOffset;
|
||||
group.alpha = 0f;
|
||||
|
||||
float startAt = i * stagger;
|
||||
sequence.Insert(startAt, rt.DOAnchorPos(basePos, duration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
|
||||
sequence.Insert(startAt, group.DOFade(baseAlpha, duration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public static Sequence PlayKeyDownFlash(
|
||||
Transform keyDownRoot,
|
||||
bool useUnscaledTime,
|
||||
float fromYOffset = 36f,
|
||||
float itemStagger = 0.03f)
|
||||
{
|
||||
if (keyDownRoot == null) return null;
|
||||
|
||||
List<RectTransform> targets = CollectKeyDownRects(keyDownRoot);
|
||||
if (targets.Count == 0) return null;
|
||||
|
||||
targets.Sort(CompareByTopThenLeft);
|
||||
Sequence sequence = DOTween.Sequence().SetUpdate(useUnscaledTime);
|
||||
|
||||
float moveDuration = 0.1f;
|
||||
float stagger = Mathf.Max(0f, itemStagger);
|
||||
float offsetY = Mathf.Abs(fromYOffset);
|
||||
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
RectTransform rt = targets[i];
|
||||
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
|
||||
|
||||
CanvasGroup group = rt.GetComponent<CanvasGroup>();
|
||||
if (group == null) group = rt.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
rt.DOKill();
|
||||
group.DOKill();
|
||||
|
||||
Vector2 basePos = rt.anchoredPosition;
|
||||
rt.anchoredPosition = basePos - new Vector2(0f, offsetY);
|
||||
group.alpha = 0f;
|
||||
|
||||
float startAt = i * stagger;
|
||||
sequence.Insert(startAt, rt.DOAnchorPos(basePos, moveDuration).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
|
||||
sequence.Insert(startAt, group.DOFade(1f, 0.028f).SetEase(Ease.Linear).SetUpdate(useUnscaledTime));
|
||||
sequence.Insert(startAt + 0.028f, group.DOFade(0.2f, 0.026f).SetEase(Ease.Linear).SetUpdate(useUnscaledTime));
|
||||
sequence.Insert(startAt + 0.054f, group.DOFade(1f, 0.04f).SetEase(Ease.OutCubic).SetUpdate(useUnscaledTime));
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public static bool IsNamedOrChildOf(Transform target, string name)
|
||||
{
|
||||
if (target == null || string.IsNullOrEmpty(name)) return false;
|
||||
Transform it = target;
|
||||
while (it != null)
|
||||
{
|
||||
if (string.Equals(it.name, name, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
it = it.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<RectTransform> CollectTargets(Transform root, Predicate<RectTransform> includePredicate)
|
||||
{
|
||||
List<RectTransform> list = new List<RectTransform>(128);
|
||||
HashSet<RectTransform> seen = new HashSet<RectTransform>();
|
||||
Stack<Transform> stack = new Stack<Transform>();
|
||||
stack.Push(root);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
Transform parent = stack.Pop();
|
||||
if (parent == null) continue;
|
||||
|
||||
for (int i = 0; i < parent.childCount; i++)
|
||||
{
|
||||
Transform child = parent.GetChild(i);
|
||||
if (child == null) continue;
|
||||
stack.Push(child);
|
||||
|
||||
RectTransform rt = child as RectTransform;
|
||||
if (rt == null || !child.gameObject.activeInHierarchy) continue;
|
||||
if (includePredicate != null && !includePredicate(rt)) continue;
|
||||
if (!IsPanelLike(child)) continue;
|
||||
if (!seen.Add(rt)) continue;
|
||||
|
||||
list.Add(rt);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<RectTransform> CollectKeyDownRects(Transform root)
|
||||
{
|
||||
List<RectTransform> list = new List<RectTransform>(16);
|
||||
RectTransform[] all = root.GetComponentsInChildren<RectTransform>(true);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
RectTransform rt = all[i];
|
||||
if (rt == null || !rt.gameObject.activeInHierarchy) continue;
|
||||
if (rt == root) continue;
|
||||
|
||||
string n = rt.name ?? string.Empty;
|
||||
if (n.IndexOf("sdw 3", StringComparison.OrdinalIgnoreCase) < 0) continue;
|
||||
list.Add(rt);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static bool IsPanelLike(Transform tr)
|
||||
{
|
||||
if (tr == null) return false;
|
||||
if (tr.GetComponent<Selectable>() != null) return true;
|
||||
if (tr.GetComponent<Graphic>() != null) return true;
|
||||
if (tr.GetComponent<LayoutGroup>() != null) return true;
|
||||
if (tr.GetComponent<CanvasGroup>() != null) return true;
|
||||
return tr.childCount > 0;
|
||||
}
|
||||
|
||||
private static int CompareByTopThenLeft(RectTransform a, RectTransform b)
|
||||
{
|
||||
if (a == null && b == null) return 0;
|
||||
if (a == null) return 1;
|
||||
if (b == null) return -1;
|
||||
|
||||
Vector3 pa = a.position;
|
||||
Vector3 pb = b.position;
|
||||
|
||||
int xOrder = pa.x.CompareTo(pb.x); // left -> right
|
||||
if (xOrder != 0) return xOrder;
|
||||
return -pa.y.CompareTo(pb.y); // top -> bottom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 893b9011544d6c14ab8eee7fc3b45b3b
|
||||
@@ -15,7 +15,9 @@ public class UI_Show_Anim : MonoBehaviour
|
||||
{
|
||||
canvasGroup.alpha = 0;
|
||||
float a = 0;
|
||||
DOTween.To(() => a, (f) => { a = f; canvasGroup.alpha = f; }, 1, animTime_Alpha).SetUpdate(true);
|
||||
DOTween.To(() => a, (f) => { a = f; canvasGroup.alpha = f; }, 1, animTime_Alpha)
|
||||
.SetUpdate(true)
|
||||
.SetTarget(canvasGroup);
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
@@ -25,11 +27,20 @@ public class UI_Show_Anim : MonoBehaviour
|
||||
if (gameObject.Try_Get_Component(out CanvasGroup canvasGroup))
|
||||
{
|
||||
float a = 1;
|
||||
DOTween.To(() => a, (f) => { a = f; canvasGroup.alpha = f; }, 0, animTime_Alpha).SetUpdate(true);
|
||||
DOTween.To(() => a, (f) => { a = f; canvasGroup.alpha = f; }, 0, animTime_Alpha)
|
||||
.SetUpdate(true)
|
||||
.SetTarget(canvasGroup);
|
||||
}
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
DOTween.KillAll(transform);
|
||||
// Only kill tweens that belong to this UI element.
|
||||
// Passing a Transform into DOTween.KillAll(...) is dangerous in Unity because Transform has an implicit bool
|
||||
// conversion, which ends up calling KillAll(true) and wipes tweens globally.
|
||||
transform.DOKill();
|
||||
if (gameObject.Try_Get_Component(out CanvasGroup canvasGroup))
|
||||
{
|
||||
canvasGroup.DOKill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class UI_UnimplementedFeatureBlocker : MonoBehaviour
|
||||
{
|
||||
public static bool RuntimeEnabled = false;
|
||||
|
||||
[SerializeField] private string[] blockedButtonNames =
|
||||
{
|
||||
"Button_STORY",
|
||||
"Button_IDOL",
|
||||
"Button_NOTEBOOK",
|
||||
"launchEzGame",
|
||||
"Button_CHARACTER_SET",
|
||||
"Button_Market",
|
||||
"Button_Personal_information",
|
||||
"Button_view_level",
|
||||
"Button_Mail",
|
||||
"Button_notice"
|
||||
};
|
||||
|
||||
private Coroutine bindRoutine;
|
||||
private Coroutine continuousBindRoutine;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!RuntimeEnabled)
|
||||
{
|
||||
CleanupOverlaysInLoadedScenes();
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
StartBind(SceneManager.GetActiveScene());
|
||||
if (continuousBindRoutine == null)
|
||||
continuousBindRoutine = StartCoroutine(ContinuousBindLoop());
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
if (bindRoutine != null)
|
||||
{
|
||||
StopCoroutine(bindRoutine);
|
||||
bindRoutine = null;
|
||||
}
|
||||
if (continuousBindRoutine != null)
|
||||
{
|
||||
StopCoroutine(continuousBindRoutine);
|
||||
continuousBindRoutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
StartBind(scene);
|
||||
}
|
||||
|
||||
private void StartBind(Scene scene)
|
||||
{
|
||||
if (!scene.IsValid() || !scene.isLoaded)
|
||||
return;
|
||||
|
||||
if (bindRoutine != null)
|
||||
{
|
||||
StopCoroutine(bindRoutine);
|
||||
bindRoutine = null;
|
||||
}
|
||||
bindRoutine = StartCoroutine(BindRoutine(scene));
|
||||
}
|
||||
|
||||
private IEnumerator BindRoutine(Scene scene)
|
||||
{
|
||||
// Repeat binding multiple times so we override listeners added in Start/OnEnable by scene scripts.
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ApplyBlockers();
|
||||
yield return new WaitForSecondsRealtime(0.12f);
|
||||
}
|
||||
bindRoutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator ContinuousBindLoop()
|
||||
{
|
||||
while (enabled)
|
||||
{
|
||||
ApplyBlockers();
|
||||
yield return new WaitForSecondsRealtime(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyBlockers()
|
||||
{
|
||||
if (blockedButtonNames == null || blockedButtonNames.Length == 0)
|
||||
return;
|
||||
|
||||
HashSet<Button> candidates = new HashSet<Button>();
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int j = 0; j < all.Length; j++)
|
||||
{
|
||||
Transform t = all[j];
|
||||
if (t == null)
|
||||
continue;
|
||||
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded)
|
||||
continue;
|
||||
|
||||
if (!IsBlockedName(t.name))
|
||||
continue;
|
||||
|
||||
CollectNearbyButtons(t, candidates);
|
||||
}
|
||||
|
||||
foreach (Button btn in candidates)
|
||||
{
|
||||
if (btn == null)
|
||||
continue;
|
||||
|
||||
btn.onClick.RemoveAllListeners();
|
||||
btn.onClick.AddListener(OnBlockedButtonClick);
|
||||
EnsureOverlayClickBlocker(btn);
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectNearbyButtons(Transform target, HashSet<Button> set)
|
||||
{
|
||||
if (target == null || set == null)
|
||||
return;
|
||||
|
||||
Button self = target.GetComponent<Button>();
|
||||
if (self != null)
|
||||
set.Add(self);
|
||||
|
||||
Button parent = target.GetComponentInParent<Button>(true);
|
||||
if (parent != null)
|
||||
set.Add(parent);
|
||||
|
||||
Button[] children = target.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
{
|
||||
if (children[i] != null)
|
||||
set.Add(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsBlockedName(string objectName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(objectName) || blockedButtonNames == null)
|
||||
return false;
|
||||
|
||||
string current = NormalizeName(objectName);
|
||||
for (int i = 0; i < blockedButtonNames.Length; i++)
|
||||
{
|
||||
string target = blockedButtonNames[i];
|
||||
if (string.IsNullOrEmpty(target))
|
||||
continue;
|
||||
|
||||
string normalizedTarget = NormalizeName(target);
|
||||
if (current == normalizedTarget)
|
||||
return true;
|
||||
if (current.Contains(normalizedTarget) || normalizedTarget.Contains(current))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string NormalizeName(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return string.Empty;
|
||||
|
||||
return value
|
||||
.Replace(" ", "")
|
||||
.Replace("_", "")
|
||||
.Replace("-", "")
|
||||
.ToLowerInvariant();
|
||||
}
|
||||
|
||||
private void EnsureOverlayClickBlocker(Button sourceButton)
|
||||
{
|
||||
if (sourceButton == null) return;
|
||||
|
||||
const string overlayName = "__BlockedFeatureOverlay";
|
||||
|
||||
Transform host = sourceButton.targetGraphic != null
|
||||
? sourceButton.targetGraphic.transform
|
||||
: sourceButton.transform;
|
||||
if (host == null)
|
||||
host = sourceButton.transform;
|
||||
|
||||
Transform existing = host.Find(overlayName);
|
||||
GameObject overlayGo;
|
||||
if (existing == null)
|
||||
{
|
||||
overlayGo = new GameObject(overlayName, typeof(RectTransform), typeof(Image), typeof(Button));
|
||||
overlayGo.transform.SetParent(host, false);
|
||||
RectTransform rt = overlayGo.GetComponent<RectTransform>();
|
||||
rt.anchorMin = Vector2.zero;
|
||||
rt.anchorMax = Vector2.one;
|
||||
rt.offsetMin = Vector2.zero;
|
||||
rt.offsetMax = Vector2.zero;
|
||||
rt.localScale = Vector3.one;
|
||||
|
||||
Image img = overlayGo.GetComponent<Image>();
|
||||
img.color = new Color(1f, 1f, 1f, 0f);
|
||||
img.raycastTarget = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayGo = existing.gameObject;
|
||||
}
|
||||
|
||||
overlayGo.SetActive(true);
|
||||
overlayGo.transform.SetAsLastSibling();
|
||||
|
||||
Button overlayBtn = overlayGo.GetComponent<Button>();
|
||||
if (overlayBtn != null)
|
||||
{
|
||||
overlayBtn.transition = Selectable.Transition.None;
|
||||
overlayBtn.onClick.RemoveAllListeners();
|
||||
overlayBtn.onClick.AddListener(OnBlockedButtonClick);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBlockedButtonClick()
|
||||
{
|
||||
if (!RuntimeEnabled)
|
||||
return;
|
||||
UnimplementedFeaturePrompt.ShowPrompt();
|
||||
}
|
||||
|
||||
private static void CleanupOverlaysInLoadedScenes()
|
||||
{
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null)
|
||||
continue;
|
||||
if (!t.gameObject.scene.IsValid() || !t.gameObject.scene.isLoaded)
|
||||
continue;
|
||||
if (!string.Equals(t.name, "__BlockedFeatureOverlay", System.StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
if (Application.isPlaying)
|
||||
UnityEngine.Object.Destroy(t.gameObject);
|
||||
else
|
||||
UnityEngine.Object.DestroyImmediate(t.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class UI_UnimplementedFeatureBlockerBootstrap
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void Init()
|
||||
{
|
||||
if (!UI_UnimplementedFeatureBlocker.RuntimeEnabled)
|
||||
{
|
||||
GameObject old = GameObject.Find("__UnimplementedFeatureBlockerHost");
|
||||
if (old != null)
|
||||
UnityEngine.Object.Destroy(old);
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject host = GameObject.Find("__UnimplementedFeatureBlockerHost");
|
||||
if (host == null)
|
||||
host = new GameObject("__UnimplementedFeatureBlockerHost");
|
||||
UnityEngine.Object.DontDestroyOnLoad(host);
|
||||
|
||||
if (host.GetComponent<UI_UnimplementedFeatureBlocker>() == null)
|
||||
host.AddComponent<UI_UnimplementedFeatureBlocker>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6590632f0e73e14fa145e8027875df2
|
||||
@@ -0,0 +1,485 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class UnimplementedFeaturePrompt : MonoBehaviour
|
||||
{
|
||||
public static bool RuntimeEnabled = false;
|
||||
private static UnimplementedFeaturePrompt instance;
|
||||
|
||||
[Header("Flash")]
|
||||
[SerializeField] private int flashCount = 2;
|
||||
[SerializeField] private float flashOnTime = 0.04f;
|
||||
[SerializeField] private float flashOffTime = 0.03f;
|
||||
|
||||
private GameObject root;
|
||||
private GameObject pressText;
|
||||
private GameObject noChoice;
|
||||
private GameObject choiceLessThanFive;
|
||||
private GameObject image3;
|
||||
private Button continueButton;
|
||||
private Button considerButton;
|
||||
private Button doNotShowAgainButton;
|
||||
private Button okayButton;
|
||||
private Coroutine flashRoutine;
|
||||
|
||||
public static void ShowPrompt()
|
||||
{
|
||||
if (!RuntimeEnabled)
|
||||
return;
|
||||
EnsureInstance();
|
||||
if (instance != null)
|
||||
instance.ShowInternal();
|
||||
}
|
||||
|
||||
private static void EnsureInstance()
|
||||
{
|
||||
if (instance != null)
|
||||
return;
|
||||
|
||||
GameObject host = GameObject.Find("__UnimplementedFeaturePromptHost");
|
||||
if (host == null)
|
||||
{
|
||||
host = new GameObject("__UnimplementedFeaturePromptHost");
|
||||
DontDestroyOnLoad(host);
|
||||
}
|
||||
|
||||
instance = host.GetComponent<UnimplementedFeaturePrompt>();
|
||||
if (instance == null)
|
||||
instance = host.AddComponent<UnimplementedFeaturePrompt>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
// Re-resolve references every scene so we can reuse existing UI if present.
|
||||
root = null;
|
||||
pressText = null;
|
||||
noChoice = null;
|
||||
choiceLessThanFive = null;
|
||||
image3 = null;
|
||||
continueButton = null;
|
||||
considerButton = null;
|
||||
doNotShowAgainButton = null;
|
||||
okayButton = null;
|
||||
}
|
||||
|
||||
private void ShowInternal()
|
||||
{
|
||||
EnsurePromptRoot();
|
||||
if (root == null)
|
||||
{
|
||||
Debug.LogWarning("[UnimplementedFeaturePrompt] Prompt root was not found and fallback creation failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureMinimumPromptElements();
|
||||
BringRootToFront();
|
||||
BindOkayButton();
|
||||
|
||||
root.SetActive(true);
|
||||
CanvasGroup rootGroup = root.GetComponent<CanvasGroup>();
|
||||
if (rootGroup != null)
|
||||
rootGroup.alpha = 1f;
|
||||
|
||||
SetActiveSafe(noChoice, false);
|
||||
SetActiveSafe(choiceLessThanFive, false);
|
||||
SetActiveSafe(image3, false);
|
||||
SetButtonVisible(continueButton, false);
|
||||
SetButtonVisible(considerButton, false);
|
||||
SetButtonVisible(doNotShowAgainButton, false);
|
||||
SetButtonVisible(okayButton, true);
|
||||
SetActiveSafe(pressText, true);
|
||||
|
||||
if (flashRoutine != null)
|
||||
StopCoroutine(flashRoutine);
|
||||
flashRoutine = StartCoroutine(FlashMessage());
|
||||
}
|
||||
|
||||
private IEnumerator FlashMessage()
|
||||
{
|
||||
GameObject target = pressText != null ? pressText : root;
|
||||
if (target == null)
|
||||
yield break;
|
||||
|
||||
CanvasGroup cg = target.GetComponent<CanvasGroup>();
|
||||
if (cg == null)
|
||||
cg = target.AddComponent<CanvasGroup>();
|
||||
|
||||
int count = Mathf.Max(1, flashCount);
|
||||
float onTime = Mathf.Clamp(flashOnTime, 0.01f, 0.05f);
|
||||
float offTime = Mathf.Clamp(flashOffTime, 0.01f, 0.05f);
|
||||
|
||||
cg.alpha = 0f;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
cg.alpha = 1f;
|
||||
yield return new WaitForSecondsRealtime(onTime);
|
||||
if (i < count - 1)
|
||||
{
|
||||
cg.alpha = 0f;
|
||||
yield return new WaitForSecondsRealtime(offTime);
|
||||
}
|
||||
}
|
||||
cg.alpha = 1f;
|
||||
flashRoutine = null;
|
||||
}
|
||||
|
||||
private void OnOkayClicked()
|
||||
{
|
||||
if (flashRoutine != null)
|
||||
{
|
||||
StopCoroutine(flashRoutine);
|
||||
flashRoutine = null;
|
||||
}
|
||||
if (root != null)
|
||||
root.SetActive(false);
|
||||
}
|
||||
|
||||
private void BindOkayButton()
|
||||
{
|
||||
if (okayButton == null)
|
||||
return;
|
||||
|
||||
okayButton.onClick.RemoveListener(OnOkayClicked);
|
||||
okayButton.onClick.AddListener(OnOkayClicked);
|
||||
}
|
||||
|
||||
private void EnsurePromptRoot()
|
||||
{
|
||||
Scene activeScene = SceneManager.GetActiveScene();
|
||||
if (root != null && root.scene.IsValid() && root.scene == activeScene)
|
||||
return;
|
||||
|
||||
root = FindSceneObjectByExactName("\uFF01mustselectyouridol");
|
||||
if (root == null)
|
||||
root = FindSceneObjectByContainsName("mustselectyouridol");
|
||||
|
||||
if (root == null)
|
||||
root = CreateFallbackPrompt();
|
||||
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
pressText = FindChildByName(root.transform, "Press an unimplemented feature");
|
||||
if (pressText == null)
|
||||
pressText = FindChildByName(root.transform, "pressanunimplementedfeature");
|
||||
|
||||
noChoice = FindChildByName(root.transform, "No choice");
|
||||
choiceLessThanFive = FindChildByName(root.transform, "choice < 5");
|
||||
image3 = FindChildByName(root.transform, "Image (3)");
|
||||
continueButton = FindButtonByName(root.transform, "Continue");
|
||||
considerButton = FindButtonByName(root.transform, "Consider");
|
||||
doNotShowAgainButton = FindButtonByName(root.transform, "Do not show again");
|
||||
okayButton = FindButtonByName(root.transform, "okay");
|
||||
if (okayButton == null)
|
||||
okayButton = FindButtonByContainsName(root.transform, "ok");
|
||||
}
|
||||
|
||||
private GameObject CreateFallbackPrompt()
|
||||
{
|
||||
Canvas canvas = FindTopCanvasInActiveScene();
|
||||
if (canvas == null)
|
||||
canvas = CreateFallbackCanvas();
|
||||
if (canvas == null)
|
||||
return null;
|
||||
|
||||
GameObject rootGo = new GameObject("\uFF01mustselectyouridol", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
|
||||
rootGo.transform.SetParent(canvas.transform, false);
|
||||
RectTransform rootRt = rootGo.GetComponent<RectTransform>();
|
||||
rootRt.anchorMin = Vector2.zero;
|
||||
rootRt.anchorMax = Vector2.one;
|
||||
rootRt.offsetMin = Vector2.zero;
|
||||
rootRt.offsetMax = Vector2.zero;
|
||||
Image bg = rootGo.GetComponent<Image>();
|
||||
bg.color = new Color(0f, 0f, 0f, 0.35f);
|
||||
|
||||
GameObject textGo = new GameObject("Press an unimplemented feature", typeof(RectTransform), typeof(Text));
|
||||
textGo.transform.SetParent(rootGo.transform, false);
|
||||
RectTransform textRt = textGo.GetComponent<RectTransform>();
|
||||
textRt.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
textRt.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
textRt.sizeDelta = new Vector2(820f, 80f);
|
||||
textRt.anchoredPosition = new Vector2(0f, 40f);
|
||||
Text t = textGo.GetComponent<Text>();
|
||||
t.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||||
t.fontSize = 40;
|
||||
t.alignment = TextAnchor.MiddleCenter;
|
||||
t.color = Color.white;
|
||||
t.text = "Press an unimplemented feature";
|
||||
|
||||
GameObject okayGo = new GameObject("okay", typeof(RectTransform), typeof(Image), typeof(Button));
|
||||
okayGo.transform.SetParent(rootGo.transform, false);
|
||||
RectTransform okayRt = okayGo.GetComponent<RectTransform>();
|
||||
okayRt.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
okayRt.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
okayRt.sizeDelta = new Vector2(200f, 60f);
|
||||
okayRt.anchoredPosition = new Vector2(0f, -40f);
|
||||
Image okBg = okayGo.GetComponent<Image>();
|
||||
okBg.color = Color.white;
|
||||
|
||||
GameObject okayTextGo = new GameObject("Text (Legacy)", typeof(RectTransform), typeof(Text));
|
||||
okayTextGo.transform.SetParent(okayGo.transform, false);
|
||||
RectTransform okayTextRt = okayTextGo.GetComponent<RectTransform>();
|
||||
okayTextRt.anchorMin = Vector2.zero;
|
||||
okayTextRt.anchorMax = Vector2.one;
|
||||
okayTextRt.offsetMin = Vector2.zero;
|
||||
okayTextRt.offsetMax = Vector2.zero;
|
||||
Text okText = okayTextGo.GetComponent<Text>();
|
||||
okText.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||||
okText.fontSize = 30;
|
||||
okText.alignment = TextAnchor.MiddleCenter;
|
||||
okText.color = new Color(0.23f, 0.23f, 0.23f, 1f);
|
||||
okText.text = "okay";
|
||||
|
||||
return rootGo;
|
||||
}
|
||||
|
||||
private static void SetButtonVisible(Button button, bool visible)
|
||||
{
|
||||
if (button != null)
|
||||
button.gameObject.SetActive(visible);
|
||||
}
|
||||
|
||||
private static void SetActiveSafe(GameObject go, bool active)
|
||||
{
|
||||
if (go != null)
|
||||
go.SetActive(active);
|
||||
}
|
||||
|
||||
private static GameObject FindSceneObjectByExactName(string objectName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(objectName))
|
||||
return null;
|
||||
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null || t.gameObject.scene != scene)
|
||||
continue;
|
||||
if (string.Equals(t.name, objectName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static GameObject FindSceneObjectByContainsName(string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
return null;
|
||||
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
Transform[] all = UnityEngine.Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (t == null || t.gameObject.scene != scene)
|
||||
continue;
|
||||
if (t.name.IndexOf(token, System.StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
return t.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static GameObject FindChildByName(Transform root, string childName)
|
||||
{
|
||||
if (root == null || string.IsNullOrEmpty(childName))
|
||||
return null;
|
||||
|
||||
Transform[] children = root.GetComponentsInChildren<Transform>(true);
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
{
|
||||
Transform c = children[i];
|
||||
if (c != null && string.Equals(c.name, childName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return c.gameObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Button FindButtonByName(Transform root, string buttonName)
|
||||
{
|
||||
if (root == null || string.IsNullOrEmpty(buttonName))
|
||||
return null;
|
||||
|
||||
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
Button b = buttons[i];
|
||||
if (b != null && string.Equals(b.name, buttonName, System.StringComparison.OrdinalIgnoreCase))
|
||||
return b;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Button FindButtonByContainsName(Transform root, string token)
|
||||
{
|
||||
if (root == null || string.IsNullOrEmpty(token))
|
||||
return null;
|
||||
|
||||
string normalizedToken = token.Replace(" ", "").ToLowerInvariant();
|
||||
Button[] buttons = root.GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
Button b = buttons[i];
|
||||
if (b == null)
|
||||
continue;
|
||||
|
||||
string current = b.name.Replace(" ", "").ToLowerInvariant();
|
||||
if (current.Contains(normalizedToken))
|
||||
return b;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Canvas FindTopCanvasInActiveScene()
|
||||
{
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
Canvas[] canvases = UnityEngine.Object.FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
Canvas best = null;
|
||||
int bestOrder = int.MinValue;
|
||||
|
||||
for (int i = 0; i < canvases.Length; i++)
|
||||
{
|
||||
Canvas c = canvases[i];
|
||||
if (c == null || c.gameObject.scene != scene)
|
||||
continue;
|
||||
|
||||
int order = c.sortingOrder;
|
||||
if (c.renderMode == RenderMode.ScreenSpaceOverlay)
|
||||
order += 10000;
|
||||
|
||||
if (best == null || order > bestOrder)
|
||||
{
|
||||
best = c;
|
||||
bestOrder = order;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
private static Canvas CreateFallbackCanvas()
|
||||
{
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
if (!scene.IsValid() || !scene.isLoaded)
|
||||
return null;
|
||||
|
||||
GameObject go = new GameObject("__UnimplementedPromptCanvas",
|
||||
typeof(RectTransform),
|
||||
typeof(Canvas),
|
||||
typeof(CanvasScaler),
|
||||
typeof(GraphicRaycaster));
|
||||
try
|
||||
{
|
||||
SceneManager.MoveGameObjectToScene(go, scene);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// keep default scene placement if move fails
|
||||
}
|
||||
|
||||
Canvas canvas = go.GetComponent<Canvas>();
|
||||
if (canvas != null)
|
||||
{
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = 32700;
|
||||
}
|
||||
|
||||
CanvasScaler scaler = go.GetComponent<CanvasScaler>();
|
||||
if (scaler != null)
|
||||
{
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920f, 1080f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
}
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
private void EnsureMinimumPromptElements()
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
if (pressText == null)
|
||||
{
|
||||
GameObject textGo = new GameObject("Press an unimplemented feature", typeof(RectTransform), typeof(Text));
|
||||
textGo.transform.SetParent(root.transform, false);
|
||||
RectTransform textRt = textGo.GetComponent<RectTransform>();
|
||||
textRt.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
textRt.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
textRt.sizeDelta = new Vector2(820f, 80f);
|
||||
textRt.anchoredPosition = new Vector2(0f, 40f);
|
||||
|
||||
Text t = textGo.GetComponent<Text>();
|
||||
t.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||||
t.fontSize = 40;
|
||||
t.alignment = TextAnchor.MiddleCenter;
|
||||
t.color = Color.white;
|
||||
t.text = "Press an unimplemented feature";
|
||||
pressText = textGo;
|
||||
}
|
||||
|
||||
if (okayButton == null)
|
||||
{
|
||||
GameObject okayGo = new GameObject("okay", typeof(RectTransform), typeof(Image), typeof(Button));
|
||||
okayGo.transform.SetParent(root.transform, false);
|
||||
RectTransform okayRt = okayGo.GetComponent<RectTransform>();
|
||||
okayRt.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
okayRt.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
okayRt.sizeDelta = new Vector2(200f, 60f);
|
||||
okayRt.anchoredPosition = new Vector2(0f, -40f);
|
||||
|
||||
Image okBg = okayGo.GetComponent<Image>();
|
||||
okBg.color = Color.white;
|
||||
|
||||
GameObject textGo = new GameObject("Text (Legacy)", typeof(RectTransform), typeof(Text));
|
||||
textGo.transform.SetParent(okayGo.transform, false);
|
||||
RectTransform textRt = textGo.GetComponent<RectTransform>();
|
||||
textRt.anchorMin = Vector2.zero;
|
||||
textRt.anchorMax = Vector2.one;
|
||||
textRt.offsetMin = Vector2.zero;
|
||||
textRt.offsetMax = Vector2.zero;
|
||||
|
||||
Text t = textGo.GetComponent<Text>();
|
||||
t.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||||
t.fontSize = 30;
|
||||
t.alignment = TextAnchor.MiddleCenter;
|
||||
t.color = new Color(0.23f, 0.23f, 0.23f, 1f);
|
||||
t.text = "okay";
|
||||
|
||||
okayButton = okayGo.GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
|
||||
private void BringRootToFront()
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
Canvas canvas = root.GetComponent<Canvas>();
|
||||
if (canvas == null)
|
||||
canvas = root.AddComponent<Canvas>();
|
||||
if (root.GetComponent<GraphicRaycaster>() == null)
|
||||
root.AddComponent<GraphicRaycaster>();
|
||||
|
||||
canvas.overrideSorting = true;
|
||||
canvas.sortingOrder = 32700;
|
||||
|
||||
if (root.transform.parent != null)
|
||||
root.transform.SetAsLastSibling();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39a418c2032c3cc4899163d987dfd3e1
|
||||
Reference in New Issue
Block a user