using System; using System.Collections; using System.Collections.Generic; using System.Linq; using AibisDream.Framework; using Cinemachine; using JetBrains.Annotations; using UnityEngine; namespace AibisDream.FixSystem { public class BodyModuleSystem : MonoBehaviour { #region 内部索引 public List BodyModules { get; private set; } private GameObject _bodyModuleGroup; private GameObject _headModuleGroup; public CableSystem CableSystem { get; private set; } [HideInInspector] public HeatMapController heatMapController; #endregion #region 系统状态 private readonly ModuleSystemData _data = new(); public bool inHotErr; private int _heatValue; public bool isAvailable; private int HeatValue { get => _heatValue; set { _heatValue = value; inHotErr = _heatValue > 0; } } #endregion [SerializeField] public float plugSnappingRange = 1f; private Vector3 _headModuleOriginalPos; private Coroutine _breathingCoroutine; private Coroutine _painShakeCoroutine; private Coroutine _continuousPainCoroutine; private void Awake() { InitComponentRefs(); } private void InitComponentRefs() { // 注册数据 StorageSystem.Instance.RegisterData(_data); // 处理内部索引 _bodyModuleGroup = transform.Find("Body Module Group")?.gameObject; _headModuleGroup = transform.Find("Head Module Group")?.gameObject; CableSystem = transform.Find("Cable System").GetComponent(); if (transform.Find("HeatMapController")) { heatMapController = transform.Find("HeatMapController").GetComponent(); } FixSystemCenter.SystemDic.Register(this); // 注册Camera var virtualCam = transform.Find("Body Module Camera").GetComponent(); CameraKit.Instance.RegisterCamera(CameraEnum.BodyModule, virtualCam); var virtualCam2 = transform.Find("Body Module Camera Center").GetComponent(); CameraKit.Instance.RegisterCamera(CameraEnum.BodyModuleCenter, virtualCam2); } private void OnDestroy() { StorageSystem.Instance.UnregisterData(); CameraKit.Instance.UnRegisterCamera(CameraEnum.BodyModule); } /// /// 寻找最接近的Module /// /// 源位置 /// 最近的Module /// 是否能找到目标范围内的Module public bool TryFindClosestModule(Vector3 sourcePos, out BodyModule targetModule) { var closestDistance = Mathf.Infinity; BodyModule closestModule = null; if (BodyModules is not { Count: > 0 }) { targetModule = null; return false; } // 寻找最接近的BodyModule foreach (var bodyModule in BodyModules) { if (!bodyModule.IsAvailable()) // 检查模块是否可用 { continue; // 跳过不可用的模块 } float tempDistance = Vector3.Distance(sourcePos, bodyModule.GetSocketPos()); if (tempDistance < closestDistance) { closestDistance = tempDistance; closestModule = bodyModule; } } bool res; // 判断距离是否在目标范围内,在的话就返回,不在的话返回个空的 if (closestDistance < plugSnappingRange && closestModule) { targetModule = closestModule; res = true; } else { targetModule = null; res = false; } return res; } public void OpenModuleSlots() { foreach (var module in BodyModules) { module.OpenPlugSlot(); } } public void CloseModuleSlots([CanBeNull] BodyModule curModule) { if (BodyModules == null || BodyModules.Count == 0) return; foreach (var module in BodyModules) { if (module != curModule) { module.ClosePlugSlot(); } } } /// /// 寻找指定名称的BodyModule /// /// 模块名称 /// 对应名称的BodyModule public BodyModule FindBodyModuleByName(string modulename) { return BodyModules?.FirstOrDefault(module => module.data.moduleName == modulename); } /// /// 设置发热 /// public void SetHeat(int targetHeatValue) { HeatValue = targetHeatValue; heatMapController.SetTemptureDirect(HeatValue); } public void ShowHeatMap() { heatMapController.ShowHeatMap(); DisableSystem(); ResetPlug(); } public void HideHeatMap() { heatMapController.HideHeatMap(); EnableSystem(); } /// /// 冷却后处理 /// public void OnCooling() { if (!inHotErr) return; // 系统冷却 _heatValue = 0; } /// /// 插头重新插入初始插孔 /// public void ResetPlug() { CableSystem.ResetPlug(); } /// /// 激活交互系统 /// public void EnableSystem() { isAvailable = true; } /// /// 停止交互系统 /// public void DisableSystem() { isAvailable = false; } public void SwitchModuleGroup(ModuleState moduleState) { // 先切换Group switch (moduleState) { case ModuleState.Body: _bodyModuleGroup?.SetActive(true); _headModuleGroup?.SetActive(false); break; case ModuleState.Head: _bodyModuleGroup?.SetActive(false); _headModuleGroup?.SetActive(true); break; default: throw new ArgumentOutOfRangeException(nameof(moduleState), moduleState, null); } // 重新获取ModuleGroup var root = moduleState == ModuleState.Body ? _bodyModuleGroup : _headModuleGroup; BodyModules = root?.GetComponentsInChildren().ToList(); // 更改data _data.moduleState = moduleState; } /// /// 从模块中清除 /// /// 将要被移除的模块 public void RemoveModule(BodyModule module) { BodyModules.Remove(module); } private void Start() { if (_headModuleGroup != null) { _headModuleOriginalPos = _headModuleGroup.transform.localPosition; StartBreathing(); } } public void StartBreathing() { if (_breathingCoroutine != null) { StopCoroutine(_breathingCoroutine); } _breathingCoroutine = StartCoroutine(BreathingAnimation()); } public void StopBreathing() { if (_breathingCoroutine != null) { StopCoroutine(_breathingCoroutine); _breathingCoroutine = null; } if (_headModuleGroup != null) { _headModuleGroup.transform.localPosition = _headModuleOriginalPos; } } private IEnumerator BreathingAnimation() { float time = 0; while (true) { time += Time.deltaTime; float yOffset = Mathf.Sin(time * 2f) * 0.02f; // 调整呼吸幅度和速度 _headModuleGroup.transform.localPosition = _headModuleOriginalPos + new Vector3(0, yOffset, 0); yield return null; } // ReSharper disable once IteratorNeverReturns } public void TriggerPainShake() { if (_painShakeCoroutine != null) { StopCoroutine(_painShakeCoroutine); } _painShakeCoroutine = StartCoroutine(PainShakeAnimation()); } private IEnumerator PainShakeAnimation() { StopBreathing(); float duration = 0.5f; float elapsed = 0f; Vector3 originalPos = _headModuleGroup.transform.localPosition; while (elapsed < duration) { elapsed += Time.deltaTime; float intensity = 1f - (elapsed / duration); _headModuleGroup.transform.localPosition = originalPos + new Vector3( UnityEngine.Random.Range(-0.1f, 0.1f) * intensity, UnityEngine.Random.Range(-0.1f, 0.1f) * intensity, UnityEngine.Random.Range(-0.1f, 0.1f) * intensity ); yield return null; } _headModuleGroup.transform.localPosition = originalPos; StartBreathing(); } public void StartContinuousPain() { if (_continuousPainCoroutine != null) { StopCoroutine(_continuousPainCoroutine); } _continuousPainCoroutine = StartCoroutine(ContinuousPainAnimation()); } public void StopContinuousPain() { if (_continuousPainCoroutine != null) { StopCoroutine(_continuousPainCoroutine); _continuousPainCoroutine = null; } if (_headModuleGroup != null) { _headModuleGroup.transform.localPosition = _headModuleOriginalPos; } StartBreathing(); } private IEnumerator ContinuousPainAnimation() { StopBreathing(); while (true) { // 抖动阶段 float shakeDuration = 1f; float shakeElapsed = 0f; Vector3 originalPos = _headModuleGroup.transform.localPosition; while (shakeElapsed < shakeDuration) { shakeElapsed += Time.deltaTime; _headModuleGroup.transform.localPosition = originalPos + new Vector3( UnityEngine.Random.Range(-0.05f, 0.05f), UnityEngine.Random.Range(-0.05f, 0.05f), UnityEngine.Random.Range(-0.05f, 0.05f) ); yield return null; } // 暂停阶段 _headModuleGroup.transform.localPosition = originalPos; yield return new WaitForSeconds(0.5f); } // ReSharper disable once IteratorNeverReturns } } [LoadIndex(2)] public class ModuleSystemData : IData { public ModuleState moduleState; public IEnumerator Load() { FixSystemCenter.SystemDic.Get().SwitchModuleGroup(moduleState); yield break; } } public enum ModuleState { Body, Head } }