using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using asap.core; using Cinemachine; using DataCenter; using UniRx; using Random = UnityEngine.Random; namespace UI.PartnerGather.Mining { /// /// 事件合作伙伴挖矿场景控制器 /// 负责管理整个挖矿场景的逻辑,包括角色移动、挖矿动画、相机跟随等 /// 建议挂载在:挖矿场景的根对象上 /// public class EventPartnerMiningSceneController : MonoBehaviour { #region 组件引用配置 [Header("=== 核心组件引用 ===")] [Tooltip("角色控制器 - 建议挂载在角色GameObject上")] public EventPartnerMiningCharacterController character; [Header("第二主角")] public EventPartnerMiningCharacterController Character2; // 好友的 [Tooltip("挖矿点管理器 - 建议挂载在MiningPoints容器对象上")] public EventPartnerMiningPointManager miningPoints; [Tooltip("火车控制器 - 建议挂载在Train容器对象上")] public EventPartnerTrainController trainController; [Header("=== 资源配置 ===")] [Tooltip("矿石资源预制体数组 - 从Project窗口拖拽矿石Prefab到这里")] public GameObject[] miningResourcePrefabs; // P_miningresource_01~05 // [Header("=== 相机跟随设置 ===")] // [Tooltip("跟随相机Transform - 通常是Main Camera")] // public Transform followCamera; // [Range(-10f, 10f)] // public float cameraOffsetX = 2f; // [Range(0f, 20f)] // public float cameraY = 5f; // [Range(-50f, 0f)] // public float cameraZ = -10f; // [Range(1f, 20f)] // public float cameraSmooth = 8f; [Header("=== 动画与移动配置 ===")] [Range(0.5f, 10f)] [Tooltip("角色移动速度")] public float characterMoveSpeed = 2f; [Range(0.5f, 5f)] [Tooltip("挖矿动画持续时间")] public float miningDuration = 2f; [Range(0.01f, 1f)] [Tooltip("矿石生成间隔")] public float oreGenerateDelay = 0.5f; #endregion #region 运行时数据 private CinemachineVirtualCameraBase _targetVcam; // 动态生成的矿石对象缓存 private readonly List _activeMiningResources = new(); // 管理矿石堆,一个一个的场景可能更好 private readonly List _listOre = new(); // 数据管理与事件订阅 private EventPartnerGatherManager _manager; // private CompositeDisposable _disposables = new(); // UI面板引用 private EventPartnerDrawMiningPanel _drawMiningPanel; // 数据同步缓存(用于检测变化) private int _lastMiningProgress = -1; private int _lastTrainProgress = -1; private int _lastPoints = -1; #endregion private void Awake() { // 获取数据管理器 _manager = GContext.container.Resolve(); // 自动查找子组件 InitializeComponents(); Log("EventPartnerMiningSceneController 初始化完成"); // 第二主角 Log(Character2); } /// /// 自动查找和初始化子组件 /// 如果Inspector中未手动分配组件,会尝试在子对象中查找 /// private void InitializeComponents() { Log("开始初始化挖矿场景组件..."); // 查找挖矿点管理器 if (!miningPoints) { miningPoints = GetComponentInChildren(); Log(miningPoints != null ? $"✓ 自动找到挖矿点管理器: {miningPoints.name}" : "⚠ 警告:未找到EventPartnerMiningPointManager组件"); } // 查找角色控制器 if (!character) { character = GetComponentInChildren(); Log(character ? $"✓ 自动找到角色控制器: {character.name}" : "⚠ 警告:未找到EventPartnerMiningCharacterController组件"); } // 查找火车控制器 if (!trainController) { trainController = GetComponentInChildren(); Log(trainController ? $"✓ 自动找到火车控制器: {trainController.name}" : "⚠ 警告:未找到EventPartnerTrainController组件"); } // // 查找跟随相机(如果未设置) // if (followCamera == null) // { // var mainCamera = Camera.main; // if (mainCamera != null) // { // followCamera = mainCamera.transform; // Log($"✓ 自动设置跟随相机: {followCamera.name}"); // } // else // { // Log("⚠ 警告:未找到主相机,相机跟随功能将不可用"); // } // } // _vCam = transform.Find("CameraRoot/Camera").GetComponent(); _targetVcam = transform.Find("CameraRoot/CameraSwitch").GetComponent(); // 验证矿石资源预制体 if (miningResourcePrefabs == null || miningResourcePrefabs.Length == 0) { Log("⚠ 警告:未设置矿石资源预制体,矿石生成功能将不可用"); } else { Log($"✓ 矿石资源预制体数量: {miningResourcePrefabs.Length}"); } Log("挖矿场景组件初始化完成"); } private void OnEnable() { GContext.OnEvent().Subscribe(_ => OnPointsUpdate()).AddTo(_disposables); GContext.OnEvent().Subscribe(evt => OnMiningProgressUpdate(evt)).AddTo(_disposables); GContext.OnEvent().Subscribe(evt => OnTrainProgressUpdate(evt)).AddTo(_disposables); } private void Start() { _listOre.Add(transform.Find("ore01")); _listOre.Add(transform.Find("ore02")); _listOre.Add(transform.Find("ore03")); _listOre.Add(transform.Find("ore04")); _listOre.Add(transform.Find("ore05")); SyncAllData(); } private void Update() { // UpdateCameraFollow(); PollDataChanges(); } #region 相机跟随 (来自EventPartnerMiningController) // private void UpdateCameraFollow() // { // if (followCamera == null || character == null) return; // var pos = followCamera.position; // pos.x = Mathf.Lerp(pos.x, character.transform.position.x + cameraOffsetX, Time.deltaTime * cameraSmooth); // pos.y = cameraY; // pos.z = cameraZ; // followCamera.position = pos; // } #endregion #region 数据同步监听 (来自EventPartnerMiningController) private void PollDataChanges() { if (_manager?.GatherData == null) return; if (_lastPoints != _manager.GatherData.CurrentPoints) { _lastPoints = _manager.GatherData.CurrentPoints; } if (_lastMiningProgress != _manager.GatherData.CurrentMiningProgress) { int delta = _manager.GatherData.CurrentMiningProgress - _lastMiningProgress; _lastMiningProgress = _manager.GatherData.CurrentMiningProgress; for (int i = 0; i < Mathf.Max(0, delta); i++) { DoAutoMiningStep(); } } if (_lastTrainProgress != _manager.GatherData.TrainProgress) { _lastTrainProgress = _manager.GatherData.TrainProgress; UpdateUIPanel(); } } private void OnPointsUpdate() { UpdateUIPanel(); } private void OnMiningProgressUpdate(EventPartnerGatherMiningProgressUpdate evt) { Log($"接收到挖矿进度更新事件: {evt.Progress}"); // 触发自动挖矿动画(如果进度增加) int delta = evt.Progress - _lastMiningProgress; if (delta > 0) { _lastMiningProgress = evt.Progress; for (int i = 0; i < delta; i++) { DoAutoMiningStep(); } } UpdateUIPanel(); } private void OnTrainProgressUpdate(EventPartnerGatherTrainProgressUpdate evt) { Log($"接收到火车进度更新事件: {evt.Progress}/{evt.MaxNodes}"); _lastTrainProgress = evt.Progress; UpdateUIPanel(); } private void SyncAllData() { if (_manager?.GatherData == null) return; _lastPoints = _manager.GatherData.CurrentPoints; _lastMiningProgress = _manager.GatherData.CurrentMiningProgress; _lastTrainProgress = _manager.GatherData.TrainProgress; UpdateUIPanel(); } // ReSharper disable Unity.PerformanceAnalysis private async void DoAutoMiningStep() { if (miningPoints == null || character == null) return; var target = miningPoints.GetNextPoint(); if (target == null) return; await character.MoveToPosition(target.position, characterMoveSpeed); await character.PlayMining(miningDuration); UpdateUIPanel(); } private void UpdateUIPanel() { if (_drawMiningPanel == null || _manager?.GatherData == null) return; _drawMiningPanel.SetPoints(_manager.GatherData.CurrentPoints); _drawMiningPanel.SetMiningProgress(_manager.GatherData.CurrentMiningProgress); _drawMiningPanel.SetTrainProgress(_manager.GatherData.TrainProgress, _manager.MaxTrainNodes); } public void SetUIPanel(EventPartnerDrawMiningPanel panel) { _drawMiningPanel = panel; } #endregion private Transform _transPoint; #region 手动采集流程 (原MiningSceneController功能) public async Task StartMiningSequence(int point) { // 获取下一个挖矿点 var targetPoint = miningPoints.GetNextPoint(); if (targetPoint == null) return; UpdateActive(); var userPoint = targetPoint.Find("user_point"); var trainPoint = targetPoint.Find("train_point"); await character.MoveToPosition(userPoint.position, characterMoveSpeed); trainController.StartMoveTo(trainPoint.position); await OnEnterMining(point,targetPoint); } // 进入阶段,需要积分,计算挖矿到什么阶段 private async Task OnEnterMining(int points,Transform targetPoints) { await character.PlayMining(miningDuration); await GenerateAndCollectOres(points); } // 更新当前激活对象 private void UpdateActive() { // _activeOri = } private async Task GenerateAndCollectOres(int points) { Log($"GenerateAndCollectOres-> {points}"); // 根据点数生成对应数量的矿石 var oreCount = CalculateOreCount(points); var oreList = new List(); var listOrePos = CalculateOrePos(points); // for (var i = 0; i < oreCount; ++i) // { // var pos = listOrePos[i % listOrePos.Count]; // oreList.Add(CreateOre(pos)); // } // foreach (var ore in oreList) // { // await Awaiters.Seconds(oreGenerateDelay); // _ = trainController.CollectOre(ore, points); // } for (int i = 0; i < oreCount; i++) { // await Task.Delay((int)(oreGenerateDelay * 1000)); await Awaiters.Seconds(oreGenerateDelay); var pos = listOrePos[i % listOrePos.Count]; // 生成矿石 var ore = CreateOre(pos); if (ore != null) { // 矿石飞入对应车厢 _ = trainController.CollectOre(ore, points); } } } private int CalculateOreCount(int points) { return points switch { // return points; // 根据点数计算矿石数量 // if (points >= 50) return 5; // if (points >= 30) return 3; // if (points >= 20) return 2; // return 1; < 100 => 8, < 200 => 16, _ => 1 }; } private List CalculateOrePos(int points) { var ore = _listOre.First(); return (from Transform child in ore select child.position).ToList(); } private GameObject CreateOre(Vector3 position) { if (miningResourcePrefabs == null || miningResourcePrefabs.Length == 0) return null; // 随机选择一个矿石预制体 var orePos = new Vector3(position.x, position.y + 2, position.z); var prefab = miningResourcePrefabs[Random.Range(0, miningResourcePrefabs.Length)]; var ore = Instantiate(prefab, orePos, Quaternion.identity); _activeMiningResources.Add(ore); return ore; } #endregion public void ResetScene() { // 清理场景中的矿石 foreach (var ore in _activeMiningResources) { if (ore != null) DestroyImmediate(ore); } _activeMiningResources.Clear(); // 重置挖矿点 miningPoints?.ResetPoints(); // 重置火车状态 trainController?.ResetTrain(); } private void OnDisable() { _disposables.Dispose(); _disposables = new CompositeDisposable(); if (_targetVcam == null) return; // 方法1:将该相机移动到当前优先级子队列顶部,通常会成为Live或在混合后成为Live _targetVcam.MoveToTopOfPrioritySubqueue(); } private void Log(object t) { Debug.Log($" EventPartnerMiningSceneController {t} "); } } }