/* * @Author: 白哉 * @Description: * @Date: 2026年01月29日 星期四 16:01:25 * @Modify: */ using System.Collections.Generic; using Logic.CrashSight; using UnityEngine; namespace TH1_Logic.Comic { public enum ComicState { None = 0, Prepared = 1, Playing = 2, Pausing = 3, Ended = 4, } public class ComicControl { private GameObject _comicRoot; private ComicData _comicData; private ComicSheet _comicSheet; private float _speed = 1f; private float _progress = 0f; private float _duration = 10f; private int _actionIndex = 0; private int _comicMaxIndex = 0; private ComicState _state = ComicState.None; private Dictionary _actionHandle = new Dictionary(); public GameObject ComicRoot => _comicRoot; public ComicSheet ComicSheet => _comicSheet; public ComicState State => _state; public int ActionIndex => _actionIndex; public int MaxIndex => _comicMaxIndex; public float Progress => _progress; public float Duration => _duration; public void Init(ComicSheet sheet, GameObject comicRoot) { Clear(); if (!comicRoot) return; // IL2CPP 保护:确保所有集合已初始化 sheet?.EnsureCollectionsInitialized(); _comicRoot = comicRoot; _comicSheet = sheet; var comicPrefab = ComicManager.Instance.LoadPrefab("ComicPrefab"); if (!comicPrefab) { LogSystem.LogError($"ComicControl Init Error ComicPrefab is null"); return; } var dialogPrefab = ComicManager.Instance.LoadPrefab("DialogPrefab"); if (!dialogPrefab) { LogSystem.LogError($"ComicControl Init Error DialogPrefab is null"); return; } var imagePrefab = ComicManager.Instance.LoadPrefab("ImagePrefab"); if (!imagePrefab) { LogSystem.LogError($"ComicControl Init Error ImagePrefab is null"); return; } var index = 0; for (int i = 0; i < _comicSheet.ComicDatas.Count; i++) { var data = _comicSheet.ComicDatas[i]; var comicInstance = Object.Instantiate(comicPrefab, _comicRoot.transform, false); data.Mono = comicInstance.GetComponent(); if (!data.Mono) { LogSystem.LogError($"ComicControl Init Error _comicMono is null"); return; } data.ApplyToMono(); // IL2CPP 保护:跳过 null 集合 if (data.SubItems == null) { LogSystem.LogWarning($"[ComicControl] ComicData SubItems is null, initializing empty list"); data.SubItems = new List(); } foreach (var item in data.SubItems) { GameObject instance = null; if(item.ItemType == ComicSubItemType.Image) instance = Object.Instantiate(imagePrefab, data.Mono.ItemRoot, false); if(item.ItemType == ComicSubItemType.Dialog) instance = Object.Instantiate(dialogPrefab, data.Mono.ItemRoot, false); var itemMono = instance?.GetComponent(); if (!itemMono) { LogSystem.LogError($"ComicControl Init Error itemMono is null"); continue; } item.Mono = itemMono; item.ApplyToItemMono(); } if (i == 0) { data.InitFadeInAction(ComicActionType.FadeIn); } else { data.InitFadeInAction(ComicActionType.AllSlideInUp); } if (i == _comicSheet.ComicDatas.Count - 1) { data.InitFadeOutAction(ComicActionType.FadeOut); } else { data.InitFadeOutAction(ComicActionType.AllFadeOut); } data.FadeInAction.Index = index; // IL2CPP 保护 if (data.Actions == null) { LogSystem.LogWarning($"[ComicControl] ComicData Actions is null, initializing empty list"); data.Actions = new List(); } foreach (var action in data.Actions) { index++; action.Index = index; } index++; data.FadeOutAction.Index = index; } _comicMaxIndex = index; _actionIndex = 0; _progress = 0; _state = ComicState.Prepared; Update(0f); } public void PreviewComicData(ComicData data, GameObject comicRoot) { Clear(); if (!comicRoot) return; _comicRoot = comicRoot; _comicData = data; var comicPrefab = ComicManager.Instance.LoadPrefab("ComicPrefab"); if (!comicPrefab) { LogSystem.LogError($"ComicControl Init Error ComicPrefab is null"); return; } var dialogPrefab = ComicManager.Instance.LoadPrefab("DialogPrefab"); if (!dialogPrefab) { LogSystem.LogError($"ComicControl Init Error DialogPrefab is null"); return; } var imagePrefab = ComicManager.Instance.LoadPrefab("ImagePrefab"); if (!imagePrefab) { LogSystem.LogError($"ComicControl Init Error ImagePrefab is null"); return; } var comicInstance = Object.Instantiate(comicPrefab, _comicRoot.transform, false); data.Mono = comicInstance.GetComponent(); if (!data.Mono) { LogSystem.LogError($"ComicControl Init Error _comicMono is null"); return; } data.ApplyToMono(); foreach (var item in data.SubItems) { GameObject instance = null; if(item.ItemType == ComicSubItemType.Image) instance = Object.Instantiate(imagePrefab, data.Mono.ItemRoot, false); if(item.ItemType == ComicSubItemType.Dialog) instance = Object.Instantiate(dialogPrefab, data.Mono.ItemRoot, false); var itemMono = instance?.GetComponent(); if (!itemMono) { LogSystem.LogError($"ComicControl Init Error itemMono is null"); continue; } item.Mono = itemMono; item.ApplyToItemMono(); } } public void ForceNext() { if (_state == ComicState.Ended) return; if (_state == ComicState.Playing) { Update(Mathf.Max(_duration - _progress, 0f)); } if (_state == ComicState.Prepared) { _state = ComicState.Playing; _actionIndex = 0; _progress = 0; _state = ComicState.Playing; } if (_state == ComicState.Pausing) { if (_actionIndex >= _comicMaxIndex) { _state = ComicState.Ended; return; } _actionIndex++; _progress = 0; _state = ComicState.Playing; } } public void Next() { if (_state == ComicState.Ended) return; if (_state == ComicState.Playing) { Update(Mathf.Max(_duration - _progress, 0f)); return; } if (_state == ComicState.Prepared) { _state = ComicState.Playing; _actionIndex = 0; _progress = 0; _state = ComicState.Playing; } if (_state == ComicState.Pausing) { if (_actionIndex >= _comicMaxIndex) { _state = ComicState.Ended; return; } _actionIndex++; _progress = 0; _state = ComicState.Playing; } } public void Update(float deltaTime = 0.016f) { if (deltaTime != 0 && _state != ComicState.Playing) return; _actionHandle.Clear(); _progress += deltaTime * _speed; _duration = 0; foreach (var data in _comicSheet.ComicDatas) { // IL2CPP 保护 if (data.Actions == null) continue; foreach (var action in data.Actions) UpdateAction(data, action); } for (int i = _comicSheet.ComicDatas.Count - 1; i >= 0; i--) { UpdateAction(_comicSheet.ComicDatas[i], _comicSheet.ComicDatas[i].FadeOutAction); } for (int i = _comicSheet.ComicDatas.Count - 1; i >= 0; i--) { UpdateAction(_comicSheet.ComicDatas[i], _comicSheet.ComicDatas[i].FadeInAction); } if (_progress >= _duration) _state = ComicState.Pausing; } private void UpdateAction(ComicData data, ComicAction action) { var logic = ComicActionLogicFactory.GetActionLogic(action.ActionType); var item = data.GetSubItemById(action.TargetId); if (action.Index == _actionIndex) { var ratio = Mathf.Min(1, _progress / action.Duration); logic.SetUpdateAction(data, item, action, ratio); if (action.TargetId >= 0) _actionHandle[action.TargetId] = action.Index; if (action.Duration > _duration) _duration = action.Duration; } if (_actionHandle.TryGetValue(action.TargetId, out var value)) return; if (action.Index < _actionIndex) { logic.SetEndState(data, item, action); } if (action.Index > _actionIndex) { logic.SetStartState(data, item, action); } } public void Exit() { Clear(); } public void Clear() { _state = ComicState.None; if (_comicSheet != null) { foreach (var data in _comicSheet.ComicDatas) ClearComicData(data); } if (_comicData != null) ClearComicData(_comicData); } public void ClearComicData(ComicData data) { if(data.Mono) Object.DestroyImmediate(data.Mono.gameObject); foreach (var item in data.SubItems) { if (item.Mono) Object.DestroyImmediate(item.Mono.gameObject); item.Mono = null; } data.Mono = null; } } }