unity小工具-非实时的值变化监听器

文章介绍了如何在Unity项目中使用XValueObserve和IValueObserver接口实现对网络环境和值的非即时监听,当条件满足时触发提醒。这种方法适用于需要延迟通知的场景,对于实时需求则需采用其他设计策略,如事件管理器或重载属性设置。
摘要由CSDN通过智能技术生成

项目里有代码专门监听网络环境的变化,特别是在下载中,如果遇到断网或者切换为移动网络,可能需要触发提醒等等。这种需求可能是通用的,于是便写了一个通用的监听代码。是

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;

public delegate T XValueGetter<T>();

public interface IValueObserver
{
    long GetId();
    bool Check(long checkTime);
    bool ReachCheckTime(long checkTime);
    void NotifyChange();
}

public class XValueObserve<T> : IValueObserver
{
    public T CurrentValue;
    public long LastCheckTime;
    public XValueGetter<T> Getter { get; set; }
    public Action<T> OnValueChangeCallback { get; set; }

    public long CheckInterval;

    public long Id;

    public XValueObserve(long id, XValueGetter<T> getter, Action<T> onValueChangeCallback, long checkInterval)
    {
        Id = id;
        Getter = getter;
        OnValueChangeCallback = onValueChangeCallback;
        CheckInterval = checkInterval;
        
        LastCheckTime = 0;
        CurrentValue = getter();
    }

    public long GetId()
    {
        return Id;
    }

    public bool ReachCheckTime(long checkTime)
    {
        return checkTime - LastCheckTime >= CheckInterval;
    }

    public bool Check(long checkTime)
    {
        T currentValue = Getter();
        LastCheckTime = checkTime;
        if (!currentValue.Equals(CurrentValue))
        {
            CurrentValue = currentValue;
            return true;
        }
        return false;
    }

    public void NotifyChange()
    {
        OnValueChangeCallback?.Invoke(CurrentValue);
    }
}

public class XValueObserveManager
{
    private static Stopwatch s_stopWatch;

    private static long s_observerId;
    
    private static List<IValueObserver> s_observers;

    public static void Init()
    {
        s_observers = new List<IValueObserver>();
        s_stopWatch = new Stopwatch();
        s_observerId = 0;
    }

    public static void Start()
    {
        s_stopWatch.Start();
    }
    
    public static void Update()
    {
        foreach (IValueObserver observer in s_observers)
        {
            if (observer.ReachCheckTime(s_stopWatch.ElapsedMilliseconds))
            {
                if (observer.Check(s_stopWatch.ElapsedMilliseconds))
                {
                    observer.NotifyChange();
                }
            }
        }
    }

    public static long AddObserve<T>(XValueGetter<T> getter, Action<T> onValueChangeCallback, long checkInterval)
    {
        XValueObserve<T> observe = new XValueObserve<T>(s_observerId++, getter, onValueChangeCallback, checkInterval);
        s_observers.Add(observe);
        return observe.Id;
    }
    
    public static void RemoveObserve(long id)
    {
        s_observers.RemoveAll(observe => observe.GetId() == id);
    }
}

 使用起来,也比较方便

void Start()
{
    XValueObserveManager.Init();
    XValueObserveManager.Start();
    int posObserverId = XValueObserveManager.AddObserve(() => transform.position, pos =>
    {
        Debug.Log(pos);
    }, 1000);

    int netObserverId = XValueObserveManager.AddObserve(() => Application.internetReachability, reach =>
    {
        Debug.Log(reach.ToString());
    }, 1000);
}

注意,这种变化观察都是非及时性质的,也就是并不会在变化发生的瞬间通知,而是最少要延迟一帧(基于Update执行)。

如果需要的是实时的,则需要另外的设计了,比如用事件管理器,但对于一些通用的数值则可能需要封装为属性,重载set方法,广播事件了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值