存档功能

This commit is contained in:
2025-01-08 11:41:20 +08:00
parent c67366664c
commit 43b99f98e7
49 changed files with 2498 additions and 5762 deletions
@@ -5,7 +5,6 @@ using AibisDream.Kit;
using UnityEngine;
using UnityEngine.Events;
using Yarn.Unity;
using DG.Tweening;
namespace AibisDream
{
@@ -69,14 +68,6 @@ namespace AibisDream
OnDialogueComplete?.Invoke();
IsTalking = false;
});
//dialogueRunner.AddCommandListener(_ => { IsTalking = false; });
// 对话结束时切下一个SO
dialogueRunner.onDialogueComplete.AddListener(() =>
{
// DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.Bubble);
// StartCoroutine(GameLoopManager.Instance.NextSceneSo());
});
}
#region
@@ -278,12 +269,6 @@ namespace AibisDream
MainUIController.Instance.SwitchTV(picName);
}
[YarnCommand("indoor")]
public static void Indoor(float duration = 1)
{
MainUIController.Instance.TVFadeOut(duration);
}
[YarnCommand("show_tv_scene")]
public static void ShowTVScene(float duration)
{
@@ -340,35 +325,6 @@ namespace AibisDream
return MainUIController.Instance.HideObj();
}
[YarnCommand("move_to_fix")]
public static IEnumerator MoveToFix()
{
bool isCompleted = false;
Sequence s = DOTween.Sequence();
s.Append(Camera.main.transform.DOMove(new UnityEngine.Vector3(6.8f, 0, -10), 2f))
.OnComplete(() =>
{
// 动画完成后的反馈操作
Debug.Log("Move_to_fix sequence completed.");
isCompleted = true;
});
// 等待动画完成
yield return new WaitUntil(() => isCompleted);
// 动画完成后的其他操作
Debug.Log("Continuing after Move_to_fix sequence.");
}
[YarnCommand("move_out_fix")]
public static void MoveOutFix()
{
Camera.main.transform.position = new UnityEngine.Vector3(6.8f, 0, -10);
Sequence s = DOTween.Sequence();
//s.AppendInterval(0.5f);
s.Append(Camera.main.transform.DOMove(new UnityEngine.Vector3(0, 0, -10), 2f));
}
[YarnCommand("switch_dialog_view")]
public static void SwitchDialogView(string viewName)
{
-8
View File
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 204d7deedfa30dc41a72ca0fcc7f83cc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,143 +0,0 @@
using UnityEngine;
using Yarn.Unity;
using System;
using System.Collections;
using AibisDream;
using System.Linq;
using UnityEngine.UI;
using DG.Tweening;
public class BookManager : MonoBehaviour
{
public Book book; // Reference to the book script
private AutoFlip flipmanager;
public Button CloseBookButton;
public Button OepnBookButton;
private RectTransform bookPos;
public event Action OnBookClosed;
public event Action OnBookOpen;
void Start()
{
CloseBookButton.onClick.RemoveAllListeners(); // 确保不会重复绑定
CloseBookButton.onClick.AddListener(() =>
{
// 仅关闭书本,不执行额外操作
CloseBook();
});
OepnBookButton.onClick.RemoveAllListeners(); // 确保不会重复绑定
OepnBookButton.onClick.AddListener(() =>
{
// 打开书本
ButtonOpenBook();
});
DialogController.Instance.RegisterOptionCommand("listen_closeBook", CombineCloseBook);
flipmanager = book.gameObject.GetComponent<AutoFlip>();
bookPos = book.gameObject.GetComponent<RectTransform>();
// Initially, the book is closed
if(book.gameObject.activeInHierarchy)
{
CloseBook();
}
}
// Open the book and flip to a specific page
public void CombineCloseBook(YarnOption[] options)
{
var optionDic = options.ToDictionary(item => item.Text, item => item);
Debug.Log("Option dictionary keys: " + string.Join(", ", optionDic.Keys));
if (optionDic.ContainsKey("CloseBook"))
{
// 监听书关闭事件
OnBookClosed -= TriggerCloseBookOption; // 避免重复监听
OnBookClosed += TriggerCloseBookOption;
// 内部方法:当书关闭时触发该选项的逻辑
void TriggerCloseBookOption()
{
optionDic["CloseBook"].SelectOption();
}
}
}
public void ButtonOpenBook()
{
StartCoroutine(OpenBook());
}
[YarnCommand("OpenBook")]
public IEnumerator OpenBook()
{
if(book.gameObject.activeInHierarchy)
{
yield break;
}
AudioManager.RandomPlayInteraction("book");
OnBookOpen?.Invoke();
// 如果书还没有激活,先激活它
if (!book.gameObject.activeInHierarchy)
{
book.gameObject.SetActive(true);
}
// 使用 DoTween 创建一个动画序列
Sequence sequence = DOTween.Sequence();
// 设置初始位置为屏幕外或者其他你想要的位置(根据需求自行设置)
bookPos.anchoredPosition =
new Vector2(bookPos.anchoredPosition.x, -(Screen.height + bookPos.sizeDelta.y) / 2);
// 移动到目标位置
sequence.Append(bookPos.DOAnchorPos(Vector2.zero, 0.5f).SetEase(Ease.OutQuad));
// 等待序列完成
yield return sequence.WaitForCompletion();
}
[YarnCommand("Flip")]
public IEnumerator FlipToPageYarnCommand(int parameters)
{
// Parse the target page from the parameters
int targetPage = parameters;
book.interactable=false;
// Start the FlipToPageCoroutine and wait for it to finish
yield return StartCoroutine(flipmanager.FlipToPageCoroutine(targetPage));
book.interactable=true;
}
// Close the book
public void CloseBook(Action onCloseCallback = null)
{
AudioManager.RandomPlayInteraction("book");
StartCoroutine(CloseBookCoroutine(onCloseCallback));
}
private IEnumerator CloseBookCoroutine(Action onCloseCallback = null)
{
// 使用 DoTween 创建一个动画序列
Sequence sequence = DOTween.Sequence();
// 动画:将 book 移动回初始位置
sequence.Append(bookPos
.DOAnchorPos(
new Vector2(bookPos.anchoredPosition.x, -(Screen.height + bookPos.sizeDelta.y) / 2), 0.5f)
.SetEase(Ease.InQuad));
// 等待动画完成
yield return sequence.WaitForCompletion();
// 动画完成后隐藏 book
book.gameObject.SetActive(false);
OnBookClosed?.Invoke();
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 400c1e67877b4014fa862547c432b0b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,172 +0,0 @@
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Book))]
public class FlipManager : MonoBehaviour
{
public FlipMode Mode;
public float PageFlipTime = 1;
public float TimeBetweenPages = 1;
public float DelayBeforeStarting = 0;
public bool AutoStartFlip = true;
public Book ControledBook;
public int AnimationFramesCount = 40;
bool isFlipping = false;
public bool IsFlipping
{
get { return isFlipping; }
}
// Use this for initialization
void Start()
{
if (!ControledBook)
ControledBook = GetComponent<Book>();
if (AutoStartFlip)
//StartFlipping();
FlipToPage(6);
ControledBook.OnFlip.AddListener(new UnityEngine.Events.UnityAction(PageFlipped));
}
void PageFlipped()
{
isFlipping = false;
}
public void StartFlipping()
{
StartCoroutine(FlipToEnd());
}
public void FlipRightPage()
{
if (isFlipping) return;
if (ControledBook.currentPage >= ControledBook.TotalPageCount) return;
isFlipping = true;
float frameTime = PageFlipTime / AnimationFramesCount;
float xc = (ControledBook.EndBottomRight.x + ControledBook.EndBottomLeft.x) / 2;
float xl = ((ControledBook.EndBottomRight.x - ControledBook.EndBottomLeft.x) / 2) * 0.9f;
//float h = ControledBook.Height * 0.5f;
float h = Mathf.Abs(ControledBook.EndBottomRight.y) * 0.9f;
float dx = (xl) * 2 / AnimationFramesCount;
StartCoroutine(FlipRTL(xc, xl, h, frameTime, dx));
}
public void FlipLeftPage()
{
if (isFlipping) return;
if (ControledBook.currentPage <= 0) return;
isFlipping = true;
float frameTime = PageFlipTime / AnimationFramesCount;
float xc = (ControledBook.EndBottomRight.x + ControledBook.EndBottomLeft.x) / 2;
float xl = ((ControledBook.EndBottomRight.x - ControledBook.EndBottomLeft.x) / 2) * 0.9f;
//float h = ControledBook.Height * 0.5f;
float h = Mathf.Abs(ControledBook.EndBottomRight.y) * 0.9f;
float dx = (xl) * 2 / AnimationFramesCount;
StartCoroutine(FlipLTR(xc, xl, h, frameTime, dx));
}
IEnumerator FlipToEnd()
{
yield return new WaitForSeconds(DelayBeforeStarting);
float frameTime = PageFlipTime / AnimationFramesCount;
float xc = (ControledBook.EndBottomRight.x + ControledBook.EndBottomLeft.x) / 2;
float xl = ((ControledBook.EndBottomRight.x - ControledBook.EndBottomLeft.x) / 2) * 0.9f;
//float h = ControledBook.Height * 0.5f;
float h = Mathf.Abs(ControledBook.EndBottomRight.y) * 0.9f;
//y=-(h/(xl)^2)*(x-xc)^2
// y
// |
// |
// |
//_______________|_________________x
// o|o |
// o | o |
// o | o | h
// o | o |
// o------xc-------o -
// |<--xl-->
// |
// |
float dx = (xl) * 2 / AnimationFramesCount;
switch (Mode)
{
case FlipMode.RightToLeft:
while (ControledBook.currentPage < ControledBook.TotalPageCount)
{
StartCoroutine(FlipRTL(xc, xl, h, frameTime, dx));
yield return new WaitForSeconds(TimeBetweenPages);
}
break;
case FlipMode.LeftToRight:
while (ControledBook.currentPage > 0)
{
StartCoroutine(FlipLTR(xc, xl, h, frameTime, dx));
yield return new WaitForSeconds(TimeBetweenPages);
}
break;
}
}
IEnumerator FlipRTL(float xc, float xl, float h, float frameTime, float dx)
{
float x = xc + xl;
float y = (-h / (xl * xl)) * (x - xc) * (x - xc);
ControledBook.DragRightPageToPoint(new Vector3(x, y, 0));
for (int i = 0; i < AnimationFramesCount; i++)
{
y = (-h / (xl * xl)) * (x - xc) * (x - xc);
ControledBook.UpdateBookRTLToPoint(new Vector3(x, y, 0));
yield return new WaitForSeconds(frameTime);
x -= dx;
}
ControledBook.ReleasePage();
}
IEnumerator FlipLTR(float xc, float xl, float h, float frameTime, float dx)
{
float x = xc - xl;
float y = (-h / (xl * xl)) * (x - xc) * (x - xc);
ControledBook.DragLeftPageToPoint(new Vector3(x, y, 0));
for (int i = 0; i < AnimationFramesCount; i++)
{
y = (-h / (xl * xl)) * (x - xc) * (x - xc);
ControledBook.UpdateBookLTRToPoint(new Vector3(x, y, 0));
yield return new WaitForSeconds(frameTime);
x += dx;
}
ControledBook.ReleasePage();
}
public void FlipToPage(int targetPage)
{
StartCoroutine(FlipToPageCoroutine(targetPage));
}
public IEnumerator FlipToPageCoroutine(int targetPage)
{
int currentPage = ControledBook.currentPage;
if (targetPage % 2 != 0)
{
targetPage++;
}
// Calculate the number of flips needed
int pageDifference = Mathf.Abs(targetPage - currentPage) / 2;
// Determine the direction to flip
if (targetPage > currentPage)
{
for (int i = 0; i < pageDifference; i++)
{
FlipRightPage();
yield return new WaitUntil(() => !isFlipping);
}
}
else if (targetPage < currentPage)
{
for (int i = 0; i < pageDifference; i++)
{
FlipLeftPage();
yield return new WaitUntil(() => !isFlipping);
}
}
}
}
@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8bf187ebf600021479fd43ecfe56b42d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -15,7 +15,9 @@ public class MouseFollowAndZoom : MonoBehaviour
public float zoomDuration = 1.0f; // 缩放持续时间(减慢)
public Vector2 sceneBoundsMin; // 场景边界的左下角
public Vector2 sceneBoundsMax; // 场景边界的右上角
public Camera viewCamera;
//private Camera MainCamera;
private Vector3 initialPosition;
private Vector3 zoomedInPosition; // 保存缩放时的相机位置
@@ -23,11 +25,11 @@ public class MouseFollowAndZoom : MonoBehaviour
private EyeSystem eyemanager;
private EyeTarget currentTarget; // 当前目标
private float viewOffset=40.3f;
private float viewOffset = 40.3f;
private bool isActive=false;
private bool isActive = false;
private bool isLocked=false;
private bool isLocked = false;
// 只读访问
public bool GetMyPrivateVariable()
@@ -40,6 +42,7 @@ public class MouseFollowAndZoom : MonoBehaviour
{
isActive = value;
}
public void SetIsLock(bool value)
{
isLocked = value;
@@ -48,10 +51,9 @@ public class MouseFollowAndZoom : MonoBehaviour
void Start()
{
//MainCamera = Camera.main;
initialPosition = transform.position;
targetIndicator.SetActive(false); // 初始时隐藏目标框
eyemanager=FindObjectOfType<EyeSystem>();
eyemanager = FindObjectOfType<EyeSystem>();
if (eyemanager == null)
{
Debug.LogError("EyeManager instance not found in the scene.");
@@ -62,9 +64,9 @@ public class MouseFollowAndZoom : MonoBehaviour
{
if (!isActive)
{
targetIndicator.SetActive(false);
targetIndicator.SetActive(false);
return;
}
}
HandleTargetIndicator(); // 显示指示器
if (isLocked) return;
@@ -72,70 +74,72 @@ public class MouseFollowAndZoom : MonoBehaviour
UpdateCurrentTarget(); // 更新当前目标
}
private Vector3 currentOffset; // 当前的偏移量
private Vector3 currentOffset; // 当前的偏移量
void HandleMouseMovement()
{
// 获取鼠标位置
Vector3 mousePosition = Input.mousePosition;
Vector3 worldMousePosition = viewCamera.ScreenToWorldPoint(mousePosition);
worldMousePosition.z = 0; // 确保 z 为 0
// 计算目标偏移量并反向
Vector3 targetOffset = (viewCamera.transform.position - worldMousePosition) * parallaxEffectMultiplier;
targetOffset.x = Mathf.Clamp(targetOffset.x, -maxOffset.x, maxOffset.x);
targetOffset.y = Mathf.Clamp(targetOffset.y, -maxOffset.y, maxOffset.y);
// 平滑处理偏移量
float smoothFactor = 0.01f; // 平滑系数,值越小平滑效果越强,响应越慢
currentOffset = Vector3.Lerp(currentOffset, targetOffset, smoothFactor);
// 计算目标位置
Vector3 targetPosition = initialPosition + currentOffset;
// 限制目标位置在场景边界范围内
targetPosition.x = Mathf.Clamp(targetPosition.x, sceneBoundsMin.x, sceneBoundsMax.x);
targetPosition.y = Mathf.Clamp(targetPosition.y, sceneBoundsMin.y, sceneBoundsMax.y);
// 使用插值(Lerp)平滑更新位置
float followSpeed = 0.1f; // 跟随速度,值越小延迟越大
Vector3 smoothedPosition = Vector3.Lerp(transform.position, targetPosition, followSpeed);
// 应用平滑后的位置
transform.position = smoothedPosition;
}
void UpdateCurrentTarget()
{
// 获取鼠标位置
Vector3 mousePosition = Input.mousePosition;
mousePosition.x += viewOffset; // 添加偏移量
Vector3 worldPosition = viewCamera.ScreenToWorldPoint(mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPosition, Vector2.zero);
// 检查是否有目标
if (hit.collider != null && hit.collider.CompareTag("EyeTarget"))
void HandleMouseMovement()
{
currentTarget = hit.collider.GetComponent<EyeTarget>(); // 更新当前目标
// 获取鼠标位置
Vector3 mousePosition = Input.mousePosition;
Vector3 worldMousePosition = viewCamera.ScreenToWorldPoint(mousePosition);
worldMousePosition.z = 0; // 确保 z 为 0
// 处理鼠标点击事件
if (Input.GetMouseButtonDown(0))
// 计算目标偏移量并反向
Vector3 targetOffset = (viewCamera.transform.position - worldMousePosition) * parallaxEffectMultiplier;
targetOffset.x = Mathf.Clamp(targetOffset.x, -maxOffset.x, maxOffset.x);
targetOffset.y = Mathf.Clamp(targetOffset.y, -maxOffset.y, maxOffset.y);
// 平滑处理偏移量
float smoothFactor = 0.01f; // 平滑系数,值越小平滑效果越强,响应越慢
currentOffset = Vector3.Lerp(currentOffset, targetOffset, smoothFactor);
// 计算目标位置
Vector3 targetPosition = initialPosition + currentOffset;
// 限制目标位置在场景边界范围内
targetPosition.x = Mathf.Clamp(targetPosition.x, sceneBoundsMin.x, sceneBoundsMax.x);
targetPosition.y = Mathf.Clamp(targetPosition.y, sceneBoundsMin.y, sceneBoundsMax.y);
// 使用插值(Lerp)平滑更新位置
float followSpeed = 0.1f; // 跟随速度,值越小延迟越大
Vector3 smoothedPosition = Vector3.Lerp(transform.position, targetPosition, followSpeed);
// 应用平滑后的位置
transform.position = smoothedPosition;
}
void UpdateCurrentTarget()
{
// 获取鼠标位置
Vector3 mousePosition = Input.mousePosition;
mousePosition.x += viewOffset; // 添加偏移量
Vector3 worldPosition = viewCamera.ScreenToWorldPoint(mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPosition, Vector2.zero);
// 检查是否有目标
if (hit.collider != null && hit.collider.CompareTag("EyeTarget"))
{
Debug.Log("点击目标触发了");
if (currentTarget != null)
currentTarget = hit.collider.GetComponent<EyeTarget>(); // 更新当前目标
// 处理鼠标点击事件
if (Input.GetMouseButtonDown(0))
{
eyemanager.SetTarget(currentTarget); // 设置目标
}
else
{
Debug.LogWarning("The collider does not have an EyeTarget component.");
Debug.Log("点击目标触发了");
if (currentTarget != null)
{
eyemanager.SetTarget(currentTarget); // 设置目标
}
else
{
Debug.LogWarning("The collider does not have an EyeTarget component.");
}
}
}
else
{
currentTarget = null; // 如果没有目标,设置为 null
}
}
else
{
currentTarget = null; // 如果没有目标,设置为 null
}
}
void HandleTargetIndicator()
{
if (currentTarget == null)
@@ -153,7 +157,8 @@ void UpdateCurrentTarget()
// 转换为屏幕坐标
Vector3 screenCenter = viewCamera.WorldToScreenPoint(boxCenter);
Vector2 screenSize = viewCamera.WorldToScreenPoint(boxCenter + boxSize) - viewCamera.WorldToScreenPoint(boxCenter);
Vector2 screenSize = viewCamera.WorldToScreenPoint(boxCenter + boxSize) -
viewCamera.WorldToScreenPoint(boxCenter);
// 设置目标框位置和大小
RectTransform indicatorRectTransform = targetIndicator.GetComponent<RectTransform>();
@@ -167,10 +172,10 @@ void UpdateCurrentTarget()
targetIndicator.SetActive(true);
}
}
public void SetIndicatorTarget(EyeTarget target)
{
currentTarget=target;
currentTarget = target;
}
@@ -187,7 +192,7 @@ void UpdateCurrentTarget()
// {
// Debug.Log(hit.collider.gameObject.name);
// }
// if (hit.collider != null && hit.collider.CompareTag("EyeTarget")) // 检查是否是目标 Sprite
// {
@@ -253,11 +258,11 @@ void UpdateCurrentTarget()
// 绘制场景边界
Vector3 bottomLeft = new Vector3(sceneBoundsMin.x, sceneBoundsMin.y, 0);
Vector3 topRight = new Vector3(sceneBoundsMax.x, sceneBoundsMax.y, 0);
// 绘制边界框
Gizmos.DrawLine(bottomLeft, new Vector3(bottomLeft.x, topRight.y, 0));
Gizmos.DrawLine(bottomLeft, new Vector3(topRight.x, bottomLeft.y, 0));
Gizmos.DrawLine(topRight, new Vector3(bottomLeft.x, topRight.y, 0));
Gizmos.DrawLine(topRight, new Vector3(topRight.x, bottomLeft.y, 0));
}
}
}
@@ -11,15 +11,17 @@ namespace AibisDream.FixSystem
private const string SocketObjName = "Socket";
private const string ModulePicName = "Module Pic";
public Transform socketPos;
// public Transform _indicatorPos;
private BodyModuleSystem _bodyModuleSystem;
private Material _highlightMaterial;
private Material _alarmMaterial;
private Material _originalMaterial; // 原材质
private Material _originalMaterial; // 原材质
private SpriteRenderer _targetSpriteRenderer; // 目标的 SpriteRenderer
#endregion
// 模块基本数据
@@ -31,38 +33,42 @@ namespace AibisDream.FixSystem
// 获取组件索引
InitReference();
}
private void InitReference()
{
socketPos = transform.Find(SocketObjName);
_bodyModuleSystem = transform.parent.parent.GetComponent<BodyModuleSystem>();
_targetSpriteRenderer=transform.Find("Module Pic").GetComponent<SpriteRenderer>();
_targetSpriteRenderer = transform.Find("Module Pic").GetComponent<SpriteRenderer>();
_originalMaterial = _targetSpriteRenderer.GetComponent<SpriteRenderer>().material;
_highlightMaterial = Resources.Load<Material>("Materials/HighlightMaterial");
_alarmMaterial=Resources.Load<Material>("Materials/AlarmMaterial");
_alarmMaterial = Resources.Load<Material>("Materials/AlarmMaterial");
}
#region
public bool IsAvailable()
{
return _available;
}
public void SetSocketAvailable(bool isAvailable)
{
_available=isAvailable;
_available = isAvailable;
}
public void PlugIn()
{
if(DialogController.Instance!=null)
// 然后触发Yarn节点
DialogController.Instance.StartDialogNode(_bodyModuleSystem.inHotErr ? "系统过热" : data.PlugInNodeName);
if (DialogController.Instance != null)
// 然后触发Yarn节点
DialogController.Instance.StartDialogNode(_bodyModuleSystem.inHotErr ? "系统过热" : data.PlugInNodeName);
}
public void PlugOut()
{
_bodyModuleSystem.oscilloscopeSystem.MessageBoxSetNull();
StartCoroutine(_bodyModuleSystem.oscilloscopeSystem.DisableDeepInButton());
// TODO 触发Yarn节点(似乎目前没有拔出对话?)
}
@@ -87,7 +93,7 @@ namespace AibisDream.FixSystem
newSocketPos.localPosition = newData.SocketPos;
// 数据同步
data = newData;
InitReference();
}
@@ -102,20 +108,23 @@ namespace AibisDream.FixSystem
ModulePic = modulePic.sprite,
ModulePos = transform.localPosition,
SocketPos = newSocketPos.localPosition,
cantStopRunning=data.cantStopRunning,
cantStopRunning = data.cantStopRunning,
};
}
#endregion
#region
public void Highlight(bool enable)
{
if (_targetSpriteRenderer != null && _highlightMaterial != null&&_targetSpriteRenderer.material!=_alarmMaterial)
if (_targetSpriteRenderer != null && _highlightMaterial != null &&
_targetSpriteRenderer.material != _alarmMaterial)
{
_targetSpriteRenderer.material = enable ? _highlightMaterial : _originalMaterial;
}
}
public void Alarm(bool enable)
{
if (_targetSpriteRenderer != null && _alarmMaterial != null)
@@ -123,6 +132,7 @@ namespace AibisDream.FixSystem
_targetSpriteRenderer.material = enable ? _alarmMaterial : _originalMaterial;
}
}
// public void HideModule(bool enable)
// {
// if (targetSpriteRenderer != null && highlightMaterial != null)
@@ -130,16 +140,16 @@ namespace AibisDream.FixSystem
// targetSpriteRenderer.material = enable ? highlightMaterial : originalMaterial;
// }
// }
#endregion
#endregion
}
[Serializable]
public struct BodyModuleData
{
public const string PlugInNodeTemplate = "{0}PlugIn";
public const string DeepInTemplate = "{0}DeepIn";
// ID
public string moduleName;
@@ -174,11 +184,5 @@ namespace AibisDream.FixSystem
get => socketPos.ToVector3();
set => socketPos = new SerializableVector3(value);
}
// [JsonIgnore]
// public Vector3 IndicatorPos
// {
// get => indicatorPos.ToVector3();
// set => indicatorPos = new SerializableVector3(value);
// }
}
}
@@ -70,8 +70,6 @@ namespace AibisDream.FixSystem
{
heatMapController = transform.Find("HeatMapController").GetComponent<HeatMapController>();
}
Debug.Log("Register");
FixSystemCenter.SystemDic.Register(this);
}
@@ -189,12 +187,12 @@ namespace AibisDream.FixSystem
#region
public override string[] GetDataKeyOptions()
public override string GetConfigPath()
{
return _keyOptions ??= ConfigUtil.Instance.GetFileNames(DataPath);
return DataPath;
}
public override void Load()
public override void LoadLevel()
{
if (string.IsNullOrEmpty(CurDataKey))
{
@@ -248,7 +246,7 @@ namespace AibisDream.FixSystem
BodyModules = newModules;
}
public override void Save()
public override void SaveLevel()
{
if (string.IsNullOrEmpty(CurDataKey)) return;
@@ -10,152 +10,176 @@ namespace AibisDream
private static OscilloscopeSystem OscilloscopeSystem => FixSystemCenter.SystemDic.Get<OscilloscopeSystem>();
private static PunchTapeSystem PunchTapeSystem => FixSystemCenter.SystemDic.Get<PunchTapeSystem>();
[YarnCommand("SetModuleState_CantStopRunning")]
public static void SetModuleState_CantStopRunning(string ModuleName,bool state)
public static void SetModuleState_CantStopRunning(string moduleName, bool state)
{
BodyModuleSystem.SetModuleState_CantStopRunning(ModuleName,state);
BodyModuleSystem.SetModuleState_CantStopRunning(moduleName, state);
}
[YarnCommand("ShowHeatMap")]
public static void ShowHeatMap()
{
BodyModuleSystem.ShowHeatMap();
}
[YarnCommand("HideHeatMap")]
[YarnCommand("HideHeatMap")]
public static void HideHeatMap()
{
BodyModuleSystem.HideHeatMap();
}
[YarnCommand("SetHeat")]
public static void SetHeat(int heatValue)
{
BodyModuleSystem.SetHeat(heatValue);
}
[YarnCommand("Temp_RemoveUF")]
public static void Temp_RemoveUF()
{
var _UFModule = BodyModuleSystem.FindBodyModuleByName("UF").gameObject;
if(_UFModule.activeInHierarchy)
var _UFModule = BodyModuleSystem.FindBodyModuleByName("UF").gameObject;
if (_UFModule.activeInHierarchy)
{
_UFModule.SetActive(false);
}
}
[YarnCommand("Temp_RemoveUFCover")]
public static void Temp_RemoveUFCover()
{
var _UFCover = BodyModuleSystem.FindBodyModuleByName("UF").transform.Find("Cover").gameObject;
if(_UFCover.activeInHierarchy)
var _UFCover = BodyModuleSystem.FindBodyModuleByName("UF").transform.Find("Cover").gameObject;
if (_UFCover.activeInHierarchy)
{
_UFCover.SetActive(false);
}
}
[YarnCommand("Temp_InstallUF")]
public static void Temp_InstallUF()
{
var _UFModule = BodyModuleSystem.FindBodyModuleByName("UF").gameObject;
if(!_UFModule.activeInHierarchy)
var _UFModule = BodyModuleSystem.FindBodyModuleByName("UF").gameObject;
if (!_UFModule.activeInHierarchy)
{
_UFModule.SetActive(true);
}
}
[YarnCommand("Temp_InstallUFCover")]
public static void Temp_InstallUFCover()
{
var _UFCover = BodyModuleSystem.FindBodyModuleByName("UF").transform.Find("Cover").gameObject;
if(!_UFCover.activeInHierarchy)
var _UFCover = BodyModuleSystem.FindBodyModuleByName("UF").transform.Find("Cover").gameObject;
if (!_UFCover.activeInHierarchy)
{
_UFCover.SetActive(true);
}
}
[YarnCommand("Temp_InstallChip")]
public static void Temp_InstallChip()
{
var _UFCover = BodyModuleSystem.FindBodyModuleByName("Color").transform.Find("Chip").gameObject;
if(!_UFCover.activeInHierarchy)
var _UFCover = BodyModuleSystem.FindBodyModuleByName("Color").transform.Find("Chip").gameObject;
if (!_UFCover.activeInHierarchy)
{
_UFCover.SetActive(true);
}
}
[YarnCommand("Temp_RemoveChip")]
public static void Temp_RemoveChip()
{
var _UFCover = BodyModuleSystem.FindBodyModuleByName("Color").transform.Find("Chip").gameObject;
if(_UFCover.activeInHierarchy)
var _UFCover = BodyModuleSystem.FindBodyModuleByName("Color").transform.Find("Chip").gameObject;
if (_UFCover.activeInHierarchy)
{
_UFCover.SetActive(false);
}
}
[YarnCommand("SetSocketAvailable")]
public static void SetSocketAvailable(string moduleName,bool isAvailable)
public static void SetSocketAvailable(string moduleName, bool isAvailable)
{
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
targetModule.SetSocketAvailable(isAvailable);
}
[YarnCommand("ModuleHightLight")]
public static void ModuleHightLight(string moduleName,bool enable)
public static void ModuleHightLight(string moduleName, bool enable)
{
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
targetModule.Highlight(enable);
}
[YarnCommand("ModuleAlarm")]
public static void ModuleAlarm(string moduleName,bool enable)
public static void ModuleAlarm(string moduleName, bool enable)
{
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
var targetModule = BodyModuleSystem.FindBodyModuleByName(moduleName);
targetModule.Alarm(enable);
}
[YarnCommand("MessageBoxSetError")]
public static void MessageBoxSetError()
{
OscilloscopeSystem.MessageBoxSetError();
OscilloscopeSystem.MessageBoxSetError();
}
[YarnCommand("MessageBoxSetWarning")]
public static void MessageBoxSetWarning()
{
OscilloscopeSystem.MessageBoxSetWarning();
OscilloscopeSystem.MessageBoxSetWarning();
}
[YarnCommand("MessageBoxSetNormal")]
[YarnCommand("MessageBoxSetNormal")]
public static void MessageBoxSetNormal()
{
OscilloscopeSystem.MessageBoxSetNormal();
OscilloscopeSystem.MessageBoxSetNormal();
}
[YarnCommand("MessageBoxSetChecking")]
public static void MessageBoxSetChecking()
{
OscilloscopeSystem.MessageBoxSetChecking();
OscilloscopeSystem.MessageBoxSetChecking();
}
[YarnCommand("MessageBoxSetNull")]
public static void MessageBoxSetNull()
{
OscilloscopeSystem.MessageBoxSetNull();
OscilloscopeSystem.MessageBoxSetNull();
}
[YarnCommand("MessageBoxSetText")]
public static void MessageBoxSetText(string text)
{
OscilloscopeSystem.MessageBoxSetText(text);
OscilloscopeSystem.MessageBoxSetText(text);
}
[YarnCommand("EnableDeepInButton")]
public static void EnableDeepInButton()
{
OscilloscopeSystem.StartCoroutine(OscilloscopeSystem.EnableDeepInButton());
OscilloscopeSystem.StartCoroutine(OscilloscopeSystem.EnableDeepInButton());
}
[YarnCommand("DisableDeepInButton")]
public static void DisableDeepInButton()
{
OscilloscopeSystem.StartCoroutine(OscilloscopeSystem.DisableDeepInButton());
OscilloscopeSystem.StartCoroutine(OscilloscopeSystem.DisableDeepInButton());
}
[YarnCommand("PrintPunchTapes")]
public static IEnumerator PrintPunchTapes(int count)
{
yield return PunchTapeSystem.StartCoroutine(PunchTapeSystem.PrintPunchTapes(count));
}
[YarnCommand("HidePunchTapeGroup")]
public static IEnumerator HidePunchTapeGroup()
{
yield return PunchTapeSystem.StartCoroutine(PunchTapeSystem.Temp_HidePunchTapeGroup());
}
[YarnCommand("ShowPunchTapeGroup")]
public static void ShowPunchTapeGroup()
{
PunchTapeSystem.Temp_showPunchTapeGroup();
}
}
}
}
@@ -1,3 +1,4 @@
using System;
using System.Collections;
using AibisDream.Utility;
using DG.Tweening;
@@ -17,9 +18,11 @@ namespace AibisDream.FixSystem
private Transform LinkDevice => _curCharacter.transform.Find("换液设备");
private SpriteRenderer _blinkLayer;
public CharacterData characterData;
public event Action<CharacterData> CharacterChangeEvent;
public IEnumerator CharacterInit(string characterName)
{
// 异步加载角色预制体(psb
ResourceRequest request = Resources.LoadAsync<GameObject>($"Characters/{characterName}");
yield return request;
@@ -37,6 +40,8 @@ namespace AibisDream.FixSystem
_curCharacter = null;
}
characterData = new CharacterData();
characterData.characterName = characterName;
// 加载新的
GameObject characterPrefab = request.asset as GameObject;
_curCharacter = Instantiate(characterPrefab, transform);
@@ -45,8 +50,8 @@ namespace AibisDream.FixSystem
_blinkLayer = _curCharacter.transform.Find("闭眼").GetComponent<SpriteRenderer>();
_blinkLayer.enabled = false;
// 表情和动作只留一种
ActiveLayer(FaceGroup);
ActiveLayer(PoseGroup);
characterData.faceName = ActiveLayer(FaceGroup);
characterData.poseName = ActiveLayer(PoseGroup);
// 换液设备先隐藏
RemoveLinkDevice();
@@ -57,23 +62,33 @@ namespace AibisDream.FixSystem
yield return new WaitForSeconds(1);
// 激活角色
_curCharacter.SetActive(true);
UpdateCharacterData();
}
private static void ActiveLayer(Transform root, string layerName = null)
private void UpdateCharacterData()
{
CharacterChangeEvent?.Invoke(characterData);
}
private static string ActiveLayer(Transform root, string layerName = null)
{
var childLayers = root.GetComponentsInChildren<SpriteRenderer>(true);
if (childLayers.Length == 0) return;
if (childLayers.Length == 0) return null;
// 如果输入为空,就默认激活一层
if (layerName == null)
{
childLayers[0].enabled = true;
return childLayers[0].gameObject.name;
}
foreach (var layer in childLayers)
{
layer.enabled = layer.gameObject.name == layerName;
}
// 如果输入为空,就默认激活一层
if (layerName == null)
{
childLayers[0].enabled = true;
}
return layerName;
}
private void SetCharacterAlpha(float alpha)
@@ -90,7 +105,7 @@ namespace AibisDream.FixSystem
public IEnumerator CharacterFadeIn(float duration = 1f)
{
if (_curCharacter != null)
if (_curCharacter)
{
_curCharacter.SetActive(true);
yield return FadeCharacter(1, duration);
@@ -114,13 +129,15 @@ namespace AibisDream.FixSystem
public void SwitchPose(string poseName)
{
ActiveLayer(PoseGroup, poseName);
characterData.poseName = ActiveLayer(PoseGroup, poseName);
UpdateCharacterData();
}
public void SwitchFace(string faceName)
{
StopAutoBlink();
ActiveLayer(FaceGroup, faceName);
characterData.faceName = ActiveLayer(FaceGroup, faceName);
UpdateCharacterData();
}
public void Blink()
@@ -174,5 +191,18 @@ namespace AibisDream.FixSystem
Debug.LogError($"Character {characterName} not found in loaded characters.");
}
}
public void OnDestroy()
{
characterData = new CharacterData();
UpdateCharacterData();
}
}
public struct CharacterData
{
public string characterName;
public string faceName;
public string poseName;
}
}
@@ -1,5 +1,8 @@
using System;
using System.Collections;
using AibisDream.FixSystem;
using AibisDream.Framework;
using AibisDream.Utility;
using DG.Tweening;
using UnityEngine;
@@ -14,16 +17,35 @@ namespace AibisDream
public Vector3 pumpUpPos;
public Vector3 pumpDownPos;
public float pumpDuration;
private readonly ClinicData _clinicData;
private void Awake()
{
FixSystemCenter.SystemDic.Register(this);
GameLoopManager.FixDataContainer.Register(_clinicData);
character = transform.GetComponentInChildren<CharacterViewer>();
character.CharacterChangeEvent += OnCharacterChange;
_clinicData.LoadEvent += LoadData;
_pumpHead = transform.Find("正图").Find("近景").Find("桌上泵头");
_coolingScreen = transform.Find("正图").Find("近景").Find("桌面泵机运作时亮灯").gameObject;
}
private void LoadData(ClinicData data)
{
StartCoroutine(LoadDataAsync(data));
}
private IEnumerator LoadDataAsync(ClinicData data)
{
yield return character.CharacterInit(data.characterName);
character.SwitchFace(data.faceName);
character.SwitchPose(data.poseName);
}
public IEnumerator Indoor(float duration)
{
// 加载诊所场景
@@ -54,5 +76,32 @@ namespace AibisDream
// 熄灭屏幕
_coolingScreen.SetActive(false);
}
private void OnDestroy()
{
character.CharacterChangeEvent -= OnCharacterChange;
_clinicData.LoadEvent -= LoadData;
GameLoopManager.FixDataContainer.Unregister<ClinicData>();
FixSystemCenter.SystemDic.Unregister<ClinicSystem>();
}
private void OnCharacterChange(CharacterData characterData)
{
CommonUtil.CopyProperties(characterData, _clinicData);
}
}
public class ClinicData : IData
{
public string characterName;
public string faceName;
public string poseName;
public event Action<ClinicData> LoadEvent;
public void Load()
{
LoadEvent?.Invoke(this);
}
}
}
@@ -0,0 +1,227 @@
using System;
using System.Collections;
using AibisDream.Framework;
using UnityEngine.PlayerLoop;
namespace AibisDream.FixSystem
{
public class FixStateMachine
{
private IState _curState;
private string _curArgs;
public void SwitchState(FixState nextState, string args = "")
{
_curArgs = args;
_curState?.Exit();
GameLoopManager.Instance.UpdateFixState(nextState, _curArgs);
_curState = CreateState(nextState, _curArgs);
_curState.Enter();
}
private static IState CreateState(FixState nextState, string args)
{
IState res = nextState switch
{
FixState.Clinic => new ClinicState(),
FixState.Engine => new EngineState(),
FixState.CoolingMachine => new CoolingMachineState(),
FixState.BodyModule => new BodyModuleState(),
FixState.Memory => new MemoryState(),
FixState.Eye => new EyeState(),
FixState.UF => new UfState(),
FixState.Gear => new GearState(),
_ => new ClinicState()
};
res.SetArgs(args);
return res;
}
}
public interface IState
{
public FixState GetState { get; }
public void SetArgs(string args);
public IEnumerator Enter();
public IEnumerator Exit();
}
public class ClinicState : IState
{
public FixState GetState => FixState.Clinic;
public void SetArgs(string args)
{
// 无
}
public IEnumerator Enter()
{
// 切换相机
yield break;
}
public IEnumerator Exit()
{
// 似乎没有?
yield break;
}
}
public class BodyModuleState : IState
{
public FixState GetState => FixState.BodyModule;
public void SetArgs(string args)
{
// 无
}
public IEnumerator Enter()
{
// 切换相机
yield break;
}
public IEnumerator Exit()
{
// 似乎没有?
yield break;
}
}
public class GearState : IState
{
public FixState GetState => FixState.Gear;
private string _configKey;
public void SetArgs(string args)
{
_configKey = args;
}
public IEnumerator Enter()
{
// 切换相机
yield break;
}
public IEnumerator Exit()
{
// 切换相机
yield break;
}
}
public class EngineState : IState
{
public FixState GetState => FixState.Engine;
public void SetArgs(string args)
{
// 无
}
public IEnumerator Enter()
{
// 切换相机
yield break;
// 加载Level
// 解锁
}
public IEnumerator Exit()
{
// 上锁
// 切换相机
yield break;
}
}
public class CoolingMachineState : IState
{
public FixState GetState => FixState.CoolingMachine;
public void SetArgs(string args)
{
throw new NotImplementedException();
}
public IEnumerator Enter()
{
throw new NotImplementedException();
}
public IEnumerator Exit()
{
throw new NotImplementedException();
}
}
public class UfState : IState
{
public FixState GetState => FixState.UF;
public void SetArgs(string args)
{
throw new NotImplementedException();
}
public IEnumerator Enter()
{
throw new NotImplementedException();
}
public IEnumerator Exit()
{
throw new NotImplementedException();
}
}
public class EyeState : IState
{
public FixState GetState => FixState.Eye;
public void SetArgs(string args)
{
throw new NotImplementedException();
}
public IEnumerator Enter()
{
throw new NotImplementedException();
}
public IEnumerator Exit()
{
throw new NotImplementedException();
}
}
public class MemoryState : IState
{
public FixState GetState => FixState.Memory;
public void SetArgs(string args)
{
throw new NotImplementedException();
}
public IEnumerator Enter()
{
throw new NotImplementedException();
}
public IEnumerator Exit()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 235d991f9a3e427fa2aa11cb4b2b372d
timeCreated: 1736254327
@@ -16,6 +16,9 @@ namespace AibisDream.FixSystem
// TODO 这个回头要改
curState = FixState.Clinic;
AudioManager.PlayAmb1Audio("amb_room");
// 初始化状态机
StateMachine = new FixStateMachine();
}
#region
@@ -25,6 +28,12 @@ namespace AibisDream.FixSystem
#endregion
#region
public static FixStateMachine StateMachine;
#endregion
#region
private static readonly StateDictionary<ITransitionCommand> TransitionDic = new();
@@ -104,7 +104,7 @@ namespace AibisDream.FixSystem
if (!string.IsNullOrEmpty(_configKey))
{
gearSystem.CurDataKey = _configKey;
gearSystem.Load();
gearSystem.LoadLevel();
}
}
@@ -25,7 +25,7 @@ namespace AibisDream.FixSystem
if (!string.IsNullOrEmpty(_configName))
{
bodyModuleSystem.CurDataKey = _configName;
bodyModuleSystem.Load();
bodyModuleSystem.LoadLevel();
}
// 隐藏诊所
@@ -75,7 +75,7 @@ namespace AibisDream.FixSystem
if (!string.IsNullOrEmpty(_configName))
{
engineSystem.CurDataKey = _configName;
engineSystem.Load();
engineSystem.LoadLevel();
}
yield return engineSystem.OpenCover().WaitForCompletion();
@@ -156,7 +156,7 @@ namespace AibisDream.FixSystem
if (!string.IsNullOrEmpty(_configName))
{
gearSystem.CurDataKey = _configName;
gearSystem.Load();
gearSystem.LoadLevel();
}
}
@@ -13,7 +13,6 @@ namespace AibisDream.FixSystem
Memory,
Eye,
UF,
VisualSense,
Engine,
Gear
}
+244 -20
View File
@@ -1,37 +1,27 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Utility;
using Newtonsoft.Json.Linq;
using UnityEngine;
namespace AibisDream.Framework
{
public interface IModule
{
void Init();
void Init(string dataKey);
void Deinit();
}
public interface ISystem
{
void Init();
void Deinit();
}
public interface ISystemHasData
{
string CurDataKey { get; set; }
string[] GetDataKeyOptions();
void Load();
void Save();
string GetConfigPath();
void LoadLevel();
void SaveLevel();
}
public abstract class SystemHasData : MonoBehaviour, ISystemHasData
{
public abstract string CurDataKey { get; set; }
public abstract string[] GetDataKeyOptions();
public abstract void Load();
public abstract void Save();
public abstract string GetConfigPath();
public abstract void LoadLevel();
public abstract void SaveLevel();
}
public interface IHasData
@@ -39,7 +29,12 @@ namespace AibisDream.Framework
void Save(string dataKey);
void Load(string dataKey);
}
public interface IData
{
void Load();
}
#region IOC容器
public class IOCContainer
@@ -85,5 +80,234 @@ namespace AibisDream.Framework
public void Clear() => _instances.Clear();
}
public class DataContainer
{
private Dictionary<string, IData> _instances = new();
public void Register<T>(T instance) where T : IData
{
var key = typeof(T).AssemblyQualifiedName;
if (key != null) _instances[key] = instance;
}
public T Get<T>() where T : class, IData
{
var key = typeof(T).AssemblyQualifiedName;
if (key != null && _instances.TryGetValue(key, out var retInstance))
{
return retInstance as T;
}
return null;
}
public object Get(Type type)
{
var key = type.AssemblyQualifiedName;
if (key != null && _instances.TryGetValue(key, out var retInstance))
{
return retInstance;
}
return null;
}
public T Unregister<T>() where T : class, IData
{
var res = Get<T>();
var assemblyQualifiedName = typeof(T).AssemblyQualifiedName;
if (res != null && assemblyQualifiedName != null)
{
_instances.Remove(assemblyQualifiedName);
return res;
}
return null;
}
public void Clear() => _instances.Clear();
public JObject SaveAsJson()
{
return JObject.FromObject(_instances);
}
public void LoadByJson(JObject dataJson)
{
foreach (var fixDataItemPair in _instances)
{
if (!dataJson.TryGetValue(fixDataItemPair.Key, out var fixData))
{
Debug.Log(fixDataItemPair.Key + "未注册");
continue;
}
var fixDataType = Type.GetType(fixDataItemPair.Key);
if (fixDataType == null)
{
Debug.Log(fixDataItemPair.Key + "类型不存在");
continue;
}
// 把Json中读到的参数填回Data
var tempObj = fixData.ToObject(fixDataType);
CommonUtil.CopyProperties(tempObj, fixDataItemPair.Value);
}
foreach (var data in _instances.Values)
{
data.Load();
}
}
}
#endregion
#region
public interface IEasyEvent
{
IUnRegister Register(Action onEvent);
public void UnRegisterAll();
}
public class EasyEvent : IEasyEvent
{
private event Action OnEvent = () => { };
public IUnRegister Register(Action onEvent)
{
OnEvent += onEvent;
return new CustomUnRegister(() => { UnRegister(onEvent); });
}
public void UnRegister(Action onEvent) => OnEvent -= onEvent;
public void Trigger() => OnEvent?.Invoke();
public void UnRegisterAll()
{
OnEvent = null;
}
}
public class EasyEvent<T> : IEasyEvent
{
private event Action<T> OnEvent = e => { };
public IUnRegister Register(Action<T> onEvent)
{
OnEvent += onEvent;
return new CustomUnRegister(() => { UnRegister(onEvent); });
}
public void UnRegister(Action<T> onEvent) => OnEvent -= onEvent;
public void Trigger(T t) => OnEvent?.Invoke(t);
IUnRegister IEasyEvent.Register(Action onEvent)
{
return Register(Action);
void Action(T _) => onEvent();
}
public void UnRegisterAll()
{
OnEvent = null;
}
}
public class EasyEvent<T, TK> : IEasyEvent
{
private event Action<T, TK> OnEvent = (_, _) => { };
public IUnRegister Register(Action<T, TK> onEvent)
{
OnEvent += onEvent;
return new CustomUnRegister(() => { UnRegister(onEvent); });
}
public void UnRegister(Action<T, TK> onEvent) => OnEvent -= onEvent;
public void Trigger(T t, TK k) => OnEvent?.Invoke(t, k);
IUnRegister IEasyEvent.Register(Action onEvent)
{
return Register(Action);
void Action(T _, TK __) => onEvent();
}
public void UnRegisterAll()
{
OnEvent = null;
}
}
public interface IUnRegister
{
void UnRegister();
}
public struct CustomUnRegister : IUnRegister
{
private Action OnUnRegister { get; set; }
public CustomUnRegister(Action onUnRegister) => OnUnRegister = onUnRegister;
public void UnRegister()
{
OnUnRegister.Invoke();
OnUnRegister = null;
}
}
public class BindProperty<T>
{
private T _value;
private EasyEvent<T> _onValueChanged;
public BindProperty(T defaultValue = default) => _value = defaultValue;
public static Func<T, T, bool> Comparer { get; set; } = (a, b) => a.Equals(b);
public BindProperty<T> WithComparer(Func<T, T, bool> comparer)
{
Comparer = comparer;
return this;
}
public T Value
{
get => GetValue();
set
{
if (value == null && _value == null) return;
if (value != null && Comparer(value, _value)) return;
SetValue(value);
_onValueChanged.Trigger(value);
}
}
private void SetValue(T newValue) => _value = newValue;
private T GetValue() => _value;
public void SetValueWithoutEvent(T newValue) => _value = newValue;
public IUnRegister Register(Action<T> onValueChanged)
{
return _onValueChanged.Register(onValueChanged);
}
public void UnRegister(Action<T> onValueChanged) => _onValueChanged.UnRegister(onValueChanged);
public override string ToString() => Value.ToString();
public void RemoveAll()
{
_onValueChanged?.UnRegisterAll();
}
}
#endregion
}
+219
View File
@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Utility;
using UnityEngine;
namespace AibisDream.Framework
{
public class EnumEventSystem
{
public static readonly EnumEventSystem Global = new();
private readonly Dictionary<Type, IEasyEvent[]> _eventDict = new(50);
protected EnumEventSystem()
{
}
public IUnRegister Register<T>(T key, Action onEvent) where T : IConvertible
{
var kv = key.ToInt32(null);
if (_eventDict.TryGetValue(typeof(T), out var events))
{
if (events[kv] == null)
{
var tempEvent = new EasyEvent();
events[kv] = tempEvent;
return tempEvent.Register(onEvent);
}
if (events[kv] is EasyEvent targetEvent)
{
return targetEvent.Register(onEvent);
}
Debug.Log($"{key.ToString()} 注册参数错误");
return null;
}
else
{
events = new IEasyEvent[Enum.GetValues(typeof(T)).Length];
_eventDict.Add(typeof(T), events);
var tempEvent = new EasyEvent();
events[kv] = tempEvent;
return tempEvent.Register(onEvent);
}
}
public IUnRegister Register<T, TE>(T key, Action<TE> onEvent) where T : IConvertible where TE : struct
{
var kv = key.ToInt32(null);
if (_eventDict.TryGetValue(typeof(T), out var events))
{
if (events[kv] == null)
{
var tempEvent = new EasyEvent<TE>();
events[kv] = tempEvent;
return tempEvent.Register(onEvent);
}
if (events[kv] is EasyEvent<TE> targetEvent)
{
return targetEvent.Register(onEvent);
}
Debug.Log($"{key.ToString()} 注册参数错误");
return null;
}
else
{
events = new IEasyEvent[Enum.GetValues(typeof(T)).Length];
_eventDict.Add(typeof(T), events);
var tempEvent = new EasyEvent<TE>();
events[kv] = tempEvent;
return tempEvent.Register(onEvent);
}
}
public void UnRegister<T>(T key, Action onEvent) where T : IConvertible
{
var kv = key.ToInt32(null);
if (!_eventDict.TryGetValue(typeof(T), out var e)) return;
if (e.Length >= kv || e[kv] == null) return;
if (e[kv] is EasyEvent tempEvent)
{
tempEvent.UnRegister(onEvent);
}
}
public void UnRegister<T>(T key) where T : IConvertible
{
var kv = key.ToInt32(null);
if (!_eventDict.TryGetValue(typeof(T), out var e)) return;
if (e.Length >= kv || e[kv] == null) return;
e[kv].UnRegisterAll();
}
public void UnRegisterAll()
{
foreach (var eventItem in _eventDict.Values.SelectMany(eventArr => eventArr))
{
eventItem?.UnRegisterAll();
}
_eventDict.Clear();
}
public void Send<T>(T key) where T : IConvertible
{
var kv = key.ToInt32(null);
if (!_eventDict.TryGetValue(typeof(T), out var e)) return;
if (e.Length >= kv || e[kv] == null) return;
if (e[kv] is EasyEvent tempEvent)
{
tempEvent.Trigger();
}
}
public void Send<T, TE>(T key, TE param) where T : IConvertible
{
var kv = key.ToInt32(null);
if (!_eventDict.TryGetValue(typeof(T), out var e)) return;
if (e.Length >= kv || e[kv] == null) return;
if (e[kv] is EasyEvent<TE> tempEvent)
{
tempEvent.Trigger(param);
}
}
}
public class StringEventSystem
{
public static readonly StringEventSystem Global = new();
private readonly Dictionary<string, IEasyEvent> _events = new();
public IUnRegister Register(string key, Action onEvent)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent>();
return easyEvent.Register(onEvent);
}
else
{
var easyEvent = new EasyEvent();
_events.Add(key, easyEvent);
return easyEvent.Register(onEvent);
}
}
public void UnRegister(string key, Action onEvent)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent>();
easyEvent?.UnRegister(onEvent);
}
}
public void Send(string key)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent>();
easyEvent?.Trigger();
}
}
public IUnRegister Register<T>(string key, Action<T> onEvent)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent<T>>();
return easyEvent.Register(onEvent);
}
else
{
var easyEvent = new EasyEvent<T>();
_events.Add(key, easyEvent);
return easyEvent.Register(onEvent);
}
}
public void UnRegister<T>(string key, Action<T> onEvent)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent<T>>();
easyEvent?.UnRegister(onEvent);
}
}
public void Send<T>(string key, T data)
{
if (_events.TryGetValue(key, out var e))
{
var easyEvent = e.As<EasyEvent<T>>();
easyEvent?.Trigger(data);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 21974c647d3c4682b2c9dc6b8c23b4ef
timeCreated: 1736232227
@@ -29,6 +29,11 @@ namespace AibisDream.Kit
{
Instance = null;
}
OnSingletonDestroy();
}
public virtual void OnSingletonDestroy()
{
}
}
}
+143 -30
View File
@@ -1,5 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.FixSystem;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using Newtonsoft.Json.Linq;
using UnityEngine;
using Yarn.Unity;
@@ -7,42 +13,50 @@ namespace AibisDream
{
public class GameLoopManager : Singleton<GameLoopManager>
{
[Header("运行模式")]
[SerializeField]
private RunMode runMode;
#region
[Header("正式环境参数")]
[SerializeField] private TalkSceneSO firstTalkSo;
[Header("可用so合集")]
public TalkSceneSO[] totalSceneSos;
public RunMode runMode;
[Header("生产环境数据(一般不动)")] public TalkSceneSO firstTalkSo;
[Header("单场景测试")] public TalkSceneSO testTalkSo;
[Header("存档测试")] public string saveFileName;
#endregion
private TalkSceneSO _currentTalkSceneSo;
[SerializeField]
private string clinicScene;
[Header("测试环境参数")]
[SerializeField] private string testYarnProject;
public void Start()
{
if (runMode == RunMode.Test)
#if UNITY_EDITOR
if (runMode == RunMode.SingleScene)
{
MainUIController.Instance.TVFadeOut(1);
GameObject.Find("Menu Canvas").SetActive(false);
StartCoroutine(StartTestGame());
StartSingleSceneTest();
}
else if (runMode == RunMode.SaveFile)
{
MainUIController.Instance.TVFadeOut(1);
GameObject.Find("Menu Canvas").SetActive(false);
StartCoroutine(LoadSaveFile(saveFileName));
}
#else
runMode = RunMode.Product;
#endif
}
public void StartNewGame()
{
_currentTalkSceneSo = firstTalkSo;
StartCoroutine(LoadClinicScene());
}
public void StartNewGame(TalkSceneSO sceneSo)
private void StartSingleSceneTest()
{
_currentTalkSceneSo = sceneSo;
_currentTalkSceneSo = testTalkSo;
StartCoroutine(LoadClinicScene());
}
@@ -53,15 +67,6 @@ namespace AibisDream
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
}
public IEnumerator StartTestGame()
{
// TODO 全部改好之后这里要直接进入FixScene
yield return null;
//yield return SceneLoader.Instance.LoadSceneAsync(clinicScene);
var proj = Resources.Load<YarnProject>($"Yarn/{testYarnProject}/{testYarnProject}");
DialogController.Instance.StartDialog(proj);
}
public IEnumerator NextSceneSo()
{
if (_currentTalkSceneSo && _currentTalkSceneSo.nextScene)
@@ -77,11 +82,119 @@ namespace AibisDream
Debug.Log("没有下个场景了");
}
}
#region
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
// 维修系统相关数据
public static readonly DataContainer FixDataContainer = new();
// 对话变量存储
private VariableStorageBehaviour _dialogStorage;
// 当前场景
private string _curSceneKey;
// 状态机
private string _fixStateArgs;
private FixState _fixState;
public override void OnSingletonInit()
{
_dialogStorage = FindObjectOfType<VariableStorageBehaviour>();
}
/// <summary>
/// 当前场景自行更新
/// </summary>
/// <param name="sceneName">当前scene</param>
public void UpdateCurScene(string sceneName)
{
_curSceneKey = sceneName;
}
/// <summary>
/// 状态机状态更新
/// </summary>
/// <param name="curState"></param>
/// <param name="curArgs"></param>
public void UpdateFixState(FixState curState, string curArgs)
{
_fixState = curState;
_fixStateArgs = curArgs;
}
private IEnumerator LoadSaveFile(string saveName)
{
var saveFile = JsonUtil.ReadJObject($"{SaveFilePath}/{saveName}");
// 先加载对话数据
var floatDict = saveFile["floatDict"]?.ToObject<Dictionary<string, float>>();
var stringDict = saveFile["stringDict"]?.ToObject<Dictionary<string, string>>();
var boolDict = saveFile["boolDict"]?.ToObject<Dictionary<string, bool>>();
_dialogStorage.SetAllVariables(floatDict, stringDict, boolDict);
// 再加载场景
_currentTalkSceneSo = Array.Find(totalSceneSos, so => so.name == saveFile["curTalkSceneSo"]?.ToString());
yield return SceneLoader.Instance.LoadSceneAsync(saveFile["curSceneKey"]?.ToString());
if (saveFile["fixDataContainer"] is not JObject fixDataJson)
{
Debug.Log("维修数据读取问题");
yield break;
}
// 场景加载完成之后把数据填回去
FixDataContainer.LoadByJson(fixDataJson);
// 初始化维修状态机
_fixState = saveFile["fixState"]!.ToObject<FixState>();
_fixStateArgs = saveFile["fixStateArgs"]!.ToString();
FixSystemCenter.StateMachine.SwitchState(_fixState, _fixStateArgs);
// 开启对话
DialogController.Instance.StartDialog(_currentTalkSceneSo.yarnProject);
}
public void Save()
{
JObject saveFile = new JObject();
// 场景维修相关数据保存
var fixData = FixDataContainer.SaveAsJson();
saveFile["fixDataContainer"] = fixData;
// 保存对话变量
var (floatDict, stringDict, boolDict) = _dialogStorage.GetAllVariables();
saveFile["floatDict"] = JObject.FromObject(floatDict);
saveFile["stringDict"] = JObject.FromObject(stringDict);
saveFile["boolDict"] = JObject.FromObject(boolDict);
// 保存场景数据
saveFile["curSceneKey"] = _curSceneKey;
saveFile["curTalkSceneSo"] = _currentTalkSceneSo.name;
// 保存状态机数据
saveFile["fixState"] = (int) _fixState;
saveFile["fixStateArgs"] = _fixStateArgs;
// 存为Json
JsonUtil.SaveJObject(saveFile, GetSavePath());
}
private string GetSavePath()
{
_dialogStorage.TryGetValue("$gameStage", out float gameStage);
return $"{SaveFilePath}/{_currentTalkSceneSo.name}_{gameStage}_{DateTime.Now:yyyyMMdd_HHmmss}";
}
#endregion
}
public enum RunMode
{
Test, Pro, FixTest
Product,
SingleScene,
SaveFile
}
}
}
+27 -28
View File
@@ -1,5 +1,5 @@
using System;
using System.Collections;
using AibisDream.Framework;
using AibisDream.Kit;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
@@ -11,17 +11,21 @@ namespace AibisDream
{
#region
private string currentScene;
private BindProperty<string> _currentScene;
private AsyncOperationHandle _loadHandle;
private string sceneToLoad;
private bool isLoading;
#endregion
#region
public event Action LoadSceneEvent;
public event Action UnloadSceneEvent;
private string _sceneToLoad;
private bool _isLoading;
public override void OnSingletonInit()
{
_currentScene = new BindProperty<string>();
_currentScene.Register(GameLoopManager.Instance.UpdateCurScene);
}
public override void OnSingletonDestroy()
{
_currentScene.UnRegister(GameLoopManager.Instance.UpdateCurScene);
}
#endregion
@@ -41,50 +45,45 @@ namespace AibisDream
/// <returns></returns>
public IEnumerator LoadSceneAsync(string targetScene)
{
if (isLoading)
if (_isLoading)
{
yield return null;
}
else
{
// 场景转换参数
isLoading = true;
sceneToLoad = targetScene;
if (currentScene != null)
_isLoading = true;
_sceneToLoad = targetScene;
if (string.IsNullOrEmpty(_currentScene.Value))
{
UnloadSceneEvent?.Invoke();
yield return Addressables.UnloadSceneAsync(_loadHandle);
}
_loadHandle = Addressables.LoadSceneAsync(sceneToLoad, LoadSceneMode.Additive);
_loadHandle = Addressables.LoadSceneAsync(_sceneToLoad, LoadSceneMode.Additive);
yield return _loadHandle;
LoadSceneEvent?.Invoke();
currentScene = sceneToLoad;
isLoading = false;
_currentScene.Value = _sceneToLoad;
_isLoading = false;
}
}
public IEnumerator UnloadSceneAsync(string sceneToUnload)
{
if (isLoading)
if (_isLoading)
{
yield return null;
}
else
{
isLoading = true;
_isLoading = true;
if (currentScene == sceneToUnload)
if (_currentScene.Value == sceneToUnload)
{
UnloadSceneEvent?.Invoke();
yield return Addressables.UnloadSceneAsync(_loadHandle, true);
currentScene = null;
_currentScene.Value = null;
}
isLoading = false;
_isLoading = false;
}
}
}
-34
View File
@@ -14,8 +14,6 @@ namespace AibisDream {
[SerializeField] private GameObject startTab;
[SerializeField] private GameObject levelTab;
[SerializeField] private TalkSceneSO[] talkSceneSoArray;
[SerializeField] private GameObject buttonPrefab;
private void OnEnable()
@@ -40,38 +38,6 @@ namespace AibisDream {
public void SelectLevel()
{
SwitchToLevelTab();
// 生成关卡按钮
GeneLevelButtons();
}
private void GeneLevelButtons()
{
// 销毁原来的按钮
foreach (Transform child in levelTab.transform)
{
if (child.gameObject.name == "Suggestion")
{
continue;
}
Destroy(child.gameObject);
}
// 生成新按钮
for (int i = 0; i < talkSceneSoArray.Length; i++)
{
var tempButton = Instantiate(buttonPrefab, levelTab.transform);
tempButton.GetComponent<TextMeshProUGUI>().text = $"第{i + 1}关";
var idx = i;
tempButton.GetComponent<Button>().onClick.AddListener(() =>
{
GameLoopManager.Instance.StartNewGame(talkSceneSoArray[idx]);
});
}
// 生成返回按钮
var returnButton = Instantiate(buttonPrefab, levelTab.transform);
returnButton.GetComponent<TextMeshProUGUI>().text = "返回";
returnButton.GetComponent<Button>().onClick.AddListener(SwitchToStartTab);
}
private void SwitchToLevelTab()
@@ -155,12 +155,12 @@ namespace AibisDream
public override string CurDataKey { get; set; }
public override string[] GetDataKeyOptions()
public override string GetConfigPath()
{
return _keyOptions ??= ConfigUtil.Instance.GetFileNames(DataPath);
return DataPath;
}
public override void Load()
public override void LoadLevel()
{
if (string.IsNullOrEmpty(CurDataKey))
{
@@ -180,7 +180,7 @@ namespace AibisDream
OnLoad();
}
public override void Save()
public override void SaveLevel()
{
if (string.IsNullOrEmpty(CurDataKey))
{
+4 -4
View File
@@ -193,12 +193,12 @@ namespace AibisDream
private string[] _keyOptions;
public override string CurDataKey { get; set; }
public override string[] GetDataKeyOptions()
public override string GetConfigPath()
{
return _keyOptions ??= ConfigUtil.Instance.GetFileNames(DataPath);
return DataPath;
}
public override void Load()
public override void LoadLevel()
{
if (string.IsNullOrEmpty(CurDataKey))
{
@@ -273,7 +273,7 @@ namespace AibisDream
_shaftGraph = new ShaftGraph(shafts, panelShafts);
}
public override void Save()
public override void SaveLevel()
{
if (string.IsNullOrEmpty(CurDataKey)) return;
+261 -282
View File
@@ -3,19 +3,15 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using Yarn.Unity;
using Yarn.Unity;
using System.Linq;
using UnityEngine.UI;
using AibisDream.FixSystem;
using AibisDream.Framework;
//using AibisDream.Kit;
//using Framework.Core;
using AibisDream;
public class EyeSystem : MonoBehaviour
{
[SerializeField]
private List<EyeTarget> targets = new List<EyeTarget>(); // 保存目标列表
[SerializeField] private List<EyeTarget> targets = new List<EyeTarget>(); // 保存目标列表
public List<EyeTarget> Targets => targets; // 提供目标列表的公共访问
private EyeTarget currentTarget; // 当前选中的目标
@@ -29,7 +25,7 @@ public class EyeSystem : MonoBehaviour
public Button backToFaceButton;
public GameObject eyeView;
public enum EyeState
{
CanImagineColor,
@@ -38,42 +34,21 @@ public class EyeSystem : MonoBehaviour
CanSeeColor,
HaveChip
}
public ViewCameraManager cameraManager;
private IEyeStateEffect eyeStateEffect;
private EyeState currentState=EyeState.CannotImagineColor;
public EyeState CurrentState
{
get { return currentState; }
set
{
if (currentState != value)
{
SetEyeState(currentState);
// StartCoroutine(SetEyeStateCoroutine(currentState));
currentState = value;
}
}
}
private EyeState currentState = EyeState.CannotImagineColor;
private Tween hsvShiftTween;
private MouseFollowAndZoom mouseFollowAndZoom;
public void Initialize()
{
// 初始化逻辑
Debug.Log("EyeView initialized.");
}
private void Awake()
{
Init();
}
public void Init()
{
FixSystemCenter.SystemDic.Register(this);
@@ -81,73 +56,73 @@ public class EyeSystem : MonoBehaviour
public void OnEnter()
{
//SetInitialTargetState(targets[1]);
mouseFollowAndZoom.SetIsActive(true);
mouseFollowAndZoom.SetIsLock(false);
// 进入视图时的逻辑
Debug.Log("EyeView entered.");
// 可以在这里进行一些特定的初始化或加载数据
}
public void OpenEyeView()
{
eyeView.SetActive(true);
}
public void CloseEyeView()
public void CloseEyeView()
{
eyeView.SetActive(false);
}
public void OnShow()
{
public void OnShow()
{
// 离开视图时的逻辑
Debug.Log("EyeView showed.");
}
public void OnExit()
{
{
eyeStateEffect?.CleanupEffect(CurrentTarget);
mouseFollowAndZoom.SetIsActive(false);
// 离开视图时的逻辑
Debug.Log("EyeView exited.");
}
private void Start()
private void Start()
{
SetEyeState(currentState);
if (targets.Count > 0)
{
SetInitialTargetState(targets[1]);
}
mouseFollowAndZoom = FindObjectOfType<MouseFollowAndZoom>();
//eyeView.SetActive(false);
//LostColor();
}
public void SetInitialTargetState(EyeTarget target)
{
currentTarget=target;
eyeStateEffect?.InitializeEffect(target,cameraManager);
currentTarget = target;
eyeStateEffect?.InitializeEffect(target, cameraManager);
}
public EyeTarget FindEyeTargetByName(string name)
{
return Targets.FirstOrDefault(target => target.gameObject.name == name);
}
{
return Targets.FirstOrDefault(target => target.gameObject.name == name);
}
public void SetTarget(EyeTarget newTarget)
{
// if (newTarget != currentTarget)
// {
StartCoroutine(SetTargetCoroutine(newTarget.gameObject.name));
StartCoroutine(SetTargetCoroutine(newTarget.gameObject.name));
// }
}
[YarnCommand("set_Eyetarget")]
public IEnumerator SetTargetCoroutine(string targetName,bool startDialogue=true)
public IEnumerator SetTargetCoroutine(string targetName, bool startDialogue = true)
{
mouseFollowAndZoom.SetIsLock(true);
EyeTarget target = FindEyeTargetByName(targetName);
if (target == null)
@@ -161,35 +136,35 @@ public class EyeSystem : MonoBehaviour
// DialogController.Instance.SetVariable("$currentEyeTarget",target.name);
// yield break;
// }
DialogController.Instance.SetVariable("$currentEyeTarget",target.name);
DialogController.Instance.SetVariable("$currentEyeTarget", target.name);
StartCoroutine(EyeEffectFadeOut());
float duration = eyeStateEffect.TransitionDuration;
if(target.targetTransform!=null)
if (target.targetTransform != null)
{
cameraManager.MoveCameraTo(target.targetTransform, 1f);
}
else
{
cameraManager.MoveCameraTo(target.transform, 1f);
}
currentTarget.BlurIn(eyeStateEffect.TransitionDuration,false);
currentTarget.BlurIn(eyeStateEffect.TransitionDuration, false);
//yield return new WaitForSeconds(eyeStateEffect.TransitionDuration);
currentTarget = target;
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
currentTarget.BlurOut(eyeStateEffect.TransitionDuration,false);
currentTarget.BlurOut(eyeStateEffect.TransitionDuration, false);
yield return new WaitForSeconds(eyeStateEffect.TransitionDuration);
if(startDialogue)
if (startDialogue)
{
DialogController.Instance.StartDialogNode("IntoEyeView");
DialogController.Instance.StartDialogNode("IntoEyeView");
}
//mouseFollowAndZoom.SetIsActive(true);
}
@@ -200,24 +175,22 @@ public class EyeSystem : MonoBehaviour
}
[YarnCommand("EyeEffect_FadeIn")]
[YarnCommand("EyeEffect_FadeIn")]
public IEnumerator EyeEffectFadeIn()
{
if(currentTarget!=null)
if (currentTarget != null)
{
AudioManager.RandomPlayInteraction("colorimagine");
eyeStateEffect?.ApplyFocusedEffect(currentTarget);
}
yield return new WaitForSeconds(eyeStateEffect.TransitionDuration);
}
[YarnCommand("EyeEffect_FadeOut")]
public IEnumerator EyeEffectFadeOut()
{
if(currentTarget!=null)
if (currentTarget != null)
{
AudioManager.RandomPlayInteraction("colorimagine");
eyeStateEffect?.ApplyUnfocusedEffect(currentTarget);
@@ -233,250 +206,256 @@ public class EyeSystem : MonoBehaviour
{
target.Init();
}
if(currentTarget!=null)
if (currentTarget != null)
{
eyeStateEffect?.InitializeEffect(currentTarget,cameraManager);
eyeStateEffect?.InitializeEffect(currentTarget, cameraManager);
}
}
[YarnCommand("EyeEffect_Clean")]
public void EyeEffectClean()
{
if(currentTarget!=null)
if (currentTarget != null)
{
eyeStateEffect?.CleanupEffect(currentTarget);
}
}
[YarnCommand("set_EyeState")]
public void SetEyeStateForYarn(string state)
{
EyeState eyeState;
// Try to parse the string as an EyeState
if (!Enum.TryParse(state, true, out eyeState))
{
throw new ArgumentException("Invalid eye state: " + state, nameof(state));
}
// Start the coroutine for setting the eye state
SetEyeState(eyeState);
}
private void SetEyeState(EyeState state)
{
// 保存旧的状态
//oldEyeStateEffect = eyeStateEffect;
switch (state)
[YarnCommand("set_EyeState")]
public void SetEyeStateForYarn(string state)
{
case EyeState.CanImagineColor:
eyeStateEffect = new CanImagineColorEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.CannotImagineColor:
eyeStateEffect = new CannotImagineColorEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.EyeDisorder:
eyeStateEffect = new EyeDisorderEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.CanSeeColor:
eyeStateEffect = new CanSeeColorEffect();
//isFirstSetTargetAfterStateChange = false;
break;
case EyeState.HaveChip:
eyeStateEffect = new HaveChip();
//isFirstSetTargetAfterStateChange = false;
break;
default:
throw new ArgumentException("Unknown eye state: " + state.ToString(), nameof(state));
}
}
[YarnCommand("Set_Saturation")]
public IEnumerator Set_Saturation(float targetSaturation, float duration)
{
// 确保 targetSaturation 在 0 到 1 之间
targetSaturation = Mathf.Clamp01(targetSaturation);
EyeState eyeState;
Material material = eyeImage.material;
Sequence saturationSequence = DOTween.Sequence();
// 使用映射函数将目标饱和度转换为 ColorAdjustments 的范围
float mappedSaturation = MapSaturation(targetSaturation);
// 同时启动材质的饱和度变化和 ColorAdjustments 的饱和度变化
saturationSequence.Join(material.DOFloat(targetSaturation, "_HsvSaturation", duration));
// 获取 Tween 对象并添加到序列中
Tween saturationTween = ScreenEffectManager.Instance.TweenSaturation(mappedSaturation, duration);
if (saturationTween != null)
{
saturationSequence.Join(saturationTween);
}
// 启动 Sequence 并等待完成
yield return saturationSequence.WaitForCompletion();
}
private float MapSaturation(float input)
{
return Mathf.Lerp(-100, 0, input);
}
private Sequence glitchin;
[YarnCommand("EyeGlitch_in")]
public IEnumerator EyeGlitch_in()
{
glitchin = DOTween.Sequence();
Material material = eyeImage.material;
if(eyeImage==null)
{
Debug.LogError("No eyeImage");
yield break;
}
// AudioManager.RandomPlayInteraction("colorcorrect_in");
// AudioManager.PlayLoopAudio("colorcorrect_loop");
// _HsvShift 从 0 ~ 360 来回变化
hsvShiftTween = DOTween.To(() => material.GetFloat("_HsvShift"), x => material.SetFloat("_HsvShift", x), 360, 1f)
.SetLoops(-1, LoopType.Yoyo);
glitchin.Append(hsvShiftTween);
// _GlitchAmount 1 秒内从 0 ~ 8
glitchin.Insert(0, DOTween.To(() => material.GetFloat("_GlitchAmount"), x => material.SetFloat("_GlitchAmount", x), 8, 1f));
// _WarpStrength 1 秒内从 0 ~ 0.015
glitchin.Insert(0, DOTween.To(() => material.GetFloat("_WarpStrength"), x => material.SetFloat("_WarpStrength", x), 0.015f, 1f));
yield return new WaitForSeconds(1f);
}
[YarnCommand("EyeGlitch_out")]
public void EyeGlitch_out(float duration)
{
Material material = eyeImage.material;
if(eyeImage==null)
{
Debug.LogError("No eyeImage");
return;
}
if (glitchin != null && glitchin.IsActive())
{
glitchin.Kill();
}
material.DOFloat(0,"_WarpStrength", duration);
material.DOFloat(0,"_GlitchAmount", duration);
material.DOFloat(0,"_HsvShift", duration);
// 确保之前的动画被停止
}
[YarnCommand("set_EyeColor")]
public IEnumerator SetEyeColor(string color,string memoryName=null)
{
Material material = eyeImage.material;
Material memoryMaterial = memoryRender.material;
memoryRender.sprite = null;
memoryMaterial.SetFloat("_FullDistortionFade", 0f);
memoryMaterial.SetFloat("_SqueezePower", 18f);
if(eyeImage==null)
{
Debug.LogError("No eyeImage");
yield break;
}
if (memoryName!=null)
{
Sprite memorySprite = Resources.Load<Sprite>("Art/Memory/" + memoryName);
if (memorySprite == null)
// Try to parse the string as an EyeState
if (!Enum.TryParse(state, true, out eyeState))
{
Debug.LogWarning("Memory not found: " + memoryName);
throw new ArgumentException("Invalid eye state: " + state, nameof(state));
}
// Start the coroutine for setting the eye state
SetEyeState(eyeState);
}
private void SetEyeState(EyeState state)
{
// 保存旧的状态
//oldEyeStateEffect = eyeStateEffect;
switch (state)
{
case EyeState.CanImagineColor:
eyeStateEffect = new CanImagineColorEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.CannotImagineColor:
eyeStateEffect = new CannotImagineColorEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.EyeDisorder:
eyeStateEffect = new EyeDisorderEffect();
//isFirstSetTargetAfterStateChange = true;
break;
case EyeState.CanSeeColor:
eyeStateEffect = new CanSeeColorEffect();
//isFirstSetTargetAfterStateChange = false;
break;
case EyeState.HaveChip:
eyeStateEffect = new HaveChip();
//isFirstSetTargetAfterStateChange = false;
break;
default:
throw new ArgumentException("Unknown eye state: " + state.ToString(), nameof(state));
}
}
[YarnCommand("Set_Saturation")]
public IEnumerator Set_Saturation(float targetSaturation, float duration)
{
// 确保 targetSaturation 在 0 到 1 之间
targetSaturation = Mathf.Clamp01(targetSaturation);
Material material = eyeImage.material;
Sequence saturationSequence = DOTween.Sequence();
// 使用映射函数将目标饱和度转换为 ColorAdjustments 的范围
float mappedSaturation = MapSaturation(targetSaturation);
// 同时启动材质的饱和度变化和 ColorAdjustments 的饱和度变化
saturationSequence.Join(material.DOFloat(targetSaturation, "_HsvSaturation", duration));
// 获取 Tween 对象并添加到序列中
Tween saturationTween = ScreenEffectManager.Instance.TweenSaturation(mappedSaturation, duration);
if (saturationTween != null)
{
saturationSequence.Join(saturationTween);
}
// 启动 Sequence 并等待完成
yield return saturationSequence.WaitForCompletion();
}
private float MapSaturation(float input)
{
return Mathf.Lerp(-100, 0, input);
}
private Sequence glitchin;
[YarnCommand("EyeGlitch_in")]
public IEnumerator EyeGlitch_in()
{
glitchin = DOTween.Sequence();
Material material = eyeImage.material;
if (eyeImage == null)
{
Debug.LogError("No eyeImage");
yield break;
}
memoryRender.sprite = memorySprite;
// 使 memoryRender 可见
memoryRender.gameObject.SetActive(true);
// AudioManager.RandomPlayInteraction("colorcorrect_in");
// AudioManager.PlayLoopAudio("colorcorrect_loop");
// _HsvShift 从 0 ~ 360 来回变化
hsvShiftTween = DOTween
.To(() => material.GetFloat("_HsvShift"), x => material.SetFloat("_HsvShift", x), 360, 1f)
.SetLoops(-1, LoopType.Yoyo);
glitchin.Append(hsvShiftTween);
// 创建一个新的 DOTween 序列
Sequence memorySequence = DOTween.Sequence();
// _GlitchAmount 1 秒内从 0 ~ 8
glitchin.Insert(0,
DOTween.To(() => material.GetFloat("_GlitchAmount"), x => material.SetFloat("_GlitchAmount", x), 8, 1f));
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", 1.5f));
memorySequence.AppendInterval(1.5f);
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", 2f));
memorySequence.Insert(4.5f, memoryMaterial.DOFloat(0f, "_FullDistortionFade", 0.5f).OnComplete(() =>
// _WarpStrength 1 秒内从 0 ~ 0.015
glitchin.Insert(0,
DOTween.To(() => material.GetFloat("_WarpStrength"), x => material.SetFloat("_WarpStrength", x), 0.015f,
1f));
yield return new WaitForSeconds(1f);
}
[YarnCommand("EyeGlitch_out")]
public void EyeGlitch_out(float duration)
{
Material material = eyeImage.material;
if (eyeImage == null)
{
memoryRender.gameObject.SetActive(false);
AudioManager.RandomPlayInteraction("water_drip");
}));
Debug.LogError("No eyeImage");
return;
}
if (glitchin != null && glitchin.IsActive())
{
glitchin.Kill();
}
material.DOFloat(0, "_WarpStrength", duration);
material.DOFloat(0, "_GlitchAmount", duration);
material.DOFloat(0, "_HsvShift", duration);
// 确保之前的动画被停止
}
[YarnCommand("set_EyeColor")]
public IEnumerator SetEyeColor(string color, string memoryName = null)
{
Material material = eyeImage.material;
Material memoryMaterial = memoryRender.material;
memoryRender.sprite = null;
memoryMaterial.SetFloat("_FullDistortionFade", 0f);
memoryMaterial.SetFloat("_SqueezePower", 18f);
if (eyeImage == null)
{
Debug.LogError("No eyeImage");
yield break;
}
if (memoryName != null)
{
Sprite memorySprite = Resources.Load<Sprite>("Art/Memory/" + memoryName);
if (memorySprite == null)
{
Debug.LogWarning("Memory not found: " + memoryName);
yield break;
}
memoryRender.sprite = memorySprite;
// 使 memoryRender 可见
memoryRender.gameObject.SetActive(true);
// 创建一个新的 DOTween 序列
Sequence memorySequence = DOTween.Sequence();
memorySequence.Append(memoryMaterial.DOFloat(0.85f, "_FullDistortionFade", 1.5f));
memorySequence.AppendInterval(1.5f);
memorySequence.Append(memoryMaterial.DOFloat(0f, "_SqueezePower", 2f));
memorySequence.Insert(4.5f, memoryMaterial.DOFloat(0f, "_FullDistortionFade", 0.5f).OnComplete(() =>
{
memoryRender.gameObject.SetActive(false);
AudioManager.RandomPlayInteraction("water_drip");
}));
// 等待序列完成
yield return memorySequence.WaitForCompletion();
}
Sequence sequence = DOTween.Sequence();
// 添加一个 tween 来改变 _RoundWaveStrength 的值
sequence.Append(material.DOFloat(1, "_RoundWaveStrength", 2)).OnComplete(() => { EyeGlitch_out(0.5f); });
// 根据颜色改变 _ColorChangeTolerance 的值
switch (color.ToLower())
{
case "blue":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
break;
case "red":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance3", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
break;
case "green":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance2", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
break;
case "All":
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
break;
default:
Debug.LogWarning("Unknown color: " + color);
break;
}
// 添加一个 tween 来将 _RoundWaveStrength 的值回复为 0
sequence.Append(material.DOFloat(0, "_RoundWaveStrength", 0.5f));
// 开始这个序列
sequence.Play();
// 等待序列完成
yield return memorySequence.WaitForCompletion();
yield return sequence.WaitForCompletion();
}
Sequence sequence = DOTween.Sequence();
// 添加一个 tween 来改变 _RoundWaveStrength 的值
sequence.Append(material.DOFloat(1, "_RoundWaveStrength", 2)).OnComplete(() =>
[YarnCommand("EyeGetColor")]
public void GetColor()
{
SetEyeState(EyeState.CanImagineColor);
// 对目标列表中的每个目标执行 ColorBack 方法
foreach (EyeTarget target in targets)
{
EyeGlitch_out(0.5f);
});
// 根据颜色改变 _ColorChangeTolerance 的值
switch (color.ToLower())
{
case "blue":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
break;
case "red":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance3", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
break;
case "green":
sequence.Join(material.DOFloat(0, "_ColorChangeTolerance2", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
break;
case "All":
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance2", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance", 2));
sequence.Join(material.DOFloat(1, "_ColorChangeTolerance3", 2));
break;
default:
Debug.LogWarning("Unknown color: " + color);
break;
target.ColorBack();
}
// 切换到 CanImagineColorEffect 状态
}
// 添加一个 tween 来将 _RoundWaveStrength 的值回复为 0
sequence.Append(material.DOFloat(0, "_RoundWaveStrength", 0.5f));
// 开始这个序列
sequence.Play();
// 等待序列完成
yield return sequence.WaitForCompletion();
}
[YarnCommand("EyeGetColor")]
public void GetColor()
{
SetEyeState(EyeState.CanImagineColor);
// 对目标列表中的每个目标执行 ColorBack 方法
foreach (EyeTarget target in targets)
public void LostColor()
{
target.ColorBack();
// 对目标列表中的每个目标执行 ColorBack 方法
foreach (EyeTarget target in targets)
{
target.ColorLost();
}
}
// 切换到 CanImagineColorEffect 状态
}
public void LostColor()
{
// 对目标列表中的每个目标执行 ColorBack 方法
foreach (EyeTarget target in targets)
{
target.ColorLost();
}
}
}
}
+44 -3
View File
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
@@ -74,10 +75,50 @@ namespace AibisDream.Utility
public static Vector3 GetMouseWorldPos(Vector3 mousePoint, Transform transform)
{
if (!_mainCam) _mainCam = Camera.main;
mousePoint.z = _mainCam.WorldToScreenPoint(transform.position).z;
return _mainCam.ScreenToWorldPoint(mousePoint);
}
}
}
/// <summary>
/// 属性复制
/// </summary>
/// <param name="source">属性源</param>
/// <param name="target">属性目标</param>
public static void CopyProperties(object source, object target)
{
var sourceProperties = source.GetType().GetProperties();
var targetProperties = target.GetType().GetProperties();
foreach (var sourceProperty in sourceProperties)
{
var targetProperty = targetProperties.FirstOrDefault(p =>
p.Name == sourceProperty.Name && p.PropertyType == sourceProperty.PropertyType);
if (targetProperty != null && targetProperty.CanWrite)
{
targetProperty.SetValue(target, sourceProperty.GetValue(source));
}
}
}
#region
public static T As<T>(this object selfObj) where T : class
{
return selfObj as T;
}
public static T Self<T>(this T self, Action<T> onDo)
{
onDo?.Invoke(self);
return self;
}
public static T Self<T>(this T self, Func<T, T> onDo)
{
return onDo.Invoke(self);
}
#endregion
}
}
+12
View File
@@ -69,6 +69,12 @@ namespace AibisDream.Utility
return jObject.Properties().Select(jProp => jProp.Name).ToArray();
}
public static JObject ReadJObject(string path)
{
string json = File.ReadAllText(path);
return JObject.Parse(json);
}
/// <summary>
/// 保存Bean
/// </summary>
@@ -81,6 +87,12 @@ namespace AibisDream.Utility
File.WriteAllText(path, json);
}
public static void SaveJObject(JObject jObject, string path)
{
string json = jObject.ToString();
File.WriteAllText(path, json);
}
/// <summary>
/// 保存类
/// </summary>