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} ");
}
}
}