如果你需要在逻辑层做一些预先的剔除操作,可能需要从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的更多相关文章

  1. Unity中的GC以及优化

    [简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...

  2. 浅谈Unity中的GC以及优化

    介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使 ...

  3. 如何查看子线程中的GC Alloc

    1)如何查看子线程中的GC Alloc2)Build时,提示安卓NDK异常3)如何获得ParticleSystem产生的三角形数量4)关于图片通道的问题5)GPUSkinning导致模型动画不平滑 M ...

  4. UNITY 的GC ALLOC到底是什么

    U3D的Profiler中的GC ALLOC 项让人很麻烦,一直搞不清楚它是什么,因为 GC 是垃圾回收,而alloc是内存分配,那么 GC ALLOC 是 垃圾回收内存分配? 这个名字起的太TM烂了 ...

  5. Unity优化之GC——合理优化Unity的GC

      转载请标明出处http://www.cnblogs.com/zblade/ 最近有点繁忙,白天干活晚上抽空写点翻译,还要运动,所以翻译工作进行的有点缓慢 =.= PS: 最近重新回来更新了一遍,文 ...

  6. Unity减少GC Alloc之 使用for替换foreach

    Unity中foreach会增加GC unity中for效率比foreach高? 在unity中使用foreach遍历集合会增加gc alloc,参考的话题:作为Unity3D的脚本而言,c#中for ...

  7. C#可空类型的速度和GC Alloc测试

    在Unity中进行速度和GC Alloc的测试 测试脚本: using UnityEngine; using System; using System.Collections; using Syste ...

  8. Unity3D游戏GC优化总结---protobuf-net无GC版本优化实践

    protobuf-net优化效果图 protobuf-net是Unity3D游戏开发中被广泛使用的Google Protocol Buffer库的c#版本,之所以c#版本被广泛使用,是因为c++版本的 ...

  9. Unity中的内存泄漏

    在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏.大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧 ...

随机推荐

  1. Codis——分布式Redis服务的解决方案

    Codis——分布式Redis服务的解决方案 之前介绍过的 Twemproxy 是一种Redis代理,但它不支持集群的动态伸缩,而codis则支持动态的增减Redis节点:另外,官方的redis 3. ...

  2. R自动数据收集第二章HTML笔记1(主要关于handler处理器函数和帮助文档所有示例)

    本文知识点:     1潜在畸形页面使用htmlTreeParse函数 2startElement的用法 3闭包 4handler函数的命令和函数体主要写法 5节点的丢弃,取出,取出标签名称.属性.属 ...

  3. c语言第一章第一节 认识变量

    声明:本人大一新生,闲着无聊..写写c语言教程..菜鸟一枚..大神勿喷!!! 接下来我们都用dev来进行编译..vc++太古老了,没提示功能,不好上手,并且老是出毛病..vs太大了,编个c不至于,运行 ...

  4. Apache服务器安装过程及问题的解决(for windows system32bit)

    在使用Hbuilder设计网站时,在制作本站搜索时,用到了Php文件,而Hbuilder的内置web服务器不支持php的解析, 所以需要安装配置外部服务器,有多个选择,我安装的apache服务器,并遇 ...

  5. Dota2 demo手游项目历程

    最近其实是打算认真研究c++ primer和设计模式的原著,然后写一些读书笔记的,不过设计模式原著里生词太多,大多都看的不是很明白,因此暂时放弃阅读设计模式,打算用这些时间做一个类似我叫mt2的手游d ...

  6. Python 局部变量与全局变量

    本来以为 局部变量就是在函数/def/class/lambda内部的变量,全局变量就是在之前这些之外的变量.但是,再一次学习Python atm 中应用时发现了一次特例(意外) 字典中 在函数内部改变 ...

  7. nuget的搭建及多源冲突

    为什么使用nuget来管理类库引用就不再阐述,好处真的一抓一把.在使用nuget的时候,我们如果总去访问别人的nuget源,受限于网络情况的好坏,速度真的没法保证,更别说访问国外的源了.那好,我们来自 ...

  8. PYTHON文件操作(二)

    class file(object) def close(self): # real signature unknown; restored from __doc__ 关闭文件 "" ...

  9. HashMap和 Hashtable的比较

    Hashtable 和 HashMap的比较 1.  HashMap可以接受null(HashMap可以接受为null的键值(key)和值(value), HashTable不可以接受为null的键( ...

  10. visual studio 2013 中配置OpenCV2.4.13 姿势

    首先在path中添加 “C:\OpenCV\opencv\build\x64\vc12\bin”   (地址随实际变化) 注:添加的都是*86不使用*64 在visualstudio 2013中配置 ...