使用unity3d需要注意到细节

Unity3D在做性能优化方面需要注意的问题和技术细节 详解 使用C# Job System:Unity3D的C# Job System提供了一种并行计算的方式,可以充分利用多核CPU的性能,从而提高游戏的性能。使用GPU Instancing:通过使用GPU实例化技术,可以将多个相同模型的物体渲染成一个批次,从而减少Draw Call的数量。脚本是游戏逻辑的核心,但过多的脚本会增加CPU的负载,从而降低游戏的性能。使用异步加载API:使用Unity3D提供的异步加载API,可以在后台加载资源,避免游戏的卡顿现象。算法和数据结构的选择会直接影响游戏的性能。 阅读详情

       操作transform.localPosition的时候请小心

  移动GameObject是非常平常的一件事情,一下代码看起来很简单:

  transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );

  但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameObject的localScale是(2.0f,2.0f,2.0f)。你的GameObject将会移动20.0个单位/秒。因为该 GameObject的world position等于:

  Vector3 offset = new Vector3( my.localPosition.x * parent.lossyScale.x,
  my.localPosition.y * parent.lossyScale.y,
  my.localPosition.z * parent.lossyScale.z );
  Vector3 worldPosition = parent.position + parent.rotation * offset;

  换句话说,上面这种直接操作localPosition的方式是在没有考虑scale计算的时候进行的,为了解决这个问题,Unity3D提供了Translate函数,所以正确的做法应该是:

  transform.Translate ( 10.0f * Time.deltaTime, 0.0f, 0.0f );

  曝出在Inspector的变量同样的也能被Animation View Editor所使用

  有时候我们会想用Unity3D自带的Animation View Editor来做一些简单的动画操作。而Animation Editor不仅可以操作Unity3D自身的component,还可以操作我们自定义的MonoBehavior中的各个Property。所以加入 你有个float值需要用曲线操作,你可以简单的将它曝出到成可以serialize的类型,如:

  public float foobar = 1.0f;
  这样,这个变量不仅会在Inspector中出现,还可以在animation view中进行操作,生成AnimationClip供我们通过AnimationComponent调用。

  范例:
  public class TestCurve : MonoBehaviour {
  public float foobar = 0.0f;
  IEnumerator Start () {
  yield return new WaitForSeconds (2.0f);
  animation.Play("foobar_op");
  InvokeRepeating ( "LogFoobar", 0.0f, 0.2f );
  yield return new WaitForSeconds (animation["foobar_op"].length);
  CancelInvoke ("LogFoobar");
  }
  void LogFoobar () {
  Debug.Log("foobar = " + foobar);
  }
  }
  

  GetComopnentT 可以取父类类型
  Unity3D 允许我们对MonoBehavior做派生,所以你可能有以下代码:
  public class foo : MonoBehaviour {
  ...
  }
  public class bar : foo {
  ...
  }
  
