游戏编程精粹学习 - 使用Bloom过滤来提高计算性能(BloomFilter)
原文在《游戏编程精粹2》的1.2中,BloomFilter是一种可以快速检测是否存在集合包含关系的数据结构,但有一定的误识别率。
该结构的优点
- 判断包含关系时效率较高,粗略测试了下比List快一倍(不拆分哈希)
- 由于内部是位数组BitArray,做交集并集几乎不产生开销
该结构的缺点
- 有一定的误识别率
- 使用情境有限
我在Github找了一个BloomFilter的库(这个库使用时会产生大量GC,但学习来用够了):
https://github.com/joeyrobert/bloomfilter
首先构建一个长度为N的位数组,将传入数据的哈希值按位拆分成不同段,每一个段作为一个Key放入这个长度为N的位数组。
判断包含时再把对象的多个key与位数组进行比较即可。
当然既然都存在误判率,而且是以效率为优先的话,也可以不按位拆分哈希,我写了一个最简单的版本:
public class MyBloomFilter<T>
{
BitArray mBitArray; public MyBloomFilter(int bitLength)
{
mBitArray = new BitArray(bitLength);
} public void Add(T obj)
{
var key = Mathf.Abs(obj.GetHashCode()) % mBitArray.Length; mBitArray[key] = true;
} public bool Contains(T obj)
{
var key = Mathf.Abs(obj.GetHashCode()) % mBitArray.Length;
return mBitArray[key];
}
}
注意C#已经内置了位数组这样的数据结构BitArray。
结合之前的可预测随机数(http://www.cnblogs.com/hont/p/8716586.html),我写了这样一个例子

假设这是一个草药采集的功能,每一个不同颜色的方块代表一颗草药
鼠标点击来采集它们。
代码如下
using System.Collections.Generic;
using UnityEngine; public class HerbGenerator : MonoBehaviour
{
public int x;
public int y;
public int probability = ;
List<HerbObject> mCreatedHerbList = new List<HerbObject>();
MyBloomFilter<int> mCollectedHerbList = new MyBloomFilter<int>(); void Update()
{
GetArea(x - , y - , x + , y + ); if (Input.GetMouseButtonDown())
{
var hit = default(RaycastHit);
var isHit = Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit);
if (isHit)
{
var herbObject = hit.transform.GetComponent<HerbObject>();
mCollectedHerbList.Add(herbObject.seed); Destroy(hit.transform.gameObject);
}
}
} void GetArea(int beginX, int beginY, int endX, int endY)
{
for (int i = ; i < mCreatedHerbList.Count; i++)
{
if (!mCreatedHerbList[i]) continue;
Destroy(mCreatedHerbList[i].gameObject);
} var cacheState = Random.state; mCreatedHerbList.Clear(); float spacingScale = 1f;//增加间距防止两颗草药同时消失.
for (int x = beginX, k = ; x < endX; x++)
{
for (int y = beginY; y < endY; y++, k++)
{
var seed = + x + y * (endX - beginX); if (mCollectedHerbList.Contains(seed)) continue; Random.InitState(seed);
var r = (int)(Random.value * ); if (r % < probability)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
var herbObject = cube.AddComponent<HerbObject>();
herbObject.seed = seed; cube.transform.position = new Vector3(x * spacingScale, , y * spacingScale); GalaxyBuild(r, cube); mCreatedHerbList.Add(herbObject);
}
}
} Random.state = cacheState;
} void GalaxyBuild(int seed, GameObject go)
{
var cacheState = Random.state;
Random.InitState(seed);
var meshRenderer = go.GetComponent<MeshRenderer>();
switch ((int)(Random.value * % ))
{
case ://草药类型1
meshRenderer.material.color = Color.red;
break; case ://草药类型2
meshRenderer.material.color = Color.blue;
break; case ://草药类型3
meshRenderer.material.color = Color.green;
break;
} Random.state = cacheState;
}
}
HerbGenerator
出现误判时会发生A草药采完后B草药同时消失的情况,只能增加草药刷新的间距来缓解这个问题。
游戏编程精粹学习 - 使用Bloom过滤来提高计算性能(BloomFilter)的更多相关文章
- C++游戏编程(一开篇)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7318264 作者:毛星云 邮箱: h ...
- c++游戏编程书籍
如果要自学游戏程序开发的话,可以看看下面的,呵呵. 游戏开发资料(PDF书都是中文版的,非英文,很多是本人自己扫描制作,从未网上发布过,所以独家啦): 1.Gamebryo 2.2游戏引擎(盛大.腾 ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- 工作流程,编程,调试,性能:Unity游戏开发者应该学习的20个改进技巧
Unity 是一个备受欢迎的游戏开发平台.它的功能令人印象深刻,同时也迎合了不同的游戏开发需求.游戏开发者可以使用 Unity 创建任何类型的游戏,从世界级的 RPG 游戏到最流行的增强现实游戏 Po ...
- 【Visual C++】游戏编程学习笔记之五:单一背景滚动
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之四:透明动画实现
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...
- 【Visual C++】游戏编程学习笔记之三:游戏循环的使用
本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44208419 作者:Zee ...
- 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
- 【Visual C++】游戏编程学习笔记之七:键盘输入消息
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
随机推荐
- Evolution ZOJ2853
矩阵太大导致爆栈 解决方法:矩阵不要开在main函数里面 全部在外面处理 main函数只能处理简单的赋值和加减 损失的要自减!! 最后为 sum+=t[i]*ans.m[i][n-1]; 得 ...
- 全排列-hdu1027
题目描述: 题目大意:现在给我们两个数字,N和M.我们应该编程找出由1到N组成的第M个最小序列.主要运用了全排列的思想,运用了全排列中next_permutation()函数: next_permut ...
- 是否可从一个static方法内发出对非static方法的调用?
不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用.也就是说,当一个static方法被调用时, ...
- 仙剑奇侠传 游戏 开发 教程 Xianjian qixia development Game development tutorial
仙剑奇侠传 开发 游戏 开发 教程 Xianjian qixia development Game development tutorial 作者:韩梦飞沙 Author:han_meng_fei_ ...
- loj#2012. 「SCOI2016」背单词
题目链接 loj#2012. 「SCOI2016」背单词 题解 题面描述有点不清楚. 考虑贪心 type1的花费一定不会是优的,不考虑, 所以先把后缀填进去,对于反串建trie树, 先填父亲再填儿子, ...
- 4826: [Hnoi2017]影魔
4826: [Hnoi2017]影魔 https://lydsy.com/JudgeOnline/problem.php?id=4826 分析: 莫队+单调栈+st表. 考虑如何O(1)加入一个点,删 ...
- POJ.3537.Crosses and Crosses(博弈论 Multi-SG)
题目链接 \(Description\) 有一个一行n列的棋盘,每个人每次往上放一个棋子,将三个棋子连在一起的人赢.问是否有必胜策略. \(Solution\) 首先一个人若在\(i\)处放棋子,那么 ...
- Android监听view的attached或detached状态
我们在开发中,希望监听View的attached或detached状态,来进行比如eventbus的注册与解注册的操作,非常的方便实用. 可以使用系统给我们提供的listener,代码使用如下: mV ...
- Centos7 MongoDB-3.4
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的 关系型数据库遵循ACID规则 事务在英文中是transaction,和现实世界中的交易很类 ...
- 在Win7 64位旗舰版下,利用Vs2008编译64位的Qt 4.8.2
1.下载qt-everywhere-opensource-src-4.8.2.zip. 2.VS2008需要安装x64编译器. 3.将qt-everywhere-opensource-src-4.8. ...