第一种 缓存
csharp
public static class WaitCache
{
private static readonly Dictionary<float, WaitForSeconds> _cache = new();
public static WaitForSeconds Get(float seconds)
{
if (!_cache.TryGetValue(seconds, out var wait))
{
wait = new WaitForSeconds(seconds);
_cache[seconds] = wait;
}
return wait;
}
}
第二种 零GC优化版
csharp
using System.Collections;
using UnityEngine;
namespace GameScripts.Common
{
/// <summary>
/// 协程等待工具 - 零GC优化版
/// </summary>
public static class CoroutineUtility
{
// ==================== 工厂方法 ====================
public static WaitTime Wait(float seconds) => new WaitTime(seconds);
public static WaitRealtime WaitReal(float seconds) => new WaitRealtime(seconds);
public static WaitFrames Frames(int count) => new WaitFrames(count);
// ==================== 基于 Time.time(受TimeScale影响)====================
public readonly struct WaitTime : IEnumerator
{
private readonly float _endTime;
public WaitTime(float seconds)
{
_endTime = Time.time + seconds;
}
public bool MoveNext() => Time.time < _endTime;
public void Reset() { }
public object Current => null;
}
// ==================== 基于真实时间(不受TimeScale影响)====================
public readonly struct WaitRealtime : IEnumerator
{
private readonly float _endTime;
public WaitRealtime(float seconds)
{
_endTime = Time.realtimeSinceStartup + seconds;
}
public bool MoveNext() => Time.realtimeSinceStartup < _endTime;
public void Reset() { }
public object Current => null;
}
// ==================== 按帧等待(修复版)====================
public readonly struct WaitFrames : IEnumerator
{
private readonly int _targetFrame;
public WaitFrames(int frames)
{
_targetFrame = Time.frameCount + frames;
}
public bool MoveNext() => Time.frameCount < _targetFrame;
public void Reset() { }
public object Current => null;
}
// ==================== 条件等待(注意:lambda 有 GC)====================
public readonly struct WaitUntil : IEnumerator
{
private readonly System.Func<bool> _predicate;
public WaitUntil(System.Func<bool> predicate)
{
_predicate = predicate;
}
public bool MoveNext() => !_predicate();
public void Reset() { }
public object Current => null;
}
public readonly struct WaitWhile : IEnumerator
{
private readonly System.Func<bool> _predicate;
public WaitWhile(System.Func<bool> predicate)
{
_predicate = predicate;
}
public bool MoveNext() => _predicate();
public void Reset() { }
public object Current => null;
}
}
}