Tz2/Assets/Scripts/AutoHideScript.cs

251 lines
6.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using TMPro;
using UnityEngine;
/// <summary>
/// 自动隐藏脚本
/// 挂载在物体上,提供打开方法,打开后等待指定时间自动隐藏
/// 如果在等待期间再次调用打开方法,会重新计算等待时间
/// </summary>
public class AutoHideScript : MonoBehaviour
{
[Header("自动隐藏设置")]
[Tooltip("自动隐藏的延迟时间(秒)")]
[SerializeField] private float hideDelay = 3f;
[Tooltip("是否在开始时自动显示物体")]
[SerializeField] private bool showOnStart = true;
[Tooltip("是否启用调试日志")]
[SerializeField] private bool enableDebugLog = true;
[Header("CanvasGroup设置")]
[Tooltip("显示时的透明度")]
[SerializeField] private float showAlpha = 1f;
[Tooltip("隐藏时的透明度")]
[SerializeField] private float hideAlpha = 0f;
[Tooltip("是否禁用交互(隐藏时)")]
[SerializeField] private bool disableInteractionWhenHidden = true;
// CanvasGroup组件引用
private CanvasGroup canvasGroup;
// 用于取消当前等待任务的取消令牌源
private CancellationTokenSource cancellationTokenSource;
// 当前是否正在等待隐藏
private bool isWaitingToHide = false;
/// <summary>
/// 脚本启动时的初始化
/// </summary>
private void Start()
{
// 获取或添加CanvasGroup组件
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null)
{
canvasGroup = gameObject.AddComponent<CanvasGroup>();
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 为物体 {gameObject.name} 添加了CanvasGroup组件");
}
}
SetCanvasGroupAlpha(hideAlpha);
}
/// <summary>
/// 设置CanvasGroup的透明度
/// </summary>
/// <param name="alpha">透明度值0-1</param>
private void SetCanvasGroupAlpha(float alpha)
{
if (canvasGroup != null)
{
canvasGroup.alpha = alpha;
// 根据透明度设置交互状态
if (disableInteractionWhenHidden)
{
canvasGroup.interactable = alpha > 0.1f;
canvasGroup.blocksRaycasts = alpha > 0.1f;
}
}
}
/// <summary>
/// 显示物体并开始计时隐藏
/// </summary>
public void ShowObject(string title)
{
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 显示物体 {gameObject.name}");
}
transform.Find("text").GetComponent<TMP_Text>().text = title;
// 显示物体使用CanvasGroup透明度
SetCanvasGroupAlpha(showAlpha);
// 如果已经在等待隐藏,取消之前的等待任务
if (isWaitingToHide)
{
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 取消之前的隐藏任务,重新开始计时");
}
CancelCurrentHideTask();
}
// 开始新的隐藏等待任务
StartHideTask();
}
/// <summary>
/// 立即隐藏物体
/// </summary>
public void HideObject()
{
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 立即隐藏物体 {gameObject.name}");
}
// 取消当前的隐藏任务
CancelCurrentHideTask();
// 隐藏物体使用CanvasGroup透明度
SetCanvasGroupAlpha(hideAlpha);
}
/// <summary>
/// 取消当前的隐藏任务
/// </summary>
private void CancelCurrentHideTask()
{
if (cancellationTokenSource != null)
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
}
isWaitingToHide = false;
}
/// <summary>
/// 开始隐藏等待任务
/// </summary>
private void StartHideTask()
{
// 创建新的取消令牌源
cancellationTokenSource = new CancellationTokenSource();
isWaitingToHide = true;
// 使用UniTask异步等待
WaitAndHideAsync(cancellationTokenSource.Token).Forget();
}
/// <summary>
/// 异步等待并隐藏物体
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
private async UniTaskVoid WaitAndHideAsync(CancellationToken cancellationToken)
{
try
{
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 开始等待 {hideDelay} 秒后隐藏物体 {gameObject.name}");
}
// 等待指定时间
await UniTask.Delay(TimeSpan.FromSeconds(hideDelay), cancellationToken: cancellationToken);
// 等待完成后隐藏物体
if (gameObject != null)
{
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 等待完成,隐藏物体 {gameObject.name}");
}
SetCanvasGroupAlpha(hideAlpha);
}
}
catch (OperationCanceledException)
{
// 任务被取消,这是正常情况
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 隐藏任务被取消 {gameObject.name}");
}
}
catch (Exception ex)
{
// 处理其他异常
Debug.LogError($"AutoHideScript: 隐藏任务发生异常 {gameObject.name}: {ex.Message}");
}
finally
{
// 清理状态
isWaitingToHide = false;
}
}
/// <summary>
/// 设置隐藏延迟时间
/// </summary>
/// <param name="delay">延迟时间(秒)</param>
public void SetHideDelay(float delay)
{
hideDelay = Mathf.Max(0f, delay);
if (enableDebugLog)
{
Debug.Log($"AutoHideScript: 设置隐藏延迟时间为 {hideDelay} 秒");
}
}
/// <summary>
/// 获取当前是否正在等待隐藏
/// </summary>
/// <returns>如果正在等待隐藏返回true否则返回false</returns>
public bool IsWaitingToHide()
{
return isWaitingToHide;
}
/// <summary>
/// 获取当前的隐藏延迟时间
/// </summary>
/// <returns>隐藏延迟时间(秒)</returns>
public float GetHideDelay()
{
return hideDelay;
}
/// <summary>
/// 脚本销毁时清理资源
/// </summary>
private void OnDestroy()
{
CancelCurrentHideTask();
}
/// <summary>
/// 在Inspector中显示当前状态
/// </summary>
private void OnValidate()
{
// 确保延迟时间不为负数
hideDelay = Mathf.Max(0f, hideDelay);
// 确保透明度值在有效范围内
showAlpha = Mathf.Clamp01(showAlpha);
hideAlpha = Mathf.Clamp01(hideAlpha);
}
}