游戏编程精粹学习 - 使用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 ...
随机推荐
- 文档工具GitBook使用
一.登陆注册 地址:https://www.gitbook.com/ 1.gitbook可使用github账号登录,如果已经注册github可以直接使用github账号登录 2.如果是github账号 ...
- split应用
/* input:"5 35 53 2 3" output:"2 3 5 35 53" */ public class RegexDemo4 { public ...
- 最全Python爬虫总结(转载)
[html] view plain copy 最近总是要爬取一些东西,索性就把Python爬虫的相关内容都总结起来了,自己多动手还是好. (1)普通的内容爬取(2)保存爬取的图片/视频和文件和网页(3 ...
- 移动端H5页面返回并且刷新页面(BFcache)
项目中的需求:点击浏览器中的返回按钮,要让页面重新加载资源.因为这部分的资源每次去加载的内容都不一样,如果返回的时候,还是看到原先的内容,那做这个内容块的意义就很小了:而如果用户看完了这部分内容,再返 ...
- Linux输入设备详解
<什么是Linux输入设备> ➤简介 Linux输入设备总类繁杂,常见的包括有按键.键盘.触摸屏.鼠标.摇杆等等,他们本身就是字符设备,而linux内核将这些设备的共同性抽象出来 ...
- [清橙A1210]光棱坦克
[清橙A1210]光棱坦克 题目大意: 平面上放置了\(n(n\le7000)\)个反射装置,光纤将从某个装置出发,在经过一处装置时发生反射,若经过的装置坐标依次为\((x_1,y_1),(x_2,y ...
- C++学习笔记44:继承与派生
类的组合,类的继承 类的组合(汽车类,轮子类,此时可以把轮子类组合到汽车类:) 类的继承(交通工具类,汽车类,此时汽车类可以派生自交通工具类:) 组合:常用描述has a.. 继承:常用描述is a ...
- 使用Quartz搭建定时任务脚手架
定时任务的实现有很多种,在Spring项目中使用一个注解 @Scheduled就可以很快搞定. 但是很难去管理项目中的定时任务,比如说:系统中有多少定时任务,每个定时任务执行规则,修改执行规则,暂停任 ...
- TXB0108 TXS0108E 8-Bit Bidirectional Voltage-Level Translator for Open-Drain and Push-Pull Applications
TXS(开漏优化设计),如I2C TXB(上拉优化设计),如SPI TXS0108 has integrated pull-up resistors to save board space and c ...
- java并发之如何解决线程安全问题
并发(concurrency)一个并不陌生的词,简单来说,就是cpu在同一时刻执行多个任务. 而Java并发则由多线程实现的. 在jvm的世界里,线程就像不相干的平行空间,串行在虚拟机中.(当然这是比 ...