using System.Collections.Generic; using Bansonic; using DG.Tweening; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class eula_and_warnings : MonoBehaviour { private const string MainSceneName = "Main_main"; private const string RankingConsentPrefKey = "before_everything_agree_ranking"; private const string FirstLaunchCompletedPrefKey = "before_everything_first_launch_completed"; private const string LightWarningAcceptedPrefKey = "before_everything_light_warning_accepted"; private const string UserInfoAcceptedPrefKey = "before_everything_user_info_accepted"; private const float LightWarningMinimumSeconds = 5f; private const float FadeDuration = 0.3f; private const float RequiredScrollReadThreshold = 0.1f; [Header("objs")] [SerializeField] GameObject lightWarningObj; [SerializeField] GameObject uInfoEulaObj; [Header("canvas groups")] [SerializeField] CanvasGroup lightWarningCG; [SerializeField] CanvasGroup uInfoEulaCG; [Header("intro")] [SerializeField] float lightWarningFadeInDelay = 0f; [Header("light warnings")] [SerializeField] Toggle lw_uhaveRead; [SerializeField] Button lw_next; [SerializeField] Button lw_quit; [Header("user infomation eula")] [SerializeField] Toggle uie_uhaveRead; [SerializeField] Toggle uie_agreeRanking; [SerializeField] Button uie_next; [SerializeField] Button uie_quit; [SerializeField] ScrollRect uie_scrollRect; private float _lightWarningShownAtRealtime; private AsyncOperation _mainScenePreloadOperation; private Tween _lightWarningTween; private Tween _userInfoTween; private bool _isTransitioning; private bool _mainScenePreloadRequested; private bool _mainScenePreloadReady; private bool _hasCompletedFirstLaunch; private bool _hasAcceptedLightWarning; private bool _hasAcceptedUserInfoEula; private readonly List _hiddenMainSceneRoots = new List(); private void Awake() { AutoAssignReferences(); ForceInitialState(); BindEvents(); } private void Start() { LoadPersistedConsentState(); if (ShouldSkipConfirmationFlow()) { ActivateMainScene(); return; } PlayLightWarningIntro(); } private void OnDestroy() { if (lw_next != null) lw_next.onClick.RemoveListener(HandleLightWarningNextClicked); if (lw_quit != null) lw_quit.onClick.RemoveListener(HandleLightWarningQuitClicked); if (uie_next != null) uie_next.onClick.RemoveListener(HandleUserInfoNextClicked); if (uie_quit != null) uie_quit.onClick.RemoveListener(HandleUserInfoQuitClicked); _lightWarningTween?.Kill(); _userInfoTween?.Kill(); } private void ForceInitialState() { if (lightWarningObj != null) lightWarningObj.SetActive(true); if (uInfoEulaObj != null) uInfoEulaObj.SetActive(false); SetupCanvasGroup(lightWarningCG, false); SetupCanvasGroup(uInfoEulaCG, false); if (lw_uhaveRead != null) lw_uhaveRead.SetIsOnWithoutNotify(false); if (uie_uhaveRead != null) uie_uhaveRead.SetIsOnWithoutNotify(false); if (uie_agreeRanking != null) { bool agreeRanking = PlayerPrefs.GetInt(RankingConsentPrefKey, 0) == 1; uie_agreeRanking.SetIsOnWithoutNotify(agreeRanking); } if (uie_scrollRect != null) { Canvas.ForceUpdateCanvases(); uie_scrollRect.verticalNormalizedPosition = 1f; } _lightWarningShownAtRealtime = Time.realtimeSinceStartup; _isTransitioning = false; } private void LoadPersistedConsentState() { _hasCompletedFirstLaunch = PlayerPrefs.GetInt(FirstLaunchCompletedPrefKey, 0) == 1; _hasAcceptedLightWarning = PlayerPrefs.GetInt(LightWarningAcceptedPrefKey, 0) == 1; _hasAcceptedUserInfoEula = PlayerPrefs.GetInt(UserInfoAcceptedPrefKey, 0) == 1; } private bool ShouldSkipConfirmationFlow() { return _hasCompletedFirstLaunch && _hasAcceptedLightWarning && _hasAcceptedUserInfoEula; } private void PlayLightWarningIntro() { if (lightWarningObj == null || lightWarningCG == null) { return; } lightWarningObj.SetActive(true); lightWarningCG.alpha = 0f; lightWarningCG.interactable = false; lightWarningCG.blocksRaycasts = false; _lightWarningTween?.Kill(); _lightWarningTween = lightWarningCG .DOFade(1f, FadeDuration) .SetDelay(Mathf.Max(0f, lightWarningFadeInDelay)) .SetUpdate(true) .OnStart(() => _lightWarningShownAtRealtime = Time.realtimeSinceStartup) .OnComplete(() => SetupCanvasGroup(lightWarningCG, true)); } private void BindEvents() { if (lw_next != null) { lw_next.onClick.RemoveListener(HandleLightWarningNextClicked); lw_next.onClick.AddListener(HandleLightWarningNextClicked); } if (lw_quit != null) { lw_quit.onClick.RemoveListener(HandleLightWarningQuitClicked); lw_quit.onClick.AddListener(HandleLightWarningQuitClicked); } if (uie_next != null) { uie_next.onClick.RemoveListener(HandleUserInfoNextClicked); uie_next.onClick.AddListener(HandleUserInfoNextClicked); } if (uie_quit != null) { uie_quit.onClick.RemoveListener(HandleUserInfoQuitClicked); uie_quit.onClick.AddListener(HandleUserInfoQuitClicked); } } private void BeginPreloadMainScene() { if (!Application.isPlaying || _mainScenePreloadRequested) { return; } _mainScenePreloadRequested = true; StartCoroutine(PreloadMainSceneRoutine()); } private System.Collections.IEnumerator PreloadMainSceneRoutine() { _mainScenePreloadOperation = SceneManager.LoadSceneAsync(MainSceneName, LoadSceneMode.Additive); if (_mainScenePreloadOperation == null) { yield break; } _mainScenePreloadOperation.allowSceneActivation = false; while (_mainScenePreloadOperation.progress < 0.9f) { yield return null; } HidePreloadedMainSceneRoots(); _mainScenePreloadReady = true; } private void HandleLightWarningNextClicked() { if (_isTransitioning) { return; } float staySeconds = Time.realtimeSinceStartup - _lightWarningShownAtRealtime; float remainSeconds = Mathf.Max(0f, LightWarningMinimumSeconds - staySeconds); bool hasRead = lw_uhaveRead != null && lw_uhaveRead.isOn; if (!hasRead || remainSeconds > 0f) { if (!hasRead && remainSeconds > 0f) { gNotice.error.display($"您必须知悉相关风险,还需停留{Mathf.CeilToInt(remainSeconds)}秒后才可进入"); } else if (!hasRead) { gNotice.error.display("您必须知悉相关风险"); } else { gNotice.error.display($"还需停留{Mathf.CeilToInt(remainSeconds)}秒后才可进入"); } return; } _hasAcceptedLightWarning = true; PlayerPrefs.SetInt(LightWarningAcceptedPrefKey, 1); PlayerPrefs.Save(); TransitionCanvasGroup(lightWarningObj, lightWarningCG, false, () => { BeginPreloadMainScene(); TransitionCanvasGroup(uInfoEulaObj, uInfoEulaCG, true, null); }); } private void HandleLightWarningQuitClicked() { MarkPolicyRejectedAndQuit(); } private void HandleUserInfoNextClicked() { if (_isTransitioning) { return; } if (!HasScrolledToBottom()) { gNotice.error.display("必须完整阅读"); return; } if (uie_uhaveRead == null || !uie_uhaveRead.isOn) { gNotice.error.display("请勾选“我已知晓”"); return; } bool agreeRanking = uie_agreeRanking != null && uie_agreeRanking.isOn; _hasAcceptedUserInfoEula = true; _hasCompletedFirstLaunch = true; PlayerPrefs.SetInt(UserInfoAcceptedPrefKey, 1); PlayerPrefs.SetInt(FirstLaunchCompletedPrefKey, 1); PlayerPrefs.SetInt(RankingConsentPrefKey, agreeRanking ? 1 : 0); PlayerPrefs.Save(); TransitionCanvasGroup(uInfoEulaObj, uInfoEulaCG, false, ActivateMainScene); } private void HandleUserInfoQuitClicked() { MarkPolicyRejectedAndQuit(); } private static void MarkPolicyRejectedAndQuit() { #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else Application.Quit(); #endif } private void ActivateMainScene() { if (_mainScenePreloadReady) { if (!gTransition.Run(ActivatePreloadedMainSceneRoutineWithoutFade())) { StartCoroutine(ActivatePreloadedMainSceneRoutineWithoutFade()); } return; } if (!gTransition.LoadScene(MainSceneName, LoadSceneMode.Single)) { SceneManager.LoadScene(MainSceneName, LoadSceneMode.Single); } } private System.Collections.IEnumerator ActivatePreloadedMainSceneRoutineWithoutFade() { Scene sourceScene = gameObject.scene; if (_mainScenePreloadOperation == null) { if (!gTransition.LoadScene(MainSceneName, LoadSceneMode.Single)) { SceneManager.LoadScene(MainSceneName, LoadSceneMode.Single); } yield break; } _mainScenePreloadOperation.allowSceneActivation = true; while (!_mainScenePreloadOperation.isDone) { yield return null; } RestorePreloadedMainSceneRoots(); Scene mainScene = SceneManager.GetSceneByName(MainSceneName); if (mainScene.isLoaded) { SceneManager.SetActiveScene(mainScene); } if (sourceScene.IsValid() && sourceScene.isLoaded && sourceScene.name == "beforeEverything") { yield return SceneManager.UnloadSceneAsync(sourceScene); } _mainScenePreloadOperation = null; _mainScenePreloadReady = false; } private void HidePreloadedMainSceneRoots() { _hiddenMainSceneRoots.Clear(); Scene mainScene = SceneManager.GetSceneByName(MainSceneName); if (!mainScene.IsValid() || !mainScene.isLoaded) { return; } List roots = new List(); mainScene.GetRootGameObjects(roots); for (int i = 0; i < roots.Count; i++) { GameObject root = roots[i]; if (root == null || !root.activeSelf) { continue; } _hiddenMainSceneRoots.Add(root); root.SetActive(false); } } private void RestorePreloadedMainSceneRoots() { for (int i = 0; i < _hiddenMainSceneRoots.Count; i++) { GameObject root = _hiddenMainSceneRoots[i]; if (root != null) { root.SetActive(true); } } _hiddenMainSceneRoots.Clear(); } private bool HasScrolledToBottom() { if (uie_scrollRect == null) { return true; } if (!uie_scrollRect.vertical) { return true; } return uie_scrollRect.verticalNormalizedPosition <= RequiredScrollReadThreshold; } private void TransitionCanvasGroup(GameObject targetObj, CanvasGroup targetGroup, bool show, TweenCallback onComplete) { if (targetObj == null || targetGroup == null) { onComplete?.Invoke(); return; } _isTransitioning = true; if (show) { targetObj.SetActive(true); targetGroup.alpha = 0f; targetGroup.interactable = false; targetGroup.blocksRaycasts = false; } Tween tween = targetGroup .DOFade(show ? 1f : 0f, FadeDuration) .SetUpdate(true) .OnComplete(() => { SetupCanvasGroup(targetGroup, show); if (!show) { targetObj.SetActive(false); } _isTransitioning = false; onComplete?.Invoke(); }); if (ReferenceEquals(targetGroup, lightWarningCG)) { _lightWarningTween?.Kill(); _lightWarningTween = tween; } else if (ReferenceEquals(targetGroup, uInfoEulaCG)) { _userInfoTween?.Kill(); _userInfoTween = tween; } } private static void SetupCanvasGroup(CanvasGroup group, bool visible) { if (group == null) { return; } group.alpha = visible ? 1f : 0f; group.interactable = visible; group.blocksRaycasts = visible; } private void AutoAssignReferences() { if (lightWarningObj == null && lightWarningCG != null) { lightWarningObj = lightWarningCG.gameObject; } if (uInfoEulaObj == null && uInfoEulaCG != null) { uInfoEulaObj = uInfoEulaCG.gameObject; } if (lightWarningObj == null) { lightWarningObj = FindSceneObject("illnessWarnings"); } if (uInfoEulaObj == null) { uInfoEulaObj = FindSceneObject("userDataProcessing"); } if (lightWarningCG == null && lightWarningObj != null) { lightWarningCG = lightWarningObj.GetComponent(); } if (uInfoEulaCG == null && uInfoEulaObj != null) { uInfoEulaCG = uInfoEulaObj.GetComponent(); } if (lw_uhaveRead == null && lightWarningObj != null) { lw_uhaveRead = FindComponentInChildrenByName(lightWarningObj.transform, "uread"); } if (lw_next == null && lightWarningObj != null) { lw_next = FindComponentInChildrenByName