using UnityEngine; using AibisDream.FixSystem; using Cinemachine; using AibisDream.Framework; using DG.Tweening; using System.Collections; using AibisDream.Kit; namespace AibisDream { public class CuttingManager : MonoBehaviour { public BubbleSlotGroup bubbleSlotGroup; [Header("切割组件")] public GameObject gearFollowerPrefab; public GameObject entrancePanelPrefab; // 入场面板预制体 public float entranceDuration = 1.5f; // 入场动画时长 public float exitDuration = 1.5f; // 退场动画时长 public float panelOffsetY = 2f; // 面板在相机视野下方的偏移量 private GearFollower gearFollower; private bool isCuttingMode = false; private bool isEntranceComplete = false; // 入场是否完成 private bool isGearActive = false; // 标记gear是否已激活 private BodyModule _targetModule; private SpriteRenderer _targetSpriteRenderer; private GameObject entrancePanel; // 入场面板实例 private Camera _mainCamera; private CinemachineVirtualCamera _currentVirtualCamera; private void Awake() { // 注册 FixSystemCenter.SystemDic.Register(this); var virtualCam1 = transform.Find("Cut Emo Camera").GetComponent(); var virtualCam2 = transform.Find("Cut Memory Camera").GetComponent(); var virtualCam3 = transform.Find("Cut Logic Camera").GetComponent(); var virtualCam4 = transform.Find("Cut Emo Deep Camera").GetComponent(); var virtualCam5 = transform.Find("Cut Memory Deep Camera").GetComponent(); var virtualCam6 = transform.Find("Cut Logic Deep Camera").GetComponent(); CameraKit.Instance.RegisterCamera(CameraEnum.CutEmo, virtualCam1); CameraKit.Instance.RegisterCamera(CameraEnum.CutMemory, virtualCam2); CameraKit.Instance.RegisterCamera(CameraEnum.CutLogic, virtualCam3); CameraKit.Instance.RegisterCamera(CameraEnum.CutEmoDeep, virtualCam4); CameraKit.Instance.RegisterCamera(CameraEnum.CutMemoryDeep, virtualCam5); CameraKit.Instance.RegisterCamera(CameraEnum.CutLogicDeep, virtualCam6); _mainCamera = Camera.main; } private void Update() { if (isCuttingMode && !isGearActive && gearFollower != null) { // 检测点击 if (Input.GetMouseButtonDown(0)) { Ray ray = _mainCamera.ScreenPointToRay(Input.mousePosition); RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction); if (hit.collider != null && hit.collider.gameObject.GetComponent() != null) { gearFollower=hit.collider.gameObject.GetComponent(); ActivateGear(); } } } else if (isCuttingMode && isGearActive && gearFollower != null) { gearFollower.GearUpdate(); } } public void ClearCutLine() { if (gearFollower != null) { gearFollower.ClearCutLine(); Destroy(gearFollower.gameObject); gearFollower = null; } } private void ActivateGear() { AudioManager.Instance.PlaySfx("event:/FollowInput/drill"); isGearActive = true; if (gearFollower != null) { // 解除父子关系 gearFollower.transform.SetParent(null); gearFollower.Init(_targetSpriteRenderer); } // 面板退场 if (entrancePanel != null) { Vector3 startPosition = GetPanelSpawnPosition(); entrancePanel.transform.DOMove(startPosition, exitDuration) .SetEase(Ease.InBack) .OnComplete(() => { Destroy(entrancePanel); entrancePanel = null; }); } } public IEnumerator StartCutting(BodyModule targetModule) { // 检查参数 if (targetModule == null) { Debug.LogError("targetModule 为空"); yield break; } // 保存目标模块 _targetModule = targetModule; // 获取目标精灵渲染器 _targetSpriteRenderer = targetModule.GetCutSpriteRenderer(); if (_targetSpriteRenderer == null) { Debug.LogError("targetSprite 为空"); yield break; } // 停止之前的切割 StopCutting(); // 设置切割模式 isCuttingMode = true; isEntranceComplete = false; // 创建入场面板 CreateEntrancePanel(); // 等待入场动画完成 yield return new WaitUntil(() => isEntranceComplete); } private Vector3 GetPanelSpawnPosition() { if (_mainCamera == null) { _mainCamera = Camera.main; } // 获取相机的位置和旋转 Vector3 cameraPosition = _mainCamera.transform.position; Quaternion cameraRotation = _mainCamera.transform.rotation; // 计算相机视野下方的位置 Vector3 forward = cameraRotation * Vector3.forward; Vector3 right = cameraRotation * Vector3.right; Vector3 up = cameraRotation * Vector3.up; // 计算相机视野的底部中心点 float height = 2f * Mathf.Tan(_mainCamera.fieldOfView * 0.5f * Mathf.Deg2Rad) * _mainCamera.nearClipPlane; float width = height * _mainCamera.aspect; // 计算面板的起始位置(在相机视野下方) Vector3 bottomCenter = cameraPosition + forward * _mainCamera.nearClipPlane - up * (height * 0.5f + panelOffsetY); return bottomCenter; } private void CreateEntrancePanel() { // 获取基于当前相机位置的生成位置 Vector3 startPosition = GetPanelSpawnPosition(); if (startPosition == Vector3.zero) { Debug.LogError("无法获取面板生成位置"); return; } // 创建入场面板,保持原始旋转 entrancePanel = Instantiate(entrancePanelPrefab, startPosition, Quaternion.Euler(0,0,-90)); // 获取GearFollower组件(作为子物体) gearFollower = entrancePanel.GetComponentInChildren(); if (gearFollower == null) { Debug.LogError("入场面板预制体中没有找到GearFollower组件"); return; } // 计算相机视野高度 float height = 2f * Mathf.Tan(_mainCamera.fieldOfView * 0.5f * Mathf.Deg2Rad) * _mainCamera.nearClipPlane; // 计算目标位置(相机视野中心偏下) Vector3 targetPosition = startPosition + _mainCamera.transform.up * 3.5f; // 执行入场动画 entrancePanel.transform.DOMove(targetPosition, entranceDuration) .SetEase(Ease.OutBack) .OnComplete(() => { isEntranceComplete = true; }); } public void OnCutComplete() { isCuttingMode = false; isEntranceComplete = false; isGearActive = false; if (gearFollower != null) { gearFollower.FinishCutting(); } // 如果面板还存在,删除它 if (entrancePanel != null) { Destroy(entrancePanel); entrancePanel = null; } } public void UpdateModule() { if (_targetModule != null) { _targetModule.OnCuttingDown(); } } public void SetCutTextVisible(bool visible) { if (_targetModule != null) { _targetModule.SetCutTextVisible(visible); } } public void UpdateCutProgress(float progress) { if (_targetModule != null) { _targetModule.UpdateCutProgress(progress); } } public void StartCutTextFlicker() { if (_targetModule != null) { _targetModule.StartCutTextFlicker(); } } public void StopCutTextFlicker() { if (_targetModule != null) { _targetModule.StopCutTextFlicker(); } } public void StopCutting() { isCuttingMode = false; isEntranceComplete = false; isGearActive = false; if (_targetModule != null) { _targetModule.StopCutTextFlicker(); } if (entrancePanel != null) { // 获取当前相机位置 Vector3 startPosition = GetPanelSpawnPosition(); // 执行退场动画 entrancePanel.transform.DOMove(startPosition, exitDuration) .SetEase(Ease.InBack) .OnComplete(() => { Destroy(entrancePanel); entrancePanel = null; gearFollower = null; }); } else if (gearFollower != null) { Destroy(gearFollower.gameObject); gearFollower = null; } } } }