本文简述了 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,一切表现都很正常,直到我们支持了在过场动画中进行游戏截屏…:
考虑在过场动画中进行游戏截屏的逻辑过程:
上面所述的第三步中产生了问题(过场动画还没结束就显示了游戏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).