unity3D 封装全局更新函数

  开发中必不可少的会遇到需要每一帧刷新的境况,一般是用MonoBehaviour中的Update函数。然而开发中不可能每个对象都继承MonoBehaviour,因此需要我们封装一个自己的可以在全局调用的更新函数。

  封装全局更新需要考虑到下面几点:

  1、全局性,可以在任何一个对象中调用,且在切换场景的时候也可以正常使用。

  2、生命周期,需要可以方便的添加移除。

  说道全局性,首先想到的是静态和单例,切换场景可以正常使用就需要用到Object.DontDestroyOnLoad(go);。

  我们先封装一个全局的GameObject,用于挂载更新和其他全局组件。这个对象只需要两个功能,一个是添加组件,另一个是获取对象。代码非常简单,就不做过多说明。

  

using UnityEngine;
public static class GlobalObject
{
    private static GameObject globalObject = null;

    public static T AddComponent<T>() where T : MonoBehaviour
    {
        T component = GlobalObj.GetComponent<T>();
        if (component == null)
        {
            component = GlobalObj.AddComponent<T>();
        }
        return component;
    } 

    public static GameObject GlobalObj
    {
        get
        {
            if (globalObject == null)
            {
                globalObject = GameObject.Find("_GlobalObject");
                if (globalObject == null)
                    globalObject = new GameObject("_GlobalObject");
                Object.DontDestroyOnLoad(globalObject);
            }
            return globalObject;
        }
    }
}

  更新函数依旧在MonoBehaviour调用,因为我们不可能都继承MonoBehaviour,所以我们用一个接口,让需要更新的对象继承接口,然后在一个封装好的AllUpdate中调用。

public interface IZUpdate
{
    void ZUpdate();
}

  在封装AllUpdate时,需要两个列表,分别记录当前更新列表和已移除列表。三个核心方法,移除、添加、更新,还有一个单例。代码如下

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

public class AllUpdate : MonoBehaviour
{
    private static AllUpdate _allUpdate;
    private List<IZUpdate> updateList = new List<IZUpdate>();
    private List<IZUpdate> removeList=new List<IZUpdate>();
    private static AllUpdate allUpdate
    {
        get
        {
            if (_allUpdate == null)
            {
                try
                {
                    _allUpdate = GlobalObject.AddComponent<AllUpdate>();
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
            return _allUpdate;
        }
    }
    public static void AddUpdate(IZUpdate update)
    {
        allUpdate.updateList.Add(update);
    }
    public static void RemoveUpdate(IZUpdate update)
    {
        allUpdate.removeList.Add(update);
    }
    private void RemoveUpdate()
    {
        while (removeList.Count>0)
        {
            updateList.Remove(removeList[0]);
            removeList.RemoveAt(0);
        }
    }
    void Update()
    {
        RemoveUpdate();

        for (int i = 0; i < updateList.Count; i++)
        {
            if (removeList.IndexOf(updateList[i])==-1)
            {
                if (updateList[i] == null) continue;
                updateList[i].ZUpdate();
            }
        }
    }
}

  讲上面三处代码添加到unity工程里,就可以直接用了,下面是我写的一个简单测试。我把这个脚本挂载主摄像机上的。

using UnityEngine;
using System.Collections;

public class TestUpdate : MonoBehaviour, IZUpdate
{
    public float time;
    void OnGUI()
    {
        if (GUI.Button(new Rect(50, 250, 200, 20), "添加更新"))
        {
            AllUpdate.AddUpdate(this);
        }
        if (GUI.Button(new Rect(280, 250, 200, 20), "移除更新"))
        {
            AllUpdate.RemoveUpdate(this);
        }
    }

    public void ZUpdate()
    {
        time += Time.deltaTime;
        if (time > 1)
        {
            time = 0;
            Debug.Log("每隔一秒打印一次" + Time.time);
        }
    }
}

我发现我不太会写博客,就直接上代码了,有问题可以直接问我。

  

  

原文地址:https://www.cnblogs.com/lihangppz/p/9749914.html