448 lines
15 KiB
C#
448 lines
15 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
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;
|
|
|
|
public class MemoryProcess : MonoBehaviour
|
|
{
|
|
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 PunchTape;
|
|
|
|
private MemoryClueSlot clueSlot;
|
|
|
|
public Material fadeMaterial;
|
|
|
|
private Dictionary<PunchTape, bool> processedPunchTapes = new Dictionary<PunchTape, bool>();
|
|
|
|
public void OpenMemoryView()
|
|
{
|
|
memoryView.gameObject.SetActive(true);
|
|
memoryGroup.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();
|
|
clueSlot = FindObjectOfType<MemoryClueSlot>();
|
|
FavoritesManager.Instance.OpenFavorites();
|
|
playBackground.gameObject.SetActive(false);
|
|
playBackground.alpha = 0;
|
|
}
|
|
|
|
public void OnShow()
|
|
{
|
|
Debug.Log("memoryView showed.");
|
|
clueSlot = FindObjectOfType<MemoryClueSlot>();
|
|
FavoritesManager.Instance.OpenFavorites();
|
|
playBackground.gameObject.SetActive(false);
|
|
playBackground.alpha = 0;
|
|
}
|
|
|
|
public void OnExit()
|
|
{
|
|
// 停止拉条音频
|
|
if (isPlayingFaderSound)
|
|
{
|
|
AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
|
|
isPlayingFaderSound = false;
|
|
}
|
|
|
|
FavoritesManager.Instance.CloseFavorites();
|
|
CloseMemoryView();
|
|
// 离开视图时的逻辑
|
|
Debug.Log("MemoryView exited.");
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
InitSystem();
|
|
}
|
|
|
|
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.AddListener(OnFrequencyChanged);
|
|
frequencySlider.gameObject.SetActive(false);
|
|
frequencySlider.value = 3;
|
|
lastFrequencyValue = frequencySlider.value;
|
|
frequencySlider.interactable = true;
|
|
// 添加EventTrigger监听
|
|
var trigger = frequencySlider.gameObject.GetComponent<EventTrigger>() ?? frequencySlider.gameObject.AddComponent<EventTrigger>();
|
|
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.AddListener(OnClarityChanged);
|
|
claritySlider.gameObject.SetActive(false);
|
|
claritySlider.value = 3;
|
|
lastClarityValue = claritySlider.value;
|
|
claritySlider.interactable = true;
|
|
// 添加EventTrigger监听
|
|
var trigger = claritySlider.gameObject.GetComponent<EventTrigger>() ?? claritySlider.gameObject.AddComponent<EventTrigger>();
|
|
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;
|
|
PunchTape = 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);
|
|
|
|
FavoritesManager.Instance.OpenFavorites();
|
|
|
|
// Initialize and release slot
|
|
Init();
|
|
clueSlot.punchTape.used = true;
|
|
clueSlot.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);
|
|
FavoritesManager.Instance.CloseFavorites();
|
|
Sprite memSprite = Resources.Load<Sprite>("Art/Memory/" + memName);
|
|
memoryFinishedspRender.sprite = memSprite;
|
|
memoryFinishedImageNoColor.sprite = memSprite;
|
|
if (memSprite == null)
|
|
{
|
|
Debug.LogError("Memory not found: " + memName);
|
|
}
|
|
|
|
// AudioManager.PlayMemoryAudio("mem_" + memName);
|
|
playBackground.gameObject.SetActive(true);
|
|
//FavoritesManager.Instance.CloseFavorites();
|
|
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
|
|
{
|
|
FavoritesManager.Instance.CloseFavorites();
|
|
// Activate playBackground and fade in alpha from 0 to 1
|
|
// AudioManager.PlayMemoryAudio("mem_" + clueSlot.punchTape.MemoryIndex);
|
|
playBackground.gameObject.SetActive(true);
|
|
//FavoritesManager.Instance.CloseFavorites();
|
|
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;
|
|
DialogController.Instance.StartDialogNode(clueSlot.punchTape.YarnNodeName);
|
|
}
|
|
}
|
|
|
|
[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();
|
|
FavoritesManager.Instance.CloseFavorites();
|
|
//FavoritesManager.Instance.CloseFavorites();
|
|
if (punchTape == null)
|
|
{
|
|
Debug.Log("no punchTape");
|
|
yield break;
|
|
}
|
|
|
|
PunchTape = punchTape;
|
|
|
|
// AudioManager.PauseMemoryAudio();
|
|
if (isProcessing)
|
|
{
|
|
Debug.LogWarning("Already processing a memory. Please wait until the process is finished.");
|
|
yield break;
|
|
}
|
|
|
|
Sprite memorySprite = Resources.Load<Sprite>("Art/Memory/" + PunchTape.MemoryIndex);
|
|
memoryFinishedspRender.sprite = memorySprite;
|
|
memoryFinishedImageNoColor.sprite = memorySprite;
|
|
if (memorySprite == null)
|
|
{
|
|
Debug.LogError("Memory not found: " + PunchTape.MemoryIndex);
|
|
}
|
|
|
|
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()
|
|
{
|
|
// if (!isPlayingFaderSound)
|
|
// {
|
|
// AudioManager.Instance.PlaySfx("event:/ActionFB/mem_fader");
|
|
// isPlayingFaderSound = true;
|
|
// }
|
|
}
|
|
|
|
private void OnFaderPointerUp()
|
|
{
|
|
// if (isPlayingFaderSound)
|
|
// {
|
|
// AudioManager.Instance.StopSfx("event:/ActionFB/mem_fader");
|
|
// isPlayingFaderSound = false;
|
|
// }
|
|
}
|
|
|
|
// private void UpdateFaderSound(float speed)
|
|
// {
|
|
// // 速度归一化,最大速度可根据实际情况调整
|
|
// float normalizedSpeed = Mathf.Clamp01(speed / 10f);
|
|
// AudioManager.Instance.SetSfxParam("event:/ActionFB/mem_fader", "mem_fader_speed", normalizedSpeed);
|
|
// }
|
|
} |