refactor(fix-system): 重构 MemoryProcess 并提取 MemorySlider 组件
This commit is contained in:
@@ -1,15 +1,11 @@
|
||||
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
|
||||
@@ -17,46 +13,38 @@ namespace AibisDream.FixSystem
|
||||
public class MemoryProcess : MonoBehaviour
|
||||
{
|
||||
private const string MemorySpritePath = "Sprite/Memory/{0}.png";
|
||||
private const float FadeMaterialStartValue = -15f;
|
||||
private const float DefaultFadeDuration = 1f;
|
||||
private const float SearchStartDelay = 1f;
|
||||
private const float ProjectorMoveDuration = 2f;
|
||||
|
||||
public BubbleSlotGroup bubbleSlotGroup;
|
||||
public GameObject memoryView;
|
||||
public GameObject projector;
|
||||
public SpriteRenderer memoryFinishedspRender; // 用于显示记忆处理结束的表现
|
||||
public SpriteRenderer memoryFinishedImageNoColor; // 用于显示记忆处理结束的表现
|
||||
[SerializeField] private BubbleSlotGroup bubbleSlotGroup;
|
||||
public BubbleSlotGroup BubbleSlotGroup => bubbleSlotGroup;
|
||||
[SerializeField] private GameObject memoryView;
|
||||
[SerializeField] private GameObject projector;
|
||||
[SerializeField] private SpriteRenderer memoryFinishedSpriteRenderer; // 用于显示记忆处理结束的表现
|
||||
[SerializeField] private SpriteRenderer memoryFinishedImageNoColor; // 用于显示记忆处理结束的表现
|
||||
|
||||
[SerializeField] private Volume MainEffect;
|
||||
[SerializeField] private Volume MemoryClarityVloume;
|
||||
[SerializeField] private Volume Memoryfrequencyloume;
|
||||
[SerializeField] private Volume MemoryProcessVloume;
|
||||
public Slider frequencySlider; // 频率调节滑动条
|
||||
[SerializeField] private Volume mainEffect;
|
||||
[SerializeField] private Volume memoryClarityVolume;
|
||||
[SerializeField] private Volume memoryFrequencyVolume;
|
||||
[SerializeField] private Volume memoryProcessVolume;
|
||||
[SerializeField] private MemorySlider frequencySlider; // 频率调节滑动条
|
||||
[SerializeField] private MemorySlider claritySlider; // 清晰度调节滑动条
|
||||
|
||||
public Slider claritySlider; // 频率调节滑动条
|
||||
[SerializeField] private CanvasGroup playBackground;
|
||||
|
||||
public CanvasGroup playBackground;
|
||||
public float targetFrequency = 1.25f; // 目标频率
|
||||
|
||||
public float targetClarity = 5.7f; // 目标频率
|
||||
|
||||
private GameObject memoryGroup;
|
||||
private float lockThreshold = 0.06f; // 锁定阈值
|
||||
[SerializeField] private GameObject memoryGroup;
|
||||
[SerializeField] private CinemachineVirtualCamera memoryCamera;
|
||||
|
||||
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;
|
||||
[SerializeField] private Material fadeMaterial;
|
||||
|
||||
public void OpenMemoryView()
|
||||
{
|
||||
@@ -68,15 +56,14 @@ namespace AibisDream.FixSystem
|
||||
public IEnumerator DropMemoryProjector()
|
||||
{
|
||||
DG.Tweening.Sequence zoomInSequence = DOTween.Sequence();
|
||||
zoomInSequence.Append(projector.transform.DOLocalMoveY(-5, 2f).SetEase(Ease.OutElastic, 0.5f));
|
||||
zoomInSequence.Append(projector.transform.DOLocalMoveY(-5, ProjectorMoveDuration).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();
|
||||
zoomOutSequence.Append(projector.transform.DOLocalMoveY(0, ProjectorMoveDuration).SetEase(Ease.OutElastic, 0.5f));
|
||||
}
|
||||
|
||||
public void CloseMemoryView()
|
||||
@@ -88,15 +75,17 @@ namespace AibisDream.FixSystem
|
||||
public void OnEnter()
|
||||
{
|
||||
OpenMemoryView();
|
||||
EnsurePunchTapeSlotReference();
|
||||
PunchTapeManager.Instance.OpenFavoritesPanel();
|
||||
playBackground.gameObject.SetActive(false);
|
||||
playBackground.alpha = 0;
|
||||
PrepareMemoryView();
|
||||
}
|
||||
|
||||
public void OnShow()
|
||||
{
|
||||
Debug.Log("memoryView showed.");
|
||||
PrepareMemoryView();
|
||||
}
|
||||
|
||||
private void PrepareMemoryView()
|
||||
{
|
||||
EnsurePunchTapeSlotReference();
|
||||
PunchTapeManager.Instance.OpenFavoritesPanel();
|
||||
playBackground.gameObject.SetActive(false);
|
||||
@@ -116,6 +105,9 @@ namespace AibisDream.FixSystem
|
||||
CloseMemoryView();
|
||||
// 离开视图时的逻辑
|
||||
Debug.Log("MemoryView exited.");
|
||||
|
||||
if (frequencySlider != null) frequencySlider.LockSlider();
|
||||
if (claritySlider != null) claritySlider.LockSlider();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
@@ -138,19 +130,27 @@ namespace AibisDream.FixSystem
|
||||
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);
|
||||
if (memoryGroup != null)
|
||||
memoryGroup.SetActive(false);
|
||||
if (memoryCamera != null)
|
||||
CameraKit.Instance.RegisterCamera(CameraEnum.Memory, memoryCamera);
|
||||
}
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
frequencySlider.OnFound += CheckAllFound;
|
||||
claritySlider.OnFound += CheckAllFound;
|
||||
Init();
|
||||
}
|
||||
|
||||
float GetRandomNumber()
|
||||
private void CheckAllFound()
|
||||
{
|
||||
if (frequencySlider.IsFound && claritySlider.IsFound)
|
||||
OnSearchComplete();
|
||||
}
|
||||
|
||||
private float GetRandomNumber()
|
||||
{
|
||||
// 随机决定选择哪个区间
|
||||
if (UnityEngine.Random.value < 0.5f) // 50% 概率选择第一个区间
|
||||
@@ -163,46 +163,11 @@ namespace AibisDream.FixSystem
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
private void OnSearchComplete()
|
||||
{
|
||||
Debug.Log("Memory search completed.");
|
||||
frequencySlider.interactable = false;
|
||||
claritySlider.interactable = false;
|
||||
frequencySlider.SetInteractable(false);
|
||||
claritySlider.SetInteractable(false);
|
||||
|
||||
// 停止拉条音频
|
||||
if (isPlayingFaderSound)
|
||||
@@ -215,33 +180,6 @@ namespace AibisDream.FixSystem
|
||||
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)
|
||||
{
|
||||
// 动态调整权重
|
||||
@@ -250,8 +188,6 @@ namespace AibisDream.FixSystem
|
||||
|
||||
public void Init()
|
||||
{
|
||||
isFrequencyFound = false;
|
||||
isClarityFound = false;
|
||||
isProcessing = false;
|
||||
|
||||
// 停止拉条音频
|
||||
@@ -262,47 +198,14 @@ namespace AibisDream.FixSystem
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
frequencySlider.Init(memoryFrequencyVolume);
|
||||
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);
|
||||
}
|
||||
claritySlider.Init(memoryClarityVolume);
|
||||
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15f);
|
||||
memoryFinishedspRender.color = Color.black;
|
||||
MemoryProcessVloume.weight = 0;
|
||||
MemoryClarityVloume.weight = 0;
|
||||
Memoryfrequencyloume.weight = 0;
|
||||
if (fadeMaterial != null)
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
|
||||
memoryFinishedSpriteRenderer.color = Color.black;
|
||||
memoryProcessVolume.weight = 0;
|
||||
_activePunchTape = null;
|
||||
|
||||
playBackground.gameObject.SetActive(false);
|
||||
@@ -312,16 +215,12 @@ namespace AibisDream.FixSystem
|
||||
[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
|
||||
yield return playBackground.DOFade(0f, DefaultFadeDuration).WaitForCompletion();
|
||||
|
||||
// Deactivate playBackground after fade out
|
||||
playBackground.gameObject.SetActive(false);
|
||||
|
||||
PunchTapeManager.Instance.OpenFavoritesPanel();
|
||||
|
||||
// Initialize and release slot
|
||||
Init();
|
||||
EnsurePunchTapeSlotReference();
|
||||
if (punchTapeSlot != null && punchTapeSlot.punchTape != null)
|
||||
@@ -334,8 +233,9 @@ namespace AibisDream.FixSystem
|
||||
[YarnCommand("ColorFadeOut")]
|
||||
public IEnumerator ColorFadeOut()
|
||||
{
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15f);
|
||||
// AudioManager.PauseMemoryAudio();
|
||||
if (fadeMaterial == null) yield break;
|
||||
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
|
||||
Tween tween = fadeMaterial.DOFloat(0, "_DirectionalDistortionFade", 3);
|
||||
yield return tween.WaitForCompletion();
|
||||
}
|
||||
@@ -343,51 +243,41 @@ namespace AibisDream.FixSystem
|
||||
[YarnCommand("PlayMemory")]
|
||||
public IEnumerator PlayMemory(bool useYarn = false, string memName = "")
|
||||
{
|
||||
memoryFinishedspRender.color = Color.white;
|
||||
memoryFinishedSpriteRenderer.color = Color.white;
|
||||
PunchTapeManager.Instance.CloseFavoritesPanel();
|
||||
|
||||
if (useYarn)
|
||||
{
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", -15);
|
||||
PunchTapeManager.Instance.CloseFavoritesPanel();
|
||||
if (fadeMaterial != null)
|
||||
fadeMaterial.SetFloat("_DirectionalDistortionFade", FadeMaterialStartValue);
|
||||
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;
|
||||
memoryFinishedSpriteRenderer.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;
|
||||
}
|
||||
}
|
||||
|
||||
playBackground.gameObject.SetActive(true);
|
||||
playBackground.alpha = 0;
|
||||
AudioManager.Instance.PlaySfx("event:/ActionFB/mem_play");
|
||||
yield return playBackground.DOFade(1f, DefaultFadeDuration).WaitForCompletion();
|
||||
|
||||
if (!useYarn)
|
||||
{
|
||||
DialogController.Instance.StartDialogNode(
|
||||
LocalizationKit.GetL10NParamKey(punchTapeSlot.punchTape.ClueName));
|
||||
}
|
||||
@@ -396,17 +286,16 @@ namespace AibisDream.FixSystem
|
||||
[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();
|
||||
frequencySlider.TargetValue = GetRandomNumber();
|
||||
claritySlider.TargetValue = GetRandomNumber();
|
||||
PunchTapeManager.Instance.CloseFavoritesPanel();
|
||||
//PunchTapeManager.Instance.CloseFavoritesPanel();
|
||||
|
||||
if (punchTape == null)
|
||||
{
|
||||
Debug.Log("no punchTape");
|
||||
@@ -415,7 +304,6 @@ namespace AibisDream.FixSystem
|
||||
|
||||
_activePunchTape = punchTape;
|
||||
|
||||
// AudioManager.PauseMemoryAudio();
|
||||
if (isProcessing)
|
||||
{
|
||||
Debug.LogWarning("Already processing a memory. Please wait until the process is finished.");
|
||||
@@ -428,29 +316,27 @@ namespace AibisDream.FixSystem
|
||||
Sprite memorySprite = searchMemoryHandle.Status == AsyncOperationStatus.Succeeded
|
||||
? searchMemoryHandle.Result
|
||||
: null;
|
||||
memoryFinishedspRender.sprite = memorySprite;
|
||||
memoryFinishedSpriteRenderer.sprite = memorySprite;
|
||||
memoryFinishedImageNoColor.sprite = memorySprite;
|
||||
if (memorySprite == null)
|
||||
{
|
||||
Debug.LogError("Memory not found: " + searchMemoryKey);
|
||||
}
|
||||
|
||||
MemoryProcessVloume.weight = 1;
|
||||
memoryProcessVolume.weight = 1;
|
||||
AudioManager.Instance.PlaySfx("event:/Scriptal/mem_load");
|
||||
|
||||
yield return new WaitForSeconds(1f);
|
||||
yield return new WaitForSeconds(SearchStartDelay);
|
||||
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();
|
||||
memoryFinishedSpriteRenderer.color = Color.white;
|
||||
memoryProcessVolume.weight = 0;
|
||||
isProcessing = true;
|
||||
bool freqUnlocked = false;
|
||||
bool clarityUnlocked = false;
|
||||
frequencySlider.UnlockSlider(() => freqUnlocked = true);
|
||||
claritySlider.UnlockSlider(() => clarityUnlocked = true);
|
||||
yield return new WaitUntil(() => freqUnlocked && clarityUnlocked);
|
||||
}
|
||||
|
||||
|
||||
@@ -458,13 +344,5 @@ namespace AibisDream.FixSystem
|
||||
{
|
||||
return isProcessing;
|
||||
}
|
||||
|
||||
private void OnFaderPointerDown()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnFaderPointerUp()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace AibisDream.FixSystem
|
||||
{
|
||||
[RequireComponent(typeof(Slider))]
|
||||
public class MemorySlider : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float defaultValue = 0f;
|
||||
[SerializeField] private float sliderMaxValue = 6f;
|
||||
[SerializeField] private float lockThreshold = 0.06f;
|
||||
[SerializeField] private TimelineAsset openAsset;
|
||||
[SerializeField] private TimelineAsset closeAsset;
|
||||
|
||||
private Slider slider;
|
||||
private PlayableDirector playableDirector;
|
||||
private Volume _volume;
|
||||
private bool isLocked;
|
||||
|
||||
public float TargetValue { get; set; }
|
||||
public bool IsFound { get; private set; }
|
||||
|
||||
public event Action OnFound;
|
||||
public event Action OnLost;
|
||||
|
||||
public void Init(Volume volume)
|
||||
{
|
||||
slider = GetComponent<Slider>();
|
||||
playableDirector = GetComponent<PlayableDirector>();
|
||||
|
||||
_volume = volume;
|
||||
IsFound = false;
|
||||
slider.onValueChanged.RemoveAllListeners();
|
||||
slider.onValueChanged.AddListener(HandleValueChanged);
|
||||
slider.maxValue = sliderMaxValue;
|
||||
slider.value = defaultValue;
|
||||
UpdateVolumeWeight(slider.value);
|
||||
|
||||
isLocked = true;
|
||||
slider.interactable = false;
|
||||
}
|
||||
|
||||
public void SetInteractable(bool interactable) => slider.interactable = interactable;
|
||||
|
||||
public void UnlockSlider(Action onComplete = null)
|
||||
{
|
||||
if (!isLocked)
|
||||
{
|
||||
onComplete?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
PlayTimeline(openAsset, () =>
|
||||
{
|
||||
slider.interactable = true;
|
||||
isLocked = false;
|
||||
onComplete?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
public void LockSlider(Action onComplete = null)
|
||||
{
|
||||
if (isLocked)
|
||||
{
|
||||
onComplete?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
slider.value = 0f;
|
||||
UpdateVolumeWeight(0f);
|
||||
|
||||
PlayTimeline(closeAsset, () =>
|
||||
{
|
||||
slider.interactable = false;
|
||||
isLocked = true;
|
||||
onComplete?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
private void HandleValueChanged(float value)
|
||||
{
|
||||
float t = UpdateVolumeWeight(value);
|
||||
|
||||
bool wasFound = IsFound;
|
||||
IsFound = t < lockThreshold;
|
||||
|
||||
if (IsFound && !wasFound)
|
||||
OnFound?.Invoke();
|
||||
else if (!IsFound && wasFound)
|
||||
OnLost?.Invoke();
|
||||
}
|
||||
|
||||
private float UpdateVolumeWeight(float value)
|
||||
{
|
||||
float distance = Mathf.Abs(value - TargetValue);
|
||||
float maxDistance = Mathf.Max(
|
||||
Mathf.Abs(slider.maxValue - TargetValue),
|
||||
Mathf.Abs(slider.minValue - TargetValue)
|
||||
);
|
||||
float t = Mathf.Clamp01(distance / maxDistance);
|
||||
|
||||
if (_volume != null)
|
||||
_volume.weight = Mathf.Lerp(0, 1, t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private void PlayTimeline(TimelineAsset asset, Action onComplete)
|
||||
{
|
||||
if (asset == null || playableDirector == null)
|
||||
{
|
||||
onComplete?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
playableDirector.Stop();
|
||||
playableDirector.playableAsset = asset;
|
||||
playableDirector.time = 0;
|
||||
playableDirector.extrapolationMode = DirectorWrapMode.None;
|
||||
|
||||
Action<PlayableDirector> callback = null;
|
||||
callback = pd =>
|
||||
{
|
||||
playableDirector.stopped -= callback;
|
||||
onComplete?.Invoke();
|
||||
};
|
||||
playableDirector.stopped += callback;
|
||||
playableDirector.Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3538641e32b03b44f9824058d4275a73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user