如果你需要在逻辑层做一些预先的剔除操作,可能需要从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. Django基础,Day5 - form表单投票详解

    投票URL polls/urls.py: # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, ...

  2. ASP.NET是否存在客户端控件?

    在很久很久以前,传说...在ASP.NET开发中,使用服务端控件,比客户端控件更加损耗性能... 那么ASP.NET中是否有客户端控件呢? 有些人就说了,打开VS,然后在左边,工具箱里,有个HTML部 ...

  3. Linux搭建Nginx

    1.Nginx安装 1.1 pcre (1)下载编译包 http://www.pcre.org/ (注意需要的是pcce,而非pcre2) (2)tar -zxvf pcre-8.36.tar.gz  ...

  4. VB常用字符串操作函数

    1. ASC(X),Chr(X):转换字符字符码 [格式]: P=Asc(X) 返回字符串X的第一个字符的字符码 P=Chr(X) 返回字符码等于X的字符 [范例]: (1)P=Chr(65) ‘ 输 ...

  5. ssh

    ssh的配置文件有两个:服务端:/etc/ssh/sshd_config 客户端:/etc/ssh_config 服务端配置文件:/etc/ssh/sshd_config [root@localhos ...

  6. MySQL 锁问题

    一.MySQL中不同的存储引擎支持不同的锁机制 (A) MyISAM 和 MEMORY 支持表级锁 (B) BDB 支持页面锁,也支持表级锁 (C) InnoDB 支持行级锁,也支持表级锁,默认是行级 ...

  7. 带参方法的执行:普通方法的查询,可为空方法的查询。批量处理SQL语句。

    普通方法的查询: @Override public List<Map<String, Object>> selectSpentAmount(Integer MAT_TYPE_, ...

  8. iOS10 权限崩溃问题

    iOS10 权限崩溃问题 原文: http://blog.csdn.net/runleelrg/article/details/51673025 今天 手机升级了 iOS10 Beta,然后用正在开发 ...

  9. 在_vimrc中 set noexpandtab python 不起效果

    我ctm,今天配置不让tab转为空格,在_vimrc中set noexpandtab 不起效果. set ts=4也不起效果. 但是在命令行中其效果. 我都不知道咋办了. 问人说我有可能使用的不是那个 ...

  10. springmvc拦截器验证登录时间

    在前一篇[Filter实现用户名验证]的随笔里,记录了如何使用filter 这次增加了拦截器实现 ①filter实现用户登陆时验证用户名是否为null ②interceptor实现用户登陆时时间判断, ...