如果你需要在逻辑层做一些预先的剔除操作,可能需要从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. centos 7.0 安装nginx 1.117

    php官方下载地址 http://cn2.php.net/downloads.php

  2. 集中日志服务器Rsyslog

    http://www.gaizaoren.org/archives/408 基于主机的管理一般需要收集服务器的日志信息用于及时发现错误,处理故障. 搭建linux下的集中日志服务器的程序一般可以用sy ...

  3. FFmpeg-for IOS 一[安装]

    FFmpeg编译环境搭建 准备 下载 gas-preprocessor 下载 ffmpeg包,ffmpeg 安装yasm,先安装homebrew,输入:ruby -e "$(curl -fs ...

  4. eclipse建立springMVC 简单项目

    http://jinnianshilongnian.iteye.com/blog/1594806 如何通过eclipse建立springMVC的简单项目,现在简单介绍一下. 工具/原料   eclip ...

  5. Redis学习手册(主从复制)

    一.Redis的Replication:    这里首先需要说明的是,在Redis中配置Master-Slave模式真是太简单了.相信在阅读完这篇Blog之后你也可以轻松做到.这里我们还是先列出一些理 ...

  6. NXP NFC移植及学习笔记(原创)

    NFC功能介绍 NFC 目前使用的三种功能: 1. P2P模式:基于LLCP协议的基础上,以NDEF数据交换格式来通信. 2. 读写模式:当作为读卡器,对NFC Tag的读写. 3. 卡模拟模式:模块 ...

  7. ssl访问的原理

    本文无图文对照解释,但力求通俗易懂.请读者边读边手绘各个流程,一便于理解.      总体交互流程如下      1. 客户端发起HTTPS请求 这个没什么好说的,就是用户在浏览器里输入一个https ...

  8. $compile

    <html ng-app="compile"> <head> <script src="http://apps.bdimg.com/libs ...

  9. Android-RelativeLayout(相对布局)、LinearLayout(线性布局)

    RelativeLayout(相对布局):按照各子元素之间的位置关系完成布局. 定位:android:layout_above="@id/xxx" --将控件置于给定ID控件之上 ...

  10. iOS之小门道道

    1.代理方法不执行 很多时候在你代理方法不执行时,小样,你看看你设置代理了吗?