假设我们现在有A,B两个GameObject, A包含foo, B包含bar, 当我们写
  foo comp1 = A.GetComponentfoo();
  bar comp2 = B.GetComponentbar();

  可以看到comp1, comp2都得到了应得的Component。那如果我们对B的操作改成:

  foo comp2 = B.GetComponentfoo();
  答案是comp2还是会返回bar Component并且转换为foo类型。你同样可以用向下转换得到有效变量:

  bar comp2_bar = comp2 as bar;
  合理利用GetComponentbase_type()可以让我们设计Component的时候耦合性更低。

  Invoke, yield 等函数会受 Time.timeScale 影响

  Unity3D提供了一个十分方便的调节时间的函数Time.timeScale。对于初次使用Unity3D的使用者,会误导性的认为Time.timeScale同样可以适用于游戏中的暂停(Pause)和开始(Resume)。所以很多人有习惯写:

  Time.timeScale = 0.0f

  对于游戏的暂停/开始,是游戏系统设计的一部分,而Time.timeScale不不是用于这个部分的操作。正确的做法应该是搜集需要暂停的脚本或 GameObject,通过设置他们的enabled = false 来停止他们的脚本活动或者通过特定函数来设置这些物件暂停时需要关闭那些操作。

  Time.timeScale 更多的是用于游戏中慢镜头的播放等操作,在服务器端主导的游戏中更应该避免此类操作。值得一提的是,Unity3D的许多时间相关的函数都和 timeScale挂钩,而timeScale = 0.0f将使这些函数或动画处于完全停止的状态,这也是为什么它不适合做暂停操作的主要原因。

  这里列出受timeScale影响的一些主要函数和Component:

  MonoBehaviour.Invoke()
  MonoBehaviour.InvokeRepeating()
  yield WaitForSeconds()
  GameObject.Destroy()
  Animation Component
  Time.time, Time.deltaTime
  Coroutine 和 IEnumerator的关系

  初写Unity3D C#脚本的时候,我们经常会犯的错误是调用Coroutine函数忘记使用StartCoroutine的方式。如:

  TestCoroutine.cs
  IEnumerator CoLog () {
  yield return new WaitForSeconds (2.0f);
  Debug.Log("hello foobar");
  }

  当我们用以下代码去调用上述函数:

  TestCoroutine  testCo = GetComponentTestCoroutine();
  testCo.CoLog ();
  testCo.StartCoroutine ( "CoLog" );
  那么testCo.CoLog()的调用将不会起任何作用。

  StartCoroutine, InvokeRepeating 和其调用者关联
  通常我们只在一份GameObject中去调用StartCoroutine或者InvokeRepeating, 我们写:


  StartCoroutine ( Foobar() );
  InvokeRepeating ( "Foobar", 0.0f, 0.1f );
  所以如果这个GameObject被disable或者destroy了,这些coroutine和invokes将会被取消。就好比我们手动调用:

  StopAllCoroutines ();
  CancelInvoke ();
  

      这看上去很美妙,对于AI来说,这就像告诉一个NPC你已经死了,你自己的那些小动作就都听下来吧。
  

       但是注意了,假如这样的代码用在了一个Manager类型的控制AI上,他有可能去控制其他的AI, 也有可能通过Invoke, Coroutine去做一些微线程的操作,这个时候就要明确StartCoroutine或者InvokeRepeating的调用者的设计。讨论之前我 们先要理解,StartCoroutine或InvokeRepeating的调用会在该MonoBehavior中开启一份Thread State, 并将需要操作的函数,变量以及计时器放入这份Stack中通过并在引擎每帧Update的最后,Renderer渲染之前统一做处理。所以如果这个 MonoBehavior被Destroy了,那么这份Thread State也就随之消失,那么所有他存储的调用也就失效了。
    
       如果有两份GameObject A和B, 他们互相知道对方,假如A中通过StartCoroutine或InvokeRepeating去调用B的函数从而控制B,这个时候Thread State是存放在A里,当A被disable或者destroy了,这些可能需要一段时间的控制函数也就失效了,这个时候B明明还没死,也不会动了。更 好的做法是让在A的函数中通过B.StartCoroutine (  ) 让这份Thread State存放于B中。
  
      // class TestCortouine
  public class TestCoroutine : MonoBehaviour {
  public IEnumerator CoLog ( string _name ) {
  Debug.Log(_name + " hello foobar 01");
  yield return new WaitForSeconds (2.0f);
  Debug.Log(_name + " hello foobar 02");
  }
  }
  // component attached on GameObject A
  public class A: MonoBehaviour {
  public GameObject B;
  void Start () {
  TestCoroutine  compB = B.GetComponentTestCoroutine();
  // GOOD, thread state in B
  // same as: compB.StartCoroutine ( "CoLog", "B" );
  compB.StartCoroutine ( compB.CoLog("B") );
  // BAD, thread state in A
  StartCoroutine ( compB.CoLog("A") );
  Debug.Log("Bye bye A, we'll miss you");      
  Destroy(gameObject); // T_T I don't want to die...
  }        
  }
  
         以上代码,得到的结果将会是:
  B hello foobar 01
  A hello foobar 01
  Bye bye A, we'll miss you
  B hello foobar 02
  
         如不需要Start, Update, LateUpdate函数,请去掉他们
  当你的脚本里没有任何Start, Update, LateUpdate函数的时候,Unity3D将不会将它们加入到他的Update List中,有利于脚本整体效率的提升。
  我们可以从这两个脚本中看到区别:


  Update_01.cs
  public class Update_01 : MonoBehaviour {
  void Start () {}
  void Update () {}
  }
  Update_02.cs
  public class Update_02 : MonoBehaviour {
  }





  
