20

Sweet Snippet 之 BitMask

 3 years ago
source link: https://blog.csdn.net/tkokof1/article/details/105869486
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Sweet Snippet 之 BitMask

tkokof1 2020-04-30 21:01:11 110

本文简述了 BitMask 的(一种)使用场景和实现方法

游戏开发中往往会遇到不同游戏逻辑触发相同游戏操作的情况,举个简单的例子:在播放游戏过场动画时,我们往往需要隐藏游戏UI;而当我们进行游戏截屏时,往往也需要隐藏游戏UI.

假设显示/隐藏游戏UI的接口如下:

void SetUIActive(bool active);

按照上面所说的功能需求(过场动画和游戏截屏都需要隐藏游戏UI),我们可能会写下如下的代码:

void OnEnterCutscene()
{
    SetUIActive(false);
}

void OnLeaveCutscene()
{
    SetUIActive(true);
}

void OnEnterCapture()
{
    SetUIActive(false);
}

void OnLeaveCapture()
{
    SetUIActive(true);
}

至此我们实现了在过场动画和游戏截屏时隐藏游戏UI,一切表现都很正常,直到我们支持了在过场动画中进行游戏截屏…:

考虑在过场动画中进行游戏截屏的逻辑过程:

  • 首先我们进入过场动画(OnEnterCutscene),隐藏了游戏UI
  • 接着我们进入游戏截屏(OnEnterCapture),又隐藏了一次游戏UI
  • 接着我们退出游戏截屏(OnLeaveCapture),显示了游戏UI(Ops,过场动画还没结束就显示了游戏UI…)
  • 最后我们退出过场动画(OnLeaveCutscene),又显示了一次游戏UI

上面所述的第三步中产生了问题(过场动画还没结束就显示了游戏UI),本质原因是因为过场动画和游戏截屏进行了相同的逻辑操作,于是他们在非顺序执行时便产生了操作冲突.

解决该问题的一种方法就是使用 BitMask,即通过位掩码来"分离"相同的游戏操作,说的有些抽象,我们直接看源码便明白了~

首先是 BitMask 的实现:

using UnityEngine;

public class BitMask
{
    private int m_num;

    public BitMask(bool state = true)
    {
        m_num = state ? -1 : 0;
    }

    public bool Get(int maskIndex)
    {
        Debug.Assert(maskIndex >= 0 && maskIndex < 32, "[BitMask]BitMask only support mask index from 0 to 31, current mask index : " + maskIndex);
        return (m_num & (1 << maskIndex)) != 0;
    }

    public void Set(int maskIndex, bool maskValue)
    {
        Debug.Assert(maskIndex >= 0 && maskIndex < 32, "[BitMask]BitMask only support mask index from 0 to 31, current mask index : " + maskIndex);
        if (maskValue)
        {
            m_num = m_num | (1 << maskIndex);
        }
        else
        {
            m_num = m_num & ~(1 << maskIndex);
        }
    }

    public bool GetAll()
    {
        return AllBitsTrue();
    }

    public void SetAll(bool state)
    {
        m_num = state ? -1 : 0;
    }

    public bool AllBitsTrue()
    {
        return (~m_num) == 0;
    }

    public bool AnyBitTrue()
    {
        return m_num != 0;
    }

    public bool AllBitsFalse()
    {
        return m_num == 0;
    }

    public bool AnyBitFalse()
    {
        return (~m_num) != 0;
    }
}

使用上面的 BitMask,我们重新实现下之前的功能需求(过场动画和游戏截屏都需要隐藏游戏UI):

enum UIActiveMask 
{
    Cutscene = 0,
    Capture,
}

BitMask mask = new BitMask(true);

void OnEnterCutscene()
{
    mask.Set(UIActiveMask.Cutscene, false);
    SetUIActive(mask.GetAll());
}

void OnLeaveCutscene()
{
    mask.Set(UIActiveMask.Cutscene, true);
    SetUIActive(mask.GetAll());
}

void OnEnterCapture()
{
    mask.Set(UIActiveMask.Capture, false);
    SetUIActive(mask.GetAll());
}

void OnLeaveCapture()
{
    mask.Set(UIActiveMask.Capture, true);
    SetUIActive(mask.GetAll());
}

至此我们便通过 BitMask 解决了之前在过场动画中进行游戏截屏时出现的问题(过场动画还没结束就显示了游戏UI).


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK