Files
back_cantanBuilding/Assets/Scripts/UI/PartnerGather/Mining/EventPartnerMiningSceneController.cs
2026-05-26 16:15:54 +08:00

415 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 事件合作伙伴挖矿场景控制器
/// 负责管理整个挖矿场景的逻辑,包括角色移动、挖矿动画、相机跟随等
/// 建议挂载在:挖矿场景的根对象上
/// </summary>
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<GameObject> _activeMiningResources = new();
// 管理矿石堆,一个一个的场景可能更好
private readonly List<Transform> _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<EventPartnerGatherManager>();
// 自动查找子组件
InitializeComponents();
Log("EventPartnerMiningSceneController 初始化完成");
// 第二主角
Log(Character2);
}
/// <summary>
/// 自动查找和初始化子组件
/// 如果Inspector中未手动分配组件会尝试在子对象中查找
/// </summary>
private void InitializeComponents()
{
Log("开始初始化挖矿场景组件...");
// 查找挖矿点管理器
if (!miningPoints)
{
miningPoints = GetComponentInChildren<EventPartnerMiningPointManager>();
Log(miningPoints != null
? $"✓ 自动找到挖矿点管理器: {miningPoints.name}"
: "⚠ 警告未找到EventPartnerMiningPointManager组件");
}
// 查找角色控制器
if (!character)
{
character = GetComponentInChildren<EventPartnerMiningCharacterController>();
Log(character ? $"✓ 自动找到角色控制器: {character.name}" : "⚠ 警告未找到EventPartnerMiningCharacterController组件");
}
// 查找火车控制器
if (!trainController)
{
trainController = GetComponentInChildren<EventPartnerTrainController>();
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<CinemachineVirtualCamera>();
_targetVcam = transform.Find("CameraRoot/CameraSwitch").GetComponent<CinemachineVirtualCamera>();
// 验证矿石资源预制体
if (miningResourcePrefabs == null || miningResourcePrefabs.Length == 0)
{
Log("⚠ 警告:未设置矿石资源预制体,矿石生成功能将不可用");
}
else
{
Log($"✓ 矿石资源预制体数量: {miningResourcePrefabs.Length}");
}
Log("挖矿场景组件初始化完成");
}
private void OnEnable()
{
GContext.OnEvent<EventPartnerGatherPointsUpdate>().Subscribe(_ => OnPointsUpdate()).AddTo(_disposables);
GContext.OnEvent<EventPartnerGatherMiningProgressUpdate>().Subscribe(evt => OnMiningProgressUpdate(evt)).AddTo(_disposables);
GContext.OnEvent<EventPartnerGatherTrainProgressUpdate>().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<GameObject>();
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<Vector3> 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($"<Color=cyan> EventPartnerMiningSceneController {t} </color>");
}
}
}