unity3D游戏开发之Transform的坐标变换注意事项 Transform是unity的核心类之一.表示的是物体的平移,旋转和缩放.  而position和localPosition,  分别表示的是,transform的位置是世界空间,和父空间的描述.  注意是 父空间,并不是自身空间.  注意到这点后,在空间的变换时就会省心很多了.  如果想搞清楚transform.position的变换过程,可以这样来测试:  Java代 阅读详情

相关推荐

Unity3D插件:uniSWF操作注意事项

Unity3D有很多插件,uniSWF就是其中的一个。它可以把Flash做的UI可以导入到Unity3D中使用,非常方便,而且也可以做的很精致。但是也需要去注意uniSWF的使用规范。

UnityAPI的学习——Object类

Object类是Unity中所有对象的基类、例如GameObject、Component、Material、Shader、Texture、Mesh、Font等都是Object的子类。

ht_game的博客 1328

Carla-编译CarlaUE4提示HoloLens.Automation项目缺少Windows程序集?

编译CarlaUE4提示HoloLens.Automation项目缺少Windows程序集?不妨看看这个!

DSK_981029的博客 2573

【Unity】Unity C#基础(十五)implicit 隐式类型转换、explicit 显式类型转换

Implicit提高了代码的可读性,但程序员需要自己保证转换不引发异常且不丢失信息。Explicit可阻止编译器静默调用可能产生意外后果的转换操作。前者更易于使用,后者能向阅读代码的每个人清楚地指示您要转换类型。C#中的Explicit和Implicit更多内容请查看总目录【Unity】Unity学习笔记目录整理。

一个普普通通的游戏开发者 1478

基于DFT的scanshift sdc模板(DFT)

摘要:本文详细介绍了DFT测试模式下的SDC约束方法。

murphyrong的博客 885

Oracle迁移至华为GaussDB SQL语法和存储过程转换

在将Oracle数据库迁移至GaussDB时,SQL语法和存储过程的转换是确保应用程序正常运行和数据完整性的关键环节。由于两者在数据类型、函数、过程语言等方面存在差异,必须系统化地进行转换和测试。正则表达式脚本:批量替换常见的语法差异。SQL解析工具:解析SQL脚本,生成GaussDB兼容的语法。代码审查工具:自动检查转换后的代码,确保语法和逻辑正确。将Oracle迁移至GaussDB涉及到SQL语法和存储过程的全面转换。通过系统化的转换步骤、使用合适的工具并结合手动调整,可以确保迁移过程的顺利进行。

weixin_38428874的博客 2397

unity3d注意事项

