Files
aibis-dream/Assets/Scripts/FixSystem/Memory/MemoryProcess.cs
T

470 lines
18 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using Yarn.Unity;
using AibisDream;
using AibisDream.FixSystem;
using AibisDream.Framework;
using Cinemachine;
using UnityEngine.Rendering;
using AibisDream.Kit;
using UnityEngine.EventSystems;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace AibisDream.FixSystem
{
public class MemoryProcess : MonoBehaviour
{
private const string MemorySpritePath = "Sprite/Memory/{0}.png";
public BubbleSlotGroup bubbleSlotGroup;
public GameObject memoryView;
public GameObject projector;
public SpriteRenderer memoryFinishedspRender; // 用于显示记忆处理结束的表现
public SpriteRenderer memoryFinishedImageNoColor; // 用于显示记忆处理结束的表现
[SerializeField] private Volume MainEffect;
[SerializeField] private Volume MemoryClarityVloume;
[SerializeField] private Volume Memoryfrequencyloume;
[SerializeField] private Volume MemoryProcessVloume;
public Slider frequencySlider; // 频率调节滑动条
public Slider claritySlider; // 频率调节滑动条
public CanvasGroup playBackground;
public float targetFrequency = 1.25f; // 目标频率
public float targetClarity = 5.7f; // 目标频率
private GameObject memoryGroup;
private float lockThreshold = 0.06f; // 锁定阈值
private bool isProcessing = false; // 新增变量来追踪是否正在处理记忆
private FMOD.Studio.EventInstance faderSoundInstance; // 添加音效实例变量
private bool isPlayingFaderSound = false; // 追踪音效是否正在播放
private float lastFrequencyValue; // 记录上一帧的频率值
private float lastClarityValue; // 记录上一帧的清晰度值
private bool isColorful = false; //
private bool isFrequencyFound = false; // 追踪是否找到目标频率
private bool isClarityFound = false; // 追踪是否找到目标清晰度
private Material memoryMaterial; // 噪波材质
private PunchTape _activePunchTape;
[SerializeField] private MemoryPunchTapeSlot punchTapeSlot;
public Material fadeMaterial;
public void OpenMemoryView()
{
memoryGroup.SetActive(true);
memoryView.gameObject.SetActive(true);
}
public IEnumerator DropMemoryProjector()
{
DG.Tweening.Sequence zoomInSequence = DOTween.Sequence();
zoomInSequence.Append(projector.transform.DOLocalMoveY(-5, 2f).SetEase(Ease.OutElastic, 0.5f));
yield return zoomInSequence.WaitForCompletion();
}
public void PullMemoryProjector()
{
DG.Tweening.Sequence zoomOutSequence = DOTween.Sequence();
zoomOutSequence.Append(projector.transform.DOLocalMoveY(0, 2f).SetEase(Ease.OutElastic, 0.5f));
//yield return zoomOutSequence.WaitForCompletion();
}
public void CloseMemoryView()
{
memoryView.gameObject.SetActive(false);
memoryGroup.SetActive(false);
}
public void OnEnter()
{
OpenMemoryView();
EnsurePunchTapeSlotReference();
PunchTapeManager.Instance.OpenFavoritesPanel();
playBackground.gameObject.SetActive(false);
playBackground.alpha = 0;
}
public void OnShow()
{
Debug.Log("memoryView showed.");
EnsurePunchTapeSlotReference();
PunchTapeManager.Instance.OpenFavoritesPanel();
playBackground.gameObject.SetActive(false);
playBackground.alpha = 0;
}
public void OnExit()
{
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
PunchTapeManager.Instance.CloseFavoritesPanel();
CloseMemoryView();
// 离开视图时的逻辑
Debug.Log("MemoryView exited.");
}
private void Awake()
{
InitSystem();
}
private void EnsurePunchTapeSlotReference()
{
if (punchTapeSlot != null) return;
punchTapeSlot = MemoryPunchTapeSlot.ActiveInstance;
if (punchTapeSlot == null)
{
Debug.LogWarning(
"[MemoryProcess] 未配置 MemoryPunchTapeSlot:请在 Inspector 将 punchTapeSlot 赋值为场景中的插槽,或确保存在 MemoryPunchTapeSlot。",
this);
}
}
private void InitSystem()
{
FixSystemCenter.SystemDic.Register(this);
memoryGroup = transform.Find("Memory Group").gameObject;
memoryGroup.SetActive(false);
var virtualCam = transform.Find("Memory Camera").GetComponent<ICinemachineCamera>();
CameraKit.Instance.RegisterCamera(CameraEnum.Memory, virtualCam);
}
private void Start()
{
Init();
}
float GetRandomNumber()
{
// 随机决定选择哪个区间
if (UnityEngine.Random.value < 0.5f) // 50% 概率选择第一个区间
{
return UnityEngine.Random.Range(0.5f, 2f);
}
else // 50% 概率选择第二个区间
{
return UnityEngine.Random.Range(4f, 5.5f);
}
}
void OnFrequencyChanged(float value)
{
float distance = Mathf.Abs(value - targetFrequency);
float maxDistance = Mathf.Max(
Mathf.Abs(frequencySlider.maxValue - targetFrequency),
Mathf.Abs(frequencySlider.minValue - targetFrequency)
);
float t = Mathf.Clamp01(distance / maxDistance);
UpdateFrequencyShaderParameters(t);
CheckIfFound(t, ref isFrequencyFound);
// 控制音效 - 使用更平滑的速度计算
float currentSpeed = Mathf.Abs(value - lastFrequencyValue) / Time.deltaTime;
lastFrequencyValue = value;
// UpdateFaderSound(currentSpeed);
}
void OnClarityChanged(float value)
{
float distance = Mathf.Abs(value - targetClarity);
float maxDistance = Mathf.Max(
Mathf.Abs(claritySlider.maxValue - targetClarity),
Mathf.Abs(claritySlider.minValue - targetClarity)
);
float t = Mathf.Clamp01(distance / maxDistance);
UpdateClarityShaderParameters(t);
CheckIfFound(t, ref isClarityFound);
// 控制音效 - 使用更平滑的速度计算
float currentSpeed = Mathf.Abs(value - lastClarityValue) / Time.deltaTime;
lastClarityValue = value;
// UpdateFaderSound(currentSpeed);
}
void OnSearchComplete()
{
Debug.Log("Memory search completed.");
frequencySlider.interactable = false;
claritySlider.interactable = false;
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
AudioManager.Instance.SetSfxParam("event:/Amb/amb_mem_tuning", "is_mem_tuning", 0);
StartCoroutine(PlayMemory());
}
void CheckIfFound(float distance, ref bool isFound)
{
if (distance < lockThreshold)
{
isFound = true;
// 检查是否两个条件都满足
if (isFrequencyFound && isClarityFound)
{
OnSearchComplete(); // 一旦条件满足,调用完成处理
}
}
else
{
isFound = false;
}
}
void UpdateFrequencyShaderParameters(float distance)
{
Memoryfrequencyloume.weight = Mathf.Lerp(0, 1, distance);
}
void UpdateClarityShaderParameters(float t)
{
MemoryClarityVloume.weight = Mathf.Lerp(0, 1, t);
}
public void TweenWeight(Volume postProcessingVolume, float targetWeight, float duration)
{
// 动态调整权重
DOTween.To(() => postProcessingVolume.weight, x => postProcessingVolume.weight = x, targetWeight, duration);
}
public void Init()
{
isFrequencyFound = false;
isClarityFound = false;
isProcessing = false;
// 停止拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
if (frequencySlider != null)
{
frequencySlider.onValueChanged.RemoveAllListeners();
frequencySlider.onValueChanged.AddListener(OnFrequencyChanged);
frequencySlider.gameObject.SetActive(false);
frequencySlider.value = 3;
lastFrequencyValue = frequencySlider.value;
frequencySlider.interactable = true;
// 添加EventTrigger监听(避免 Init 重复调用时叠加)
var trigger = frequencySlider.gameObject.GetComponent<EventTrigger>() ?? frequencySlider.gameObject.AddComponent<EventTrigger>();
trigger.triggers.Clear();
var entryDown = new EventTrigger.Entry { eventID = EventTriggerType.PointerDown };
entryDown.callback.AddListener((data) => OnFaderPointerDown());
trigger.triggers.Add(entryDown);
var entryUp = new EventTrigger.Entry { eventID = EventTriggerType.PointerUp };
entryUp.callback.AddListener((data) => OnFaderPointerUp());
trigger.triggers.Add(entryUp);
}
if (claritySlider != null)
{
claritySlider.onValueChanged.RemoveAllListeners();
claritySlider.onValueChanged.AddListener(OnClarityChanged);
claritySlider.gameObject.SetActive(false);
claritySlider.value = 3;
lastClarityValue = claritySlider.value;
claritySlider.interactable = true;
var trigger = claritySlider.gameObject.GetComponent<EventTrigger>() ?? claritySlider.gameObject.AddComponent<EventTrigger>();
trigger.triggers.Clear();
var entryDown = new EventTrigger.Entry { eventID = EventTriggerType.PointerDown };
entryDown.callback.AddListener((data) => OnFaderPointerDown());
trigger.triggers.Add(entryDown);
var entryUp = new EventTrigger.Entry { eventID = EventTriggerType.PointerUp };
entryUp.callback.AddListener((data) => OnFaderPointerUp());
trigger.triggers.Add(entryUp);
}
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15f);
memoryFinishedspRender.color = Color.black;
MemoryProcessVloume.weight = 0;
MemoryClarityVloume.weight = 0;
Memoryfrequencyloume.weight = 0;
_activePunchTape = null;
playBackground.gameObject.SetActive(false);
playBackground.alpha = 0;
}
[YarnCommand("MemoryFinished")]
public IEnumerator MemoryFinished()
{
// AudioManager.PauseMemoryAudio();
// Fade out alpha from 1 to 0
yield return playBackground.DOFade(0f, 1f).WaitForCompletion(); // Fade to fully transparent over 1 second
// Deactivate playBackground after fade out
playBackground.gameObject.SetActive(false);
PunchTapeManager.Instance.OpenFavoritesPanel();
// Initialize and release slot
Init();
EnsurePunchTapeSlotReference();
if (punchTapeSlot != null && punchTapeSlot.punchTape != null)
{
punchTapeSlot.punchTape.used = true;
punchTapeSlot.ReleaseSlot();
}
}
[YarnCommand("ColorFadeOut")]
public IEnumerator ColorFadeOut()
{
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15f);
// AudioManager.PauseMemoryAudio();
Tween tween = fadeMaterial.DOFloat(0, "_DirectionalDistortionFade", 3);
yield return tween.WaitForCompletion();
}
[YarnCommand("PlayMemory")]
public IEnumerator PlayMemory(bool useYarn = false, string memName = "")
{
memoryFinishedspRender.color = Color.white;
if (useYarn)
{
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15);
PunchTapeManager.Instance.CloseFavoritesPanel();
var memoryKey = string.Format(MemorySpritePath, memName);
var memoryHandle = ResourceSystem.LoadAsync<Sprite>(memoryKey);
yield return memoryHandle;
Sprite memSprite = memoryHandle.Status == AsyncOperationStatus.Succeeded ? memoryHandle.Result : null;
memoryFinishedspRender.sprite = memSprite;
memoryFinishedImageNoColor.sprite = memSprite;
if (memSprite == null)
{
Debug.LogError("Memory not found: " + memoryKey);
}
// AudioManager.PlayMemoryAudio("mem_" + memName);
playBackground.gameObject.SetActive(true);
//PunchTapeManager.Instance.CloseFavoritesPanel();
playBackground.alpha = 0;
AudioManager.Instance.PlaySfx("event:/ActionFB/mem_play");
yield return playBackground.DOFade(1f, 1f).WaitForCompletion(); // Fade to fully opaque over 1 second
MemoryClarityVloume.weight = 0;
Memoryfrequencyloume.weight = 0;
}
else
{
PunchTapeManager.Instance.CloseFavoritesPanel();
// Activate playBackground and fade in alpha from 0 to 1
// AudioManager.PlayMemoryAudio("mem_" + punchTapeSlot.punchTape.MemoryIndex);
playBackground.gameObject.SetActive(true);
//PunchTapeManager.Instance.CloseFavoritesPanel();
playBackground.alpha = 0;
AudioManager.Instance.PlaySfx("event:/ActionFB/mem_play");
yield return playBackground.DOFade(1f, 1f).WaitForCompletion(); // Fade to fully opaque over 1 second
// Set material properties
MemoryClarityVloume.weight = 0;
Memoryfrequencyloume.weight = 0;
EnsurePunchTapeSlotReference();
if (punchTapeSlot == null || punchTapeSlot.punchTape == null)
{
Debug.LogError("[MemoryProcess] PlayMemory:未配置插槽或打孔带数据缺失。", this);
yield break;
}
DialogController.Instance.StartDialogNode(
LocalizationKit.GetL10NParamKey(punchTapeSlot.punchTape.ClueName));
}
}
[YarnCommand("search_memory")]
public IEnumerator SearchMemory(PunchTape punchTape, bool isSkipDialogue = false)
{
// 停止之前的拉条音频
if (isPlayingFaderSound)
{
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
isPlayingFaderSound = false;
}
targetClarity = GetRandomNumber();
targetFrequency = GetRandomNumber();
PunchTapeManager.Instance.CloseFavoritesPanel();
//PunchTapeManager.Instance.CloseFavoritesPanel();
if (punchTape == null)
{
Debug.Log("no punchTape");
yield break;
}
_activePunchTape = punchTape;
// AudioManager.PauseMemoryAudio();
if (isProcessing)
{
Debug.LogWarning("Already processing a memory. Please wait until the process is finished.");
yield break;
}
var searchMemoryKey = string.Format(MemorySpritePath, _activePunchTape.MemoryIndex);
var searchMemoryHandle = ResourceSystem.LoadAsync<Sprite>(searchMemoryKey);
yield return searchMemoryHandle;
Sprite memorySprite = searchMemoryHandle.Status == AsyncOperationStatus.Succeeded
? searchMemoryHandle.Result
: null;
memoryFinishedspRender.sprite = memorySprite;
memoryFinishedImageNoColor.sprite = memorySprite;
if (memorySprite == null)
{
Debug.LogError("Memory not found: " + searchMemoryKey);
}
MemoryProcessVloume.weight = 1;
AudioManager.Instance.PlaySfx("event:/Scriptal/mem_load");
yield return new WaitForSeconds(1f);
AudioManager.Instance.SetSfxParam("event:/Amb/amb_mem_tuning", "is_mem_tuning", 1);
memoryFinishedspRender.color = Color.white;
OnFrequencyChanged(frequencySlider.value);
OnClarityChanged(claritySlider.value);
MemoryProcessVloume.weight = 0;
isProcessing = true; // 开始处理,设置为true
frequencySlider.gameObject.SetActive(true);
claritySlider.gameObject.SetActive(true);
DG.Tweening.Sequence memorySequence = DOTween.Sequence();
yield return memorySequence.WaitForCompletion();
}
public bool IsProcessing()
{
return isProcessing;
}
private void OnFaderPointerDown()
{
}
private void OnFaderPointerUp()
{
}
}
}