415 lines
15 KiB
C#
415 lines
15 KiB
C#
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>");
|
||
}
|
||
}
|
||
} |