注意事项:     1.无论是包名,方法名,等名称均不可用中文定义 2.将物体事先设置好预设体后再进行复制,这样每个相同的物体都可用预设体控制 3.删除物体时千万谨慎(指的是删除物体,预设体,脚本等文件),删除了后基本恢复不了 4.图片格式统一,基本为PNG格式 5.Trigger于Collision是冲突的,所以检测碰撞时务必明确好如何进行的碰撞,发生碰撞的条件是否有满足(例如2物体碰

a6958858的博客 933

海洋与地质地理信息数据下载网站汇总集锦

各种海洋与地质地理信息数据集合

qq_36980284的博客 1268

Unity Shader - Albedo Color and Transparency 反射率颜色和透明

目录:Unity Shader - 知识点目录(先占位,后续持续更新) 原文:Albedo Color and Transparency 版本:2019.1 Albedo Color and Transparency Standard Shader材质的默认参数和一些未设置的数值,纹理。Albedo Color参数图中红色框框着。 Albedo参数控制表面的基础色调。 albedo数值从黑到白...

Jave.Lin 的学习笔记 5241

第33次CCF-CSP认证考试 第一题 词频统计 满分题解

本人小白一枚,抱着学习的态度想到网上找一些csp的参考答案,但由于实力有限,大佬的代码大都看不太懂,于是萌生了想用一些简单,基础的语句完成csp前两题的想法并公开,以便与像我这样实力不强的同学交流学习,如有更好的建议,还请斧正,感谢!

qq_75242106的博客 1869

Oracle19c SYSAUX表空间爆满?手把手教你清理SM/ADVISOR和AUDSYS占用(附完整SQL)

本文详细解析了Oracle19c中SYSAUX表空间爆满的常见原因及解决方案,重点针对SM/ADVISOR和AUDSYS组件的空间占用问题提供了完整的SQL清理脚本。通过诊断查询、空间清理和预防性维护策略,帮助DBA有效管理SYSAUX表空间,确保数据库稳定运行。

weixin_28338005的博客 236

关于关键字explicit 和 implicit

这两个关键字从字面意思上,我们知道是"明确的" 和 “含蓄的,不言明”的意思,换成程序的说法是能否进行隐式转换 举个Unity LayerMask的例子 public struct LayerMask {      public static implicit operator int (LayerMask mask);//讲LayerMask隐式转换为int类型     

沉默路人 4162

mfcc总结,这个mel三角滤波器分组到底是如何起作用的呢?

先看fft频谱图(这是4096字节取样fft计算,横轴频率是从0到512,后边意义不大,未取,纵轴是振幅),那些我随便画的蓝色线,你有什么联想?: 再看,这绿色线,是否有一种上升后,便逐渐式微的感觉,都是三角形的,这或许也是mel当初和绝大多数人看到的: 如果在振幅上加上一条限制的黑线(振幅门槛限制),黑色线以下很多频率就没有意义了,你看,有用的频率连一半(512/2=256)都占不到...

ganggangwawa的博客 9908

使用Unity3D需要注意到细节

操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f ); 但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameO

秋风扶柳笛的专栏 6897

Windows10下安装VMware16虚拟机

由于本人系统为Windows 10 家庭中文版,无法安装Linux子系统WSL,虽然网上也有强制安装的方法,但为保险起见,还是把之前的VMware虚拟机重新进行安装,并浅浅记录一下安装过程。

沉香best的博客 863

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

unity3d一些需要注意到细节

操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f ); 但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameO

编程小生的专栏 1822

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【转】使用unity3d需要注意到细节

原 文:http://cache.baiducontent.com /c?m=9d78d513d9841df41ea6837e7c01a6660e20f6743da7c76508c3e34f84152d563763f7fc677c1f5e95833e7000dc5441afb57365377471ebcb96d51f9cac925f7ed578292d42d01e418f04fc8b007e907...

weixin_30367543的博客 164

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

使用unity3d需要注意到细节 (含timescale)

操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameObj

stormbjm的专栏 7487

unity3d在ubuntu下安装及以前没注意到的细节问题

1.问题描述 首先,今天(2021-5-10)在ubuntu下面安装unity3d软件发现了自己对linux仍然有一些不熟悉的操作之处1.软件安装的权限问题,2.软件要创建目录时,引起的权限问题 (以前没注意到,今天突然间想起来的) 2.ubuntu下untiy3d的安装简介(软件安装不是今天重点) 本来是不想写这个模块的,但是看了看网络上这方面的教程实在是少之又少,特此,谨以此片...

qq_44658941的博客 215

unity3D总结的一些细节,不注意有些要折腾很多天!

1. 注意!!ps中关闭最大兼容将会导致unity导入失败!(n天)

Mono1977的专栏 2385

unity3D总结的一些细节,不注意有些要折腾非常多天!

1. 注意!!ps保存图片时,若保存为ps格式,若关闭最大兼容将会导致unity导入失败!(n天) 2.switch 推断NGUI popuplist传来的value字符串时一定要trim一下去掉空格! 3. 获取子物体时,方法不同得到的结果不同! foreach(Transform tr in transform) 返回的是下一级子物体,通俗点就是“儿子”。 Trans...

weixin_30618985的博客 126
上一篇: 使用 Sublime Text 2 开发 Unity3D 项目
下一篇: 事件委托机制实现GameObject之间的通信
七大黍
博客等级 码龄20年 436粉丝 260原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值