存档功能
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user