251 lines
6.9 KiB
C#
251 lines
6.9 KiB
C#
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);
|
||
}
|
||
|
||
}
|