Unity中无GC Alloc的CalculateFrustumPlanes
如果你需要在逻辑层做一些预先的剔除操作,可能需要从MainCamera构建视锥体,然后进行简易相交测试,这时候在unity里面用到的函数接口是CalculateFrustumPlanes:
namespace UnityEngine
{
// 摘要:
// Utility class for common geometric functions.
public sealed class GeometryUtility
{
public GeometryUtility(); // 摘要:
// Calculates frustum planes.
public static Plane[] CalculateFrustumPlanes(Camera camera);
//
// 摘要:
// Calculates frustum planes.
public static Plane[] CalculateFrustumPlanes(Matrix4x4 worldToProjectionMatrix);
//
// 摘要:
// Returns true if bounds are inside the plane array.
public static bool TestPlanesAABB(Plane[] planes, Bounds bounds);
}
}
然而它的主要问题是有gc alloc,每次调用都会自己new一个Plane数组,这很明显是不科学的,然而unity迟迟未修复此问题。
下面提供的函数在C#层中重新实现了这个接口,同时没有gcalloc,然而由于在C#中实现的原因,其效率比引擎提供的C++版本慢一倍。C#版本实测一次调用在0.01毫秒左右。所以使用哪一个版本,根据实际需求来是最好的。
C#版本的实现:
public static class GeometryUtilityUser
{
/**
* @warning OutPlanes must be new Plane[6]
* Plane Position :
* Left
* Right
* Bottom
* Top
* Near
* Far
*/
enum EPlaneSide
{
Left,
Right,
Bottom,
Top,
Near,
Far
} static float[] RootVector = new float[];
static float[] ComVector = new float[]; public static void CalculateFrustumPlanes(Camera InCamera, ref Plane[] OutPlanes)
{
Matrix4x4 projectionMatrix = InCamera.projectionMatrix;
Matrix4x4 worldToCameraMatrix = InCamera.worldToCameraMatrix;
Matrix4x4 worldToProjectionMatrix = projectionMatrix * worldToCameraMatrix; RootVector[] = worldToProjectionMatrix[, ];
RootVector[] = worldToProjectionMatrix[, ];
RootVector[] = worldToProjectionMatrix[, ];
RootVector[] = worldToProjectionMatrix[, ]; ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ]; CalcPlane(ref OutPlanes[(int)EPlaneSide.Left], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[]);
CalcPlane(ref OutPlanes[(int)EPlaneSide.Right], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[]); ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ]; CalcPlane(ref OutPlanes[(int)EPlaneSide.Bottom], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[]);
CalcPlane(ref OutPlanes[(int)EPlaneSide.Top], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[]); ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ];
ComVector[] = worldToProjectionMatrix[, ]; CalcPlane(ref OutPlanes[(int)EPlaneSide.Near], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[], ComVector[] + RootVector[]);
CalcPlane(ref OutPlanes[(int)EPlaneSide.Far], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[], -ComVector[] + RootVector[]); } static void CalcPlane(ref Plane InPlane, float InA, float InB, float InC, float InDistance)
{
Vector3 Normal = new Vector3(InA, InB, InC); float InverseMagnitude = 1.0f / (float)System.Math.Sqrt(Normal.x * Normal.x + Normal.y * Normal.y + Normal.z * Normal.z); InPlane.normal = new Vector3(Normal.x * InverseMagnitude, Normal.y * InverseMagnitude, Normal.z * InverseMagnitude); InPlane.distance = InDistance * InverseMagnitude;
}
}
下面的代码可用于验证其正确性:
private Plane[] CalcFrustum(Camera InCamera)
{
GeometryUtilityUser.CalculateFrustumPlanes(InCamera, ref CachedPlanes);
#if UNITY_EDITOR && false
Plane[] SysPlanes = GeometryUtility.CalculateFrustumPlanes(InCamera);
for (int i = ; i < SysPlanes.Length; ++i )
{
if( !IsEqual(SysPlanes[i], CachedPlanes[i]) )
{
DebugHelper.Assert(false, "Internal error in CalcFrustum");
}
}
#endif
return CachedPlanes;
}
private static bool IsEqual(Plane InFirst, Plane InSecond)
{
return IsEqual(InFirst.normal, InSecond.normal) &&
IsEqual(InFirst.distance, InSecond.distance);
}
private static bool IsEqual(Vector3 InFirst, Vector3 InSecond)
{
return IsEqual(InFirst.x, InSecond.x) &&
IsEqual(InFirst.y, InSecond.y) &&
IsEqual(InFirst.y, InSecond.y);
}
private static bool IsEqual(float InFirst, float InSecond)
{
return System.Math.Abs(InFirst - InSecond) < 0.001f;
}
private Plane[] CachedPlanes = new Plane[];
Unity中无GC Alloc的CalculateFrustumPlanes的更多相关文章
- Unity中的GC以及优化
[简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...
- 浅谈Unity中的GC以及优化
介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使 ...
- 如何查看子线程中的GC Alloc
1)如何查看子线程中的GC Alloc2)Build时,提示安卓NDK异常3)如何获得ParticleSystem产生的三角形数量4)关于图片通道的问题5)GPUSkinning导致模型动画不平滑 M ...
- UNITY 的GC ALLOC到底是什么
U3D的Profiler中的GC ALLOC 项让人很麻烦,一直搞不清楚它是什么,因为 GC 是垃圾回收,而alloc是内存分配,那么 GC ALLOC 是 垃圾回收内存分配? 这个名字起的太TM烂了 ...
- Unity优化之GC——合理优化Unity的GC
转载请标明出处http://www.cnblogs.com/zblade/ 最近有点繁忙,白天干活晚上抽空写点翻译,还要运动,所以翻译工作进行的有点缓慢 =.= PS: 最近重新回来更新了一遍,文 ...
- Unity减少GC Alloc之 使用for替换foreach
Unity中foreach会增加GC unity中for效率比foreach高? 在unity中使用foreach遍历集合会增加gc alloc,参考的话题:作为Unity3D的脚本而言,c#中for ...
- C#可空类型的速度和GC Alloc测试
在Unity中进行速度和GC Alloc的测试 测试脚本: using UnityEngine; using System; using System.Collections; using Syste ...
- Unity3D游戏GC优化总结---protobuf-net无GC版本优化实践
protobuf-net优化效果图 protobuf-net是Unity3D游戏开发中被广泛使用的Google Protocol Buffer库的c#版本,之所以c#版本被广泛使用,是因为c++版本的 ...
- Unity中的内存泄漏
在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏.大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧 ...
随机推荐
- Windows快捷键
一.常见用法: F1 显示当前程序或者windows的帮助内容. F2 当你选中一个文件的话,这意味着“重命名” F3 当你在桌面上的时候是打开“查找:所有文件” 对话框 F10或ALT 激活当前程序 ...
- NFS 文件系统
NFS的安装是非常简单的,只需要两个软件包即可,而且在通常情况下,是作为系统的默认包安装的. NFS服务的主要配置文件 /etc/exports /etc/exports文件内容格式: <输出目 ...
- css驼峰写法
当style样式与 animate() 方法一起使用时,该属性名称必须是驼峰写法: 您必须使用 paddingLeft 代替 padding-left,marginRight 代替 margin-ri ...
- ActiveMQ集群下的消息回流功能
------------------------------------------------------------------ "丢失"的消息 如果有broker1和brok ...
- 转→js数组遍历 千万不要使用for...in...
看到一篇内容还不错,但是排版实在糟糕, 逼死强迫症患者啊,直接拉下去找原文连接,找到了,但是已经消失了···500错误... 第一次因为实在看不下去一篇博客的排版, 为了排版而转载... 转载地址:h ...
- 【bzoj1700】Problem Solving 解题
题目描述 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地说,他们有P (1 <= P <= 300) 道题目要做. 他们还离开了农场并且象普通人一 ...
- Linux 双网卡绑定
Linux 双网卡绑定 Linux 双网卡绑定双网卡绑定的常用模式:mode1:active-backup 模式,即主备模式.mode0:round-broin 模式,即负载均衡模式(需要交换机配置聚 ...
- sublime text快捷键
Ctrl+Shift+V:粘贴并格式化Ctrl+D:选择单词,重复可增加选择下一个相同的单词Ctrl+L:选择行,重复可依次增加选择下一行Ctrl+M:跳转到对应括号Ctrl+K+B:开关侧栏Ctrl ...
- 修复Linux Mint损坏的依赖
第一种: sudo apt-get install -f 第二种 sudo aptitude install -f 注: 要是某软件xxx依赖损坏了,可以这样 sudo aptitude instal ...
- 写一个js向左滑动删除 交互特效的插件——Html5 touchmove
需求描述 需要实现类似QQ中对联系人的操作:向左滑动,滑出删除按钮.滑动超过一半时松开则自动滑到底,不到一半时松开则返回原处. 纯js实现 使用了h5的touchmove等事件,以及用js动态改变cs ...