位置: 编程技术 - 正文

【转】Unity 3D Best Practices(unity 3d教程)

编辑:rootadmin
原文链接 the CPU time be spent on where it really needs to be.

推荐整理分享【转】Unity 3D Best Practices(unity 3d教程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:unitycube,unity 3d webgl,unity mobile3d,unity 3d ui,unity 3d object,unity3d bim,unity 3d object,unity 3d,内容如对您有帮助,希望把文章链接给更多的朋友!

We’ve been developing games with Unity for a while. As most of our games are targeted for mobile devices, one of our main concerns on the development process is having our projects well structured and optimised.

There are a lot of simple tips and tricks we’ve been using which make all the difference on any project’s overall performance.

In order to demonstrate each topic’s usefulness, I’ll be presenting profiling data retrieved from a demo, running on an iPad Mini.

Cache Component References

Always cache references to components you’ll need to use on your scripts.

Accessing a game object world position from its script is easy, all you need to do is call transform.position. The problem is that this comes with a price.

When accessing transform, renderer or other built-in component getter inside a class it’s internally calling a GetComponent<ComponentName>() which is slow.

I’ve created a simple demo where boxes are moving around and bouncing with each other. Their movement is done by directly updating their world position on theUpdate() method.

I’ve added a switch which controls where each box uses either transform.positiondirectly or a previously cached transform variable.

Figure 1 – Caching Components

Without caching components, we get an average of ~ms spent on scripting, as with caching we decrease that value to around ~ms.

You need to add a couple of extra lines on your scripts to cache each one of the components you’ll need to use, but as you can see from the profiling data, it’s totally worth it.

Cache Objects References

Always cache object references when you need to access objects from the scene.GameObject.Find(…) is very tempting to use but is also very, very slow.

Figure 2 – Using GameObject.Find(…) vs Cache Reference

It’s very clear the impact it has on the overall performance just by looking at this image. In the demo each object is communicating with a dummy manager either by using GameObject.Find(…) or a previously cached reference.

The overall script time reduces from an average of ~ms to ~ms just by using a cached reference.

Cache Game Objects

This is something that a lot of people ask online.

No, it’s not necessary to cache game objects; you can use gameObject directly on your script without having to worry about any impact on your performance.

In this next image I switched back and forth between using a cached game object and the gameObject itself, and as you can see, there’s no change at all on the overall script execution time.

Figure 3 – Caching Game Object

Memory Allocation

Always consider creating and using Object Pools instead of always instantiating new objects on the fly.

This will bring a lot of advantages as it will lead to less memory fragmentation and make the Garbage Collector work less.

It’s also important to be aware that the Garbage Collector will become slower as the memory usage increases, because it has more memory to scan in order to find and free unused data.

From Unity’s official documentation, the GC on an iPhone 3 takes about 5ms on a KB heap size as with an heap of 1MB it will take 7ms.

Also when allocating memory from a highly fragmented heap block, you most likely don’t have the amount of contiguous memory needed which leads Unity to allocate a new heap block. This leads to a performance spike as GC is forced to kick in and try to free some memory.

To better exemplify Object Pool vs On the Fly Allocation, I tweaked my previous demo a bit.

Now each time I touch the iPad’s screen, a new box is created by either allocating a new instance or getting it from an Object Pool. Each time a box collides with each other or with the screen boundaries it will be either destroyed or returned to the pool.

Figure 4 – Without pool usage

Figure 5 – With pool usage

It’s pretty clear with both these images to see the memory behaviour I was describing. With a pool usage, although I need to allocate a lot of memory from the start to create the pool itself , I never have to do it again and the GC almost never kicks in. As without a pool, Unity is always in need to allocate new heap blocks, and for each one the GC is activated, creating a sawtooth wave pattern on the allocated memory.

This is a very simple demo on which I could easily use a pool for everything, but on a real situation not everything can be poolable. We can however control a bit when the GC does its job and force it to do some cleanup by calling System.GC.Collect(), usually done when you know you have some CPU time to spare.

Sharing Materials

Unity has a neat operation called batching. What it does is combine objects that share the same material ( among other properties ) and draws them together on a single draw call.

As each draw call represents an increased overhead on the CPU side, decreasing their amount is a guaranteed boost on your game’s performance.

It’s particularly easy to take advantage of this feature when working on UI and on 2D games in general, where you store all your textures in a common atlas using a common material.

To demonstrate the impact on the number of draw calls, I’ve added a new feature on my existing demo where I can change in real time if each of the bouncing boxes are using a shared material or each have its own.

Figure 6 – Own Material (UnityEditor Stats on PC)

Figure 7 – Own Material

Figure 8 – Shared Material (UnityEditor Stats on PC)

Figure 9 – Shared Material

As you can see, not using a shared materials generates draw calls ( for each box, and the others for UI and the screen boundaries ) and runs at ~6fps.

By switching to a shared material the number of draw calls drops to 3, indicating that all boxes are drawn in a single draw call and increasing the demo frame rate to ~fps.

More to come, stay tuned

That wraps up Part 1. Each of these topics are extremely easy to implement from the start, and as you could see from the profiler data, they will make all the difference. Don’t leave the optimisation process to the end.

Part2:Physics

This second part in our series will be entirely focused on Unity’s Physics engines.

I’ll present, similarly to the previous article, simple topics which are easy to use and will optimise the physics engine usage.

Let’s begin!

Layers and Collision Matrix:

All game objects, if not configured, are created on the Default layer where (by default) everything collides with everything. This is quite inefficient.

【转】Unity 3D Best Practices(unity 3d教程)

Establish what should collide with what. For that you should define different Layers for each type of object.

For each new layer, a new row and column is added on the Collision Matrix. This matrix is responsible for defining interactions between layers.

By default, when adding a new layer, the Collision Matrix is set for that new layer to collide with every other existing one, so it’s the developer’s responsibility to access it and setup its interactions.

By correctly setting layers and setting up your Collision Matrix, you will avoid unnecessary collisions and testing on collision listeners.

For demonstration purposes I’ve created a simple demo where I instantiate objects ( red and green) inside a box container. Green objects should only interact with themselves and the container walls, the same with red objects.

On one of the tests, all the instances belong to the Default layer and the interaction are done by string comparing the game objects tag on the collision listener.

On another test, each object type is set on their own Layer, and I configure each layer’s interaction through the collision matrix. No string testing is needed in this case since only the right collisions occur.

Figure 1 : Collision Matrix config

The image below is taken from the demo itself. It has a simple manager which counts the amount of collisions and automatically pauses after 5 seconds.

It’s quite impressive the amount of unnecessary extra collisions occurring when using a common layer.

Figure 2 : Collisions amount over 5 seconds

For more specific data I also captured profiler data on the physics engine.

Figure 3 : Common vs Separate Layers physics profiler data

There’s quite a difference on the amount of CPU spent on physics, as we can see from the profiler data, from using a single layer ( avg ~.7 ms ) to separate layers ( avg ~.6ms ).

Raycasts:

Raycasting is a very useful and powerful tool available on the physics engine. It allows us to fire a ray on a certain direction with a certain length and it will let us know if it hit something.

This however, is an expensive operation; its performance is highly influenced by the ray’s length and type of colliders on the scene.

Here are a couple of hints that can help on its usage.

This one is obvious, but, use the least amount of rays that gets the job done

Don’t extend the ray’s length more than you need to. The greater the ray, the more objects need to be tested against it.

Don’t use use Raycasts inside a FixedUpdate() function, sometimes even inside anUpdate() may be an overkill.

Beware the type of colliders you are using. Raycasting against a mesh collider is really expensive.

A good solution is creating children with primitive colliders and try to approximate the meshes shape. All the children colliders under a parent Rigidbody behave as a compound collider.

If in dire need of using mesh colliders, then at least make them convex.

Be specific on what the ray should hit and always try to specify a layer mask on the raycast function.

This is well explained on the official documentation but what you specify on the raycast function is not the layer id but a bitmask.

So if you want a ray to hit an object which is on layer which id is , what you should specify is 1<< ( bit shifting ‘1’ to the left x ) and not .

If you want for the ray to hit everything except what is on layer then simply use the bitwise complement operator (~) which reverses each bit on the the bitmask.

I’ve developed a simple demo where an object shoots rays which collide only with green boxes.

Figure 4 : Simple Raycast demo scene

From there I manipulate the number and length of the rays in order to get some profiler data to backup what I’ve written earlier.

We can see from the graphics below the impact on performance that the number of rays and their length can have.

Figure 5 : Number of rays impact on performance

Figure 6 : Rays length impact on performance

Also for demonstration purposes, I decided to make it able to switch from a normal primitive collider into a mesh collider.

Figure 7 : Mesh Colliders scene ( verts per collider )

Figure 8 : Primitive vs Mesh colliders physics profiler data

As you can see from the profile graph, raycasting against mesh colliders makes the physics engine do a bit more work per frame.

Physics 2D vs 3D:

Choose what Physics engine is best for your project.

If you are developing a 2D game or a 2.5D (3D game on a 2D plane), using the 3D Physics engine is an overkill. That extra dimension has unnecessary CPU costs for your project.

You can check the performance differences between both engines on a previous article I wrote specifically on that subject:

Rigidbody component is an essential component when adding physical interactions between objects. Even when working with colliders as triggers we need to add them to game objects for the OnTrigger events to work properly.

Game objects which don’t have a RigidBody component are considered static colliders. This is important to be aware of because it’s extremely inefficient to attempt to move static colliders, as it forces the physics engine to recalculate the physical world all over again.

Fortunately, the profiler will let you know if you are moving a static collider by adding a warning to the warning tab on the CPU Profiler.

To better demonstrate the impact when moving a static collider, I removed the RigidBody of all the moving objects on the first demo I presented, and captured new profiler data on it.

Figure 9 : Moving static colliders warning

As you can see from the figure, a total amount of warnings are generated, one for each moving game object. Also the average amount of CPU spent on Physics increased from ~.6ms to ~.ms, which is quite a bit.

When moving a game object, it’s imperative to add a RigidBody to it. If you want to control its movement directly, you simply need to mark it as kinematic on its rigid body properties.

Fixed Timestep:

Tweak the Fixed Timestep value on the Time Manager, this directly impacts theFixedUpdate() and Physics update rate. By changing this value you can try to reach a good compromise between accuracy and CPU time spent on Physics.

Wrap-up:

All of the discussed topics are really easy to configure/implement and they will surely make a difference on your projects’ performance as almost every game you’ll develop will use the physics engine, even if it’s only for collision detection.

【译】协程的使用 作者ChevyRay,年9月日,snaker7译原文地址:

碰撞检测 BoxCollider 的特殊实现 当做触发器的Collider检测,可以通过privatevoidOnTriggerStay(Collidercollider);privatevoidOnTriggerEnter(Collidercollider);privatevoidOnTriggerExit(Collidercollider);来实现,当

unity学习之在续NGUI unity学习,希望我的博客能给喜欢unity的朋友带来帮助今天继昨天讲的,接着学习NGUI,让我们可以做出一个简单的登陆注册界面来。实现打字机效果创建

标签: unity 3d教程

本文链接地址:https://www.jiuchutong.com/biancheng/375767.html 转载请保留说明!

上一篇:Clean Empty Directories on Unity3D and Git

下一篇:【译】协程的使用(协程有什么用)

  • 企业所得税行业所得率
  • 个人所得劳务报酬税率
  • 残疾人个人所得税
  • 公司雇佣退休人员怎样扣个税
  • 金蝶利润表没有数据怎么办
  • 弥补以前年度亏损金额从哪里来的
  • 城镇土地使用税纳税义务发生时间
  • 企业出现税务问题的案例
  • 建筑简易征收的合同怎么写
  • 租了房子再转租
  • 增值税发票作废如何处理
  • 非独立核算的分公司可以开票吗
  • 收到办公用品的普票怎么入账
  • 消防设施安装费包括哪些
  • 建筑业确认主营业务收入
  • 银行存款支付比例怎么算
  • 给员工缴纳保险
  • 集团内部资产划转需要交增值税吗
  • 职工食堂的费用怎么入账
  • 地税附加税减免政策
  • 纳税服务一体化综合监督工作情况报告
  • 2021年个体工商户的税率是多少
  • 怎么查询公司有没有开社保户
  • 无形资产盘盈
  • 残疾人不用交医保社保
  • 股东垫支开办费
  • 收到联营企业分派的现金股利为什么不计入利润总额
  • 预计产品质量保证损失是什么意思
  • 融资租赁业务如何纳税
  • 抵押贷款逾期怎么处理抵押物
  • 建筑施工企业跨区域如何缴税
  • 税务师入会与不入会冲突
  • 疫情 统筹
  • 新企业几个月没交社保
  • won11更新
  • win11任务管理器在哪里打开
  • php ajax json
  • 企业职工福利费的扣除标准是多少?
  • 电脑输入法设置搜狗输入法
  • linux 书 推荐
  • 广告费发票内容是什么
  • 房地产计提税金的会计分录
  • 机动处置什么意思
  • 不能进行加计扣除的研发费用有哪些
  • 缴纳增值税的会计处理方法
  • laravel入门与实战:构建主流php应用开发框架
  • 雷达信号pri
  • ios14.5ipad
  • php文件怎么浏览
  • 在税务局怎么查补缴的社保
  • 一般纳税人注销税务流程
  • 电脑自学网
  • 织梦怎么改网站主页
  • 外勤会计是做什么的
  • 个人住房租赁给公司如何开票
  • 小规模减免的附加税怎么做账
  • 嵌入式软件产品应纳税额
  • 没有发票如何做会计分录
  • 月度资金预算怎么填
  • 应收账款占比高受哪些因素影响
  • 销售自己使用过的物品免税吗
  • 启用账簿时应在账簿上签名或盖章的是
  • sqlserver (parse name)字符串截取的方法
  • sql中isnull是什么意思
  • 通过修改注册表修改edge主页
  • win8硬盘重装
  • windows附件在哪里打开
  • xp电脑关机后自动重启是什么原因
  • 怎么用win7兼容模式运行
  • win8系统字体大小设置
  • cocos2dx4.0教程
  • 我的第二个姐姐用英语怎么说
  • jQuery Validate 数组 全部验证问题
  • android开发步骤
  • Unity之megaFierstext翻书插件控制代码分析
  • Unity3D游戏开发标准教程
  • [置顶]电影名字《收件人不详》
  • 欠税款要坐牢吗
  • 北京医保网上服务大厅
  • 有关节能环保的英语作文
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设