游戏中的双缓冲模式试验

大憨熊 提交于 2019-12-04 13:43:29

我们假设一个游戏,舞台上有三个演员(A,B,C),每个演员有一个自己面对的演员且成一个环(A面对B,B面对C,C面对A)。我们可以扇一个演员的耳光,这个演员不管谁扇的他,他都会去扇他面对的演员(所以我们只要任意扇一个人,他们就会一直成环的扇下去)。

首先写好演员的类:

    public class Actor
    {
        private string m_sName;      //名字
        private bool m_bIsSlapped;   //是否被扇
        private Actor m_facedActor;  //面对的演员

        public string Name
        {
            set { m_sName = value; }
            get { return m_sName; }
        }

        public Actor(string name)
        {
            m_sName = name;
            Reset();  //构造时设为未被扇
        }

        public void Face(Actor actor)  //设置面对演员
        {
            m_facedActor = actor;
        }

        public void Reset()  //重置状态
        {
            m_bIsSlapped = false;
        }

        public void Slap()  //被扇
        {
            m_bIsSlapped = true;
        }

        public bool WasSlapped()  //是否被扇
        {
            return m_bIsSlapped;
        }

        public void CheckStatus()  //检查状态,并作出输出
        {
            if (WasSlapped())
            {
                Reset();
                Debug.Log(Name + " was slapped, so " + Name + " slapped " + m_facedActor.Name);
                m_facedActor.Slap();
            }
            else
            {
                Debug.Log(Name + " was not slapped, so nothing happens");
            }
        }
    }

然后是主类:

    public class DoubleBufferMain : MonoBehaviour
    {

        private Actor[] actors = new Actor[3];
        
        void Start()
        {
            Actor april = new Actor("April");
            Actor bella = new Actor("Bella");
            Actor charlie = new Actor("Charlie");
            april.Face(bella);
            bella.Face(charlie);
            charlie.Face(april);
            actors[0] = april;
            actors[1] = bella;
            actors[2] = charlie;

            april.Slap();  //扇A
            CheckStatus();
        }

        private void CheckStatus()
        {
            for(int i = 0; i < actors.Length; i ++)
            {
                actors[i].CheckStatus();
            }
            Invoke("CheckStatus", 1);  //每一秒检测一下状态
        }
    }

在这种情况下每个演员都会在自己被扇的同一帧扇下一个演员,他们会无限的互相伤害下去。

但是,如果我们换一下他们在主类里actors里的顺序,会发现输出的结果会发生错误,有的演员会再被扇的同一帧做出反应,有的演员会再被扇的下一帧做出反馈。

只因为我们改变了顺序,两次输出的结果就不一样了(第一次每帧都是3人扇人,第二次每帧有1个或者2个人扇人),显然我们的结果我应该因为仅仅因为我们改变了数组中演员的顺序就发生了改变,所以需要引入双缓冲的模式。修改后的Actor类和主类:

    public class Actor
    {
        private string m_sName;      //名字
        private bool m_bIsCurrentSlapped;   //当前是否被扇
        private bool m_bIsNextSlapped;   //next是否被扇
        private Actor m_facedActor;  //面对的演员

        public string Name
        {
            set { m_sName = value; }
            get { return m_sName; }
        }

        public Actor(string name)
        {
            m_sName = name;
            m_bIsCurrentSlapped = false;
            m_bIsNextSlapped = false;
        }

        public void Face(Actor actor)  //设置面对演员
        {
            m_facedActor = actor;
        }

        public void Slap()  //被扇
        {
            m_bIsNextSlapped = true;
        }

        public void Swap()  //交换状态
        {
            m_bIsCurrentSlapped = m_bIsNextSlapped;
            m_bIsNextSlapped = false;
        }

        public bool WasSlapped()  //是否被扇
        {
            return m_bIsCurrentSlapped;
        }

        public void CheckStatus()  //检查状态,并作出输出
        {
            if (WasSlapped())
            {
                Debug.Log(Name + " was slapped, so " + Name + " slapped " + m_facedActor.Name);
                m_facedActor.Slap();
            }
            else
            {
                Debug.Log(Name + " was not slapped, so nothing happens");
            }
        }
    }
    
    public class DoubleBufferMain : MonoBehaviour
    {

        private Actor[] actors = new Actor[3];
        // Start is called before the first frame update
        void Start()
        {
            Actor april = new Actor("April");
            Actor bella = new Actor("Bella");
            Actor charlie = new Actor("Charlie");
            april.Face(bella);
            bella.Face(charlie);
            charlie.Face(april);
            actors[0] = april;
            actors[1] = bella;
            actors[2] = charlie;

            april.Slap();  //扇A
            CheckStatus();
        }

        private void CheckStatus()
        {
            for (int i = 0; i < actors.Length; i ++)
            {
                actors[i].CheckStatus();
            }
            for (int i = 0; i < actors.Length; i++)
            {
                actors[i].Swap();
            }
            Invoke("CheckStatus", 1);  //每一秒检测一下状态
        }
    }

此时不管我们怎么改变演员的顺序,每帧获得的结果都是一样的,并且每个演员都会在自己被扇到的下一帧去扇下一个人。两次结果都是:

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!