提交
This commit is contained in:
@@ -8,6 +8,7 @@ using DG.Tweening;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace AibisDream.FixSystem
|
||||
{
|
||||
@@ -27,10 +28,17 @@ namespace AibisDream.FixSystem
|
||||
private SpriteRenderer _targetSpriteRenderer; // 目标的 SpriteRenderer
|
||||
|
||||
private SpriteRenderer _cutSpriteRenderer;
|
||||
|
||||
private SpriteRenderer _cutTextRenderer; // 添加cutText的SpriteRenderer引用
|
||||
|
||||
private CutLine _cutLine;
|
||||
|
||||
[Header("CutText闪烁效果")]
|
||||
private float cutTextFlickerThreshold = 0.7f; // 开始闪烁的阈值
|
||||
private float cutTextFlickerInterval = 0.1f; // 闪烁间隔
|
||||
private float cutTextFlickerTimer = 0f; // 闪烁计时器
|
||||
private bool isCutTextFlickering = false; // 是否正在闪烁
|
||||
private Coroutine flickerCoroutine; // 闪烁协程引用
|
||||
|
||||
#endregion
|
||||
|
||||
// 模块基本数据
|
||||
@@ -54,6 +62,10 @@ namespace AibisDream.FixSystem
|
||||
_originalMaterial = _targetSpriteRenderer.GetComponent<SpriteRenderer>().material;
|
||||
|
||||
_cutSpriteRenderer = transform.Find("Cut Pic")?.GetComponent<SpriteRenderer>();
|
||||
if (_cutSpriteRenderer != null)
|
||||
{
|
||||
_cutTextRenderer = _cutSpriteRenderer.transform.Find("Cut Text")?.GetComponent<SpriteRenderer>(); // 初始化cutText的SpriteRenderer
|
||||
}
|
||||
|
||||
_highlightMaterial = Resources.Load<Material>("Materials/HighlightMaterial");
|
||||
_alarmMaterial = Resources.Load<Material>("Materials/AlarmMaterial");
|
||||
@@ -128,9 +140,16 @@ namespace AibisDream.FixSystem
|
||||
{
|
||||
_bodyModuleSystem.RemoveModule(this);
|
||||
|
||||
DialogController.Instance?.StartDialogNode($"{data.moduleName}CutDown");
|
||||
EnumEventSystem.Global.Send(EventEnum.CutEnd);
|
||||
Destroy(gameObject);
|
||||
DialogController.Instance?.StartDialogNode($"{data.moduleName}CutDown");
|
||||
EnumEventSystem.Global.Send(EventEnum.CutEnd);
|
||||
Destroy(gameObject);
|
||||
}
|
||||
public void SetCutTextVisible(bool visible)
|
||||
{
|
||||
if (_cutTextRenderer != null)
|
||||
{
|
||||
_cutTextRenderer.enabled = visible;
|
||||
}
|
||||
}
|
||||
|
||||
public SpriteRenderer GetCutSpriteRenderer()
|
||||
@@ -138,6 +157,54 @@ namespace AibisDream.FixSystem
|
||||
return _cutSpriteRenderer;
|
||||
}
|
||||
|
||||
public void StartCutTextFlicker()
|
||||
{
|
||||
if (!isCutTextFlickering)
|
||||
{
|
||||
isCutTextFlickering = true;
|
||||
if (flickerCoroutine != null)
|
||||
{
|
||||
StopCoroutine(flickerCoroutine);
|
||||
}
|
||||
flickerCoroutine = StartCoroutine(CutTextFlickerCoroutine());
|
||||
}
|
||||
}
|
||||
|
||||
public void StopCutTextFlicker()
|
||||
{
|
||||
isCutTextFlickering = false;
|
||||
if (flickerCoroutine != null)
|
||||
{
|
||||
StopCoroutine(flickerCoroutine);
|
||||
flickerCoroutine = null;
|
||||
}
|
||||
// 确保最终状态是可见的
|
||||
SetCutTextVisible(true);
|
||||
}
|
||||
|
||||
private IEnumerator CutTextFlickerCoroutine()
|
||||
{
|
||||
while (isCutTextFlickering)
|
||||
{
|
||||
// 随机决定是否显示
|
||||
bool shouldShow = UnityEngine.Random.value > 0.5f;
|
||||
SetCutTextVisible(shouldShow);
|
||||
|
||||
// 随机等待时间,模拟接触不良效果
|
||||
float waitTime = UnityEngine.Random.Range(cutTextFlickerInterval * 0.5f, cutTextFlickerInterval * 1.5f);
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateCutProgress(float progress)
|
||||
{
|
||||
// 检查是否达到闪烁阈值
|
||||
if (!isCutTextFlickering && progress >= cutTextFlickerThreshold)
|
||||
{
|
||||
StartCutTextFlicker();
|
||||
}
|
||||
}
|
||||
|
||||
// public void EnableCut()
|
||||
// {
|
||||
// // 打开或获取CutLine
|
||||
|
||||
@@ -134,6 +134,15 @@ namespace AibisDream
|
||||
{
|
||||
yield return PunchTapeSystem.StartCoroutine(PunchTapeSystem.PrintPunchTapes(count));
|
||||
}
|
||||
|
||||
[YarnCommand("DropCable")]
|
||||
public static void DropCable()
|
||||
{
|
||||
BodyModuleSystem.CableSystem.DropDownCable();
|
||||
}
|
||||
[YarnCommand("RetractCable")]
|
||||
public static void RetractCable()
|
||||
{
|
||||
BodyModuleSystem.CableSystem.PullUpCable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ using Cinemachine;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.Kit;
|
||||
using UnityEditor.Localization.Plugins.XLIFF.V12;
|
||||
using DG.Tweening;
|
||||
using System.Collections;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
@@ -12,10 +14,20 @@ namespace AibisDream
|
||||
{
|
||||
[Header("切割组件")]
|
||||
public GameObject gearFollowerPrefab;
|
||||
public GameObject entrancePanelPrefab; // 入场面板预制体
|
||||
public float entranceDuration = 1.5f; // 入场动画时长
|
||||
public float exitDuration = 1.5f; // 退场动画时长
|
||||
public float panelOffsetY = 2f; // 面板在相机视野下方的偏移量
|
||||
|
||||
private GearFollower gearFollower;
|
||||
private bool isCuttingMode = false;
|
||||
private bool isEntranceComplete = false; // 入场是否完成
|
||||
private bool isGearActive = false; // 标记gear是否已激活
|
||||
private BodyModule _targetModule;
|
||||
private SpriteRenderer _targetSpriteRenderer;
|
||||
private GameObject entrancePanel; // 入场面板实例
|
||||
private Camera _mainCamera;
|
||||
private CinemachineVirtualCamera _currentVirtualCamera;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -33,23 +45,63 @@ namespace AibisDream
|
||||
CameraKit.Instance.RegisterCamera(CameraEnum.CutEmoDeep, virtualCam4);
|
||||
CameraKit.Instance.RegisterCamera(CameraEnum.CutMemoryDeep, virtualCam5);
|
||||
CameraKit.Instance.RegisterCamera(CameraEnum.CutLogicDeep, virtualCam6);
|
||||
|
||||
_mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isCuttingMode && gearFollower != null)
|
||||
if (isCuttingMode && !isGearActive && gearFollower != null)
|
||||
{
|
||||
// 检测点击
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
Ray ray = _mainCamera.ScreenPointToRay(Input.mousePosition);
|
||||
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
|
||||
|
||||
if (hit.collider != null && hit.collider.gameObject.GetComponent<GearFollower>() != null)
|
||||
{
|
||||
gearFollower=hit.collider.gameObject.GetComponent<GearFollower>();
|
||||
ActivateGear();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isCuttingMode && isGearActive && gearFollower != null)
|
||||
{
|
||||
gearFollower.GearUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartCutting(BodyModule targetModule)
|
||||
private void ActivateGear()
|
||||
{
|
||||
isGearActive = true;
|
||||
if (gearFollower != null)
|
||||
{
|
||||
// 解除父子关系
|
||||
gearFollower.transform.SetParent(null);
|
||||
gearFollower.Init(_targetSpriteRenderer);
|
||||
}
|
||||
|
||||
// 面板退场
|
||||
if (entrancePanel != null)
|
||||
{
|
||||
Vector3 startPosition = GetPanelSpawnPosition();
|
||||
entrancePanel.transform.DOMove(startPosition, exitDuration)
|
||||
.SetEase(Ease.InBack)
|
||||
.OnComplete(() => {
|
||||
Destroy(entrancePanel);
|
||||
entrancePanel = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator StartCutting(BodyModule targetModule)
|
||||
{
|
||||
// 检查参数
|
||||
if (targetModule == null)
|
||||
{
|
||||
Debug.LogError("targetModule 为空");
|
||||
return;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// 保存目标模块
|
||||
@@ -60,7 +112,7 @@ namespace AibisDream
|
||||
if (_targetSpriteRenderer == null)
|
||||
{
|
||||
Debug.LogError("targetSprite 为空");
|
||||
return;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// 停止之前的切割
|
||||
@@ -68,21 +120,94 @@ namespace AibisDream
|
||||
|
||||
// 设置切割模式
|
||||
isCuttingMode = true;
|
||||
isEntranceComplete = false;
|
||||
|
||||
// 创建GearFollower
|
||||
Vector3 SpawnPosition = new Vector3(Screen.width / 2f, Screen.height / 4f, 0);
|
||||
GameObject gearFollowerObj = Instantiate(gearFollowerPrefab, SpawnPosition, Quaternion.identity);
|
||||
gearFollower = gearFollowerObj.GetComponent<GearFollower>();
|
||||
gearFollower.Init(_targetSpriteRenderer);
|
||||
// 创建入场面板
|
||||
CreateEntrancePanel();
|
||||
|
||||
// 等待入场动画完成
|
||||
yield return new WaitUntil(() => isEntranceComplete);
|
||||
}
|
||||
|
||||
private Vector3 GetPanelSpawnPosition()
|
||||
{
|
||||
if (_mainCamera == null)
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
|
||||
// 获取相机的位置和旋转
|
||||
Vector3 cameraPosition = _mainCamera.transform.position;
|
||||
Quaternion cameraRotation = _mainCamera.transform.rotation;
|
||||
|
||||
// 计算相机视野下方的位置
|
||||
Vector3 forward = cameraRotation * Vector3.forward;
|
||||
Vector3 right = cameraRotation * Vector3.right;
|
||||
Vector3 up = cameraRotation * Vector3.up;
|
||||
|
||||
// 计算相机视野的底部中心点
|
||||
float height = 2f * Mathf.Tan(_mainCamera.fieldOfView * 0.5f * Mathf.Deg2Rad) * _mainCamera.nearClipPlane;
|
||||
float width = height * _mainCamera.aspect;
|
||||
|
||||
// 计算面板的起始位置(在相机视野下方)
|
||||
Vector3 bottomCenter = cameraPosition + forward * _mainCamera.nearClipPlane - up * (height * 0.5f + panelOffsetY);
|
||||
|
||||
return bottomCenter;
|
||||
}
|
||||
|
||||
private void CreateEntrancePanel()
|
||||
{
|
||||
// 获取基于当前相机位置的生成位置
|
||||
Vector3 startPosition = GetPanelSpawnPosition();
|
||||
if (startPosition == Vector3.zero)
|
||||
{
|
||||
Debug.LogError("无法获取面板生成位置");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建入场面板,保持原始旋转
|
||||
entrancePanel = Instantiate(entrancePanelPrefab, startPosition, Quaternion.Euler(0,0,-90));
|
||||
|
||||
// 获取GearFollower组件(作为子物体)
|
||||
gearFollower = entrancePanel.GetComponentInChildren<GearFollower>();
|
||||
if (gearFollower == null)
|
||||
{
|
||||
Debug.LogError("入场面板预制体中没有找到GearFollower组件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算相机视野高度
|
||||
float height = 2f * Mathf.Tan(_mainCamera.fieldOfView * 0.5f * Mathf.Deg2Rad) * _mainCamera.nearClipPlane;
|
||||
|
||||
// 计算目标位置(相机视野中心偏下)
|
||||
Vector3 targetPosition = startPosition + _mainCamera.transform.up * 3.5f;
|
||||
|
||||
// 执行入场动画
|
||||
entrancePanel.transform.DOMove(targetPosition, entranceDuration)
|
||||
.SetEase(Ease.OutBack)
|
||||
.OnComplete(() => {
|
||||
isEntranceComplete = true;
|
||||
});
|
||||
}
|
||||
|
||||
public void OnCutComplete()
|
||||
{
|
||||
isCuttingMode = false;
|
||||
isEntranceComplete = false;
|
||||
isGearActive = false;
|
||||
|
||||
if (gearFollower != null)
|
||||
{
|
||||
gearFollower.FinishCutting();
|
||||
}
|
||||
|
||||
// 如果面板还存在,删除它
|
||||
if (entrancePanel != null)
|
||||
{
|
||||
Destroy(entrancePanel);
|
||||
entrancePanel = null;
|
||||
}
|
||||
}
|
||||
public void UpdateModule()
|
||||
{
|
||||
@@ -91,11 +216,62 @@ namespace AibisDream
|
||||
_targetModule.OnCuttingDown();
|
||||
}
|
||||
}
|
||||
public void SetCutTextVisible(bool visible)
|
||||
{
|
||||
if (_targetModule != null)
|
||||
{
|
||||
_targetModule.SetCutTextVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateCutProgress(float progress)
|
||||
{
|
||||
if (_targetModule != null)
|
||||
{
|
||||
_targetModule.UpdateCutProgress(progress);
|
||||
}
|
||||
}
|
||||
public void StartCutTextFlicker()
|
||||
{
|
||||
if (_targetModule != null)
|
||||
{
|
||||
_targetModule.StartCutTextFlicker();
|
||||
}
|
||||
}
|
||||
public void StopCutTextFlicker()
|
||||
{
|
||||
if (_targetModule != null)
|
||||
{
|
||||
_targetModule.StopCutTextFlicker();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopCutting()
|
||||
{
|
||||
isCuttingMode = false;
|
||||
if (gearFollower != null)
|
||||
isEntranceComplete = false;
|
||||
isGearActive = false;
|
||||
|
||||
if (_targetModule != null)
|
||||
{
|
||||
_targetModule.StopCutTextFlicker();
|
||||
}
|
||||
|
||||
if (entrancePanel != null)
|
||||
{
|
||||
// 获取当前相机位置
|
||||
Vector3 startPosition = GetPanelSpawnPosition();
|
||||
|
||||
// 执行退场动画
|
||||
entrancePanel.transform.DOMove(startPosition, exitDuration)
|
||||
.SetEase(Ease.InBack)
|
||||
.OnComplete(() => {
|
||||
Destroy(entrancePanel);
|
||||
entrancePanel = null;
|
||||
gearFollower = null;
|
||||
});
|
||||
}
|
||||
else if (gearFollower != null)
|
||||
{
|
||||
Destroy(gearFollower.gameObject);
|
||||
gearFollower = null;
|
||||
|
||||
@@ -6,6 +6,7 @@ using UnityEngine.VFX;
|
||||
using DG.Tweening;
|
||||
using AibisDream.FixSystem;
|
||||
using AibisDream; // 添加OpenSystem的命名空间
|
||||
using System.Collections;
|
||||
|
||||
public class GearFollower : MonoBehaviour
|
||||
{
|
||||
@@ -45,6 +46,12 @@ public class GearFollower : MonoBehaviour
|
||||
public float fadeOutDelay = 1f; // 淡出前的延迟时间
|
||||
public AudioClip cutCompleteSound; // 切割完成音效
|
||||
|
||||
[Header("CutText闪烁效果")]
|
||||
private float cutTextFlickerThreshold = 0.7f; // 开始闪烁的阈值
|
||||
private float cutTextFlickerInterval = 0.1f; // 闪烁间隔
|
||||
private float cutTextFlickerTimer = 0f; // 闪烁计时器
|
||||
private bool isCutTextFlickering = false; // 是否正在闪烁
|
||||
|
||||
private float totalEdgeLength = 0f; // 总边缘长度
|
||||
private float cutLength = 0f; // 已切割长度
|
||||
private bool isCutComplete = false;
|
||||
@@ -127,6 +134,14 @@ public class GearFollower : MonoBehaviour
|
||||
audioSource = gameObject.AddComponent<AudioSource>();
|
||||
audioSource.playOnAwake = false;
|
||||
audioSource.spatialBlend = 0f; // 2D音效
|
||||
|
||||
// 确保初始状态
|
||||
isCutting = false;
|
||||
isInTractionMode = false;
|
||||
if (sparkVFX != null)
|
||||
{
|
||||
sparkVFX.Stop();
|
||||
}
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
@@ -379,6 +394,13 @@ public class GearFollower : MonoBehaviour
|
||||
transform.position = targetPosition;
|
||||
currentState = State.Traction;
|
||||
isInTractionMode = true;
|
||||
|
||||
// 设置渲染顺序为5
|
||||
SpriteRenderer gearRenderer = GetComponent<SpriteRenderer>();
|
||||
if (gearRenderer != null)
|
||||
{
|
||||
gearRenderer.sortingOrder = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void UpdateTractionState(Vector2 mousePos)
|
||||
@@ -547,7 +569,12 @@ public class GearFollower : MonoBehaviour
|
||||
sparkVFX.Stop();
|
||||
}
|
||||
|
||||
|
||||
// 关闭切割光照
|
||||
if (cutLight != null)
|
||||
{
|
||||
cutLight.enabled = false;
|
||||
cutLight.intensity = 0f;
|
||||
}
|
||||
}
|
||||
private int FindNearestEdgePointIndex(Vector2 pos, out float minDist)
|
||||
{
|
||||
@@ -620,6 +647,13 @@ public class GearFollower : MonoBehaviour
|
||||
float progress = cutLength / totalEdgeLength;
|
||||
Debug.Log($"当前切割长度: {cutLength}, 总长度: {totalEdgeLength}, 进度: {progress * 100}%");
|
||||
|
||||
// 更新切割进度
|
||||
var cuttingManager = FixSystemCenter.SystemDic.Get<CuttingManager>();
|
||||
if (cuttingManager != null)
|
||||
{
|
||||
cuttingManager.UpdateCutProgress(progress);
|
||||
}
|
||||
|
||||
// 检查是否满足切割完成条件
|
||||
if (!isCutComplete && progress >= cutCompletionThreshold)
|
||||
{
|
||||
@@ -703,7 +737,7 @@ public class GearFollower : MonoBehaviour
|
||||
}
|
||||
public void FinishCutting()
|
||||
{
|
||||
// 清理特效
|
||||
// 清理特效
|
||||
if (cutLight != null)
|
||||
{
|
||||
cutLight.enabled = false;
|
||||
@@ -719,10 +753,19 @@ public class GearFollower : MonoBehaviour
|
||||
// 计算随机方向
|
||||
float randomAngle = Random.Range(-cutCompleteTiltAngle, cutCompleteTiltAngle);
|
||||
Vector2 randomOffset = Random.insideUnitCircle * cutCompleteOffset;
|
||||
var cuttingManager = FixSystemCenter.SystemDic.Get<CuttingManager>();
|
||||
if (cuttingManager != null)
|
||||
{
|
||||
cuttingManager.StopCutTextFlicker();
|
||||
cuttingManager.SetCutTextVisible(false);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 立即应用倾斜和位移
|
||||
targetSpriteRenderer.transform.rotation = Quaternion.Euler(0, 0, randomAngle);
|
||||
targetSpriteRenderer.transform.position = originalTargetPosition + (Vector3)randomOffset;
|
||||
|
||||
|
||||
// 创建动画序列
|
||||
cutCompleteSequence = DOTween.Sequence();
|
||||
@@ -751,7 +794,36 @@ public class GearFollower : MonoBehaviour
|
||||
cuttingManager.UpdateModule();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void StartCutTextFlicker()
|
||||
{
|
||||
var cuttingManager = FixSystemCenter.SystemDic.Get<CuttingManager>();
|
||||
if (cuttingManager != null)
|
||||
{
|
||||
// 开始闪烁效果
|
||||
StartCoroutine(CutTextFlickerCoroutine(cuttingManager));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator CutTextFlickerCoroutine(CuttingManager cuttingManager)
|
||||
{
|
||||
while (isCutTextFlickering && !isCutComplete)
|
||||
{
|
||||
// 随机决定是否显示
|
||||
bool shouldShow = Random.value > 0.5f;
|
||||
cuttingManager.SetCutTextVisible(shouldShow);
|
||||
|
||||
// 随机等待时间,模拟接触不良效果
|
||||
float waitTime = Random.Range(cutTextFlickerInterval * 0.5f, cutTextFlickerInterval * 1.5f);
|
||||
yield return new WaitForSeconds(waitTime);
|
||||
}
|
||||
|
||||
// 确保最终状态是可见的
|
||||
if (!isCutComplete)
|
||||
{
|
||||
cuttingManager.SetCutTextVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
|
||||
Reference in New Issue
Block a user