注意:本文章将长期更新,长期修改。

快速找到对象

在Hierarchy选中需要查找的对象,在Scene视图中F,即可快速找到需要的对象


快速对齐对象

在Game视图中选到对象之后,按住V,此时可以看到移动的中心变到了鼠标所在的位置。现在尝试移动即可将两个Cube无缝连接在一起。


BMFont 使用

使用了一个大佬开放插件。
使用方法: 使用BMFont导出.fnt和.png之后,在Unity中创建CustomFont和Material。打开上面的插件,依次将需要的文件替换。
注意: 如遇到字体信息在重启Unity后丢失的情况,可在BMFontEditor.cs脚本中的最后添加 EditorUtility.SetDirty(targetFont);来解决。


刚体与碰撞体

刚体使gameObject拥有物理属性,碰撞体使gameObject拥有碰撞属性。


抽象类

抽象类没办法被序列化。虚函数不需要定义在抽象类中,就可以序列化。


ScreenToWorldPoint

如果存在调用Camera.ScreenToWorldPoint转换之后,位置没有变化的情况下,那么可能需要注意下转换位置的z值
如果相机是正交模式,那么被转换的位置是不需要关注z值。
但是相机是透视模式,那么被转换位置的z值就需要修改为如下所示:

point = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane));

Animator

通过连线使用过渡条件来播放动画时,可以在两个动作之间切换连贯
而使用animator.Play和animator.CrossFade切换动画的时候,两个动作之间没有连贯性。Play就是硬切下一个动作,而CrossFade是在参数指定的时间内慢慢切换为下一个动作。


添加物件与模型配合动作

需要注意被添加的物体不能有刚体,否则会发生意想不到的事情发生。
比如打火机添加到模型手上,配合动作时。打火机的刚体需要暂时隐藏。


Navigation

Bake栏参数:
Agent Radius 定义了Agent中心能接近墙壁或窗台的程度。
Agent Height 定义了Agent所能下探的深度。
Max Slope 定义了Agent所能行走的陡坡的坡度。
Step Height 定义了Agent可以迈上多高的障碍物。
DropHeight: 掉落高度
JumpDistance: 跳跃高度

注意事项:

  • NavMeshObstacle 障碍物需要勾选Carve才有效果
  • 代理没法到达的地方,即使设置了Off Mesh Link 也没有用。
  • 当移动对象设置Collider时,如果需要通过的路径宽度小于Collider的大小时,这个时候移动对象是无法通过的。解决方法是修改Collider的边界,或移除Collider(如果不需要使用到碰撞的话)

Input

Input.GetMouseButton: 按下鼠标时持续调用
Input.GetMouseButtonDown: 只在鼠标按下时调用一次
Input.GetMouseButtonUp: 只在鼠标松开时调用一次

参数都是一致的: 0 表示左键,1 表示右键,2 表示中间按钮。


Animator 过渡条件

过渡条件有Bool,Int,Float,Trriger几种类型。这里我们只谈论Bool和Trriger。
如果我们使用Bool作为过渡条件的话,设置为true之后,如果下次切换其他动作时不设置为false的话,这个条件就永远成立。
使用Trriger,则没有这种问题。我们需要做的仅仅是在SetTrriger之前,ResetTrigger(“上个Trriger”)。否则切换的时候人物会抽动。


运行时使程序暂停

在需要停止的地方添加如下代码即可。编辑器将进入暂停状态:

  Debug.Break();

Image Preserve Aspect

启用 Preserve Aspect 复选框。这样可以使图像在 Rect Transform 内尽可能增大,但不会被压缩或拉伸。

未勾选:

勾选后:

原图:


模型的显示

如下图所示,模型在层级面板中显示的是下图中的第二个,模型是只读的,当我们尝试删除其中的内容时会弹窗显示无法删除。
要进行编辑,需要创建一个预制件。也就是显示为下图的第一个,此时删除将变得有效。


SkinnedMeshRenderer

模型由一个包含三角形的网格组成,该网格由 Mesh Renderer(网格渲染器)进行“渲染”,从而使该网格可见。Skinned Mesh Renderer 是一种特殊类型的 Mesh Renderer,可让网格根据模型所有的骨骼的位置和旋转来改变形状
动画形成的方式如下:角色父游戏对象上的 Animator 组件将改变所有骨骼游戏对象 Transform 组件的旋转,这些改变将一起发生以形成角色的动画。


Has Exit Time 的作用

HasExitTime有两个作用:
第一个是勾选上了之后,将不用添加条件来转换了。动画播放完,将会自动转换为下一个动作。
第二个是使用条件来转换的话,不勾选选项动画将会立即切换为另一个。但是勾选了情况下,那么就会在动画播放完之后再切换,也就是说使用条件来切换将不会立即生效。


命名约定

公共成员变量/局部变量: myParam
非公共成员变量: m_MyParam


Canvas Group

画布组 (Canvas Group) 可集中控制整组 UI 元素的某些方面,而无需单独处理每个元素。画布组的属性会影响所在的游戏对象以及所有子对象。
画布组的典型用途为:

  1. 通过在窗口的游戏对象上添加画布组并控制其 Alpha 属性来淡入或淡出整个窗口。
  2. 通过将画布组添加到父游戏对象并将其 Interactable 属性设置为 false 来使整组控件不可交互(“灰显”)。
  3. 通过在 UI 元素或其某个父元素上放置画布组 (Canvas Group) 组件并将其 Block Raycasts 属性设置为 false 来使一个或多个 UI 元素不阻止鼠标事件。

Mathf.Approximately

比较两个浮点值,如果它们相似,则返回 true。
例如,(1.0 == 10.0 / 10.0) 不会每次都返回 true。 Approximately() 比较两个浮点数,如果它们相互之间的差值处于较小值范围内,则返回 true。


Input.GetAxis

Unity 有一个输入管理器(Edit-ProjectSetting-InputManager)用来定义可按名称找到的各种按钮和轴。例如,其中有一个称为 Horizontal 的轴,由 A 和 D 键以及向左和向右键表示。因此,通过该检查,玩家的计算机可以决定角色应该向左还是向右移动。
Input.GetAxis只能监听键盘和游戏手柄的输入,对于移动平台没有意义。

   float horizontal = Input.GetAxis("Horizontal");float vertival = Input.GetAxis("Vertical");

动画状态添加StateMachineBehaviour

在Animator界面中,选中需要添加脚本的动画,在Inspector中选中AddBehaviour添加StateMachineBehaviour脚本。


Spine插件下载问题

如果在Spine官网下载的文件不是.unitypackage的话,而是**.gz结尾**的文件的话。尝试换个浏览器下载,笔者换了谷歌浏览器之后就可以下载到.unitypackage。

Spine 资源导入问题

将atlas的后缀改成.txt,拖入Unity中会自动生成其他相关文件。


Spine 动画未播放完,重新播放问题

两行代码都需要添加

   spine.Skeleton.SetToSetupPose();spine.AnimationState.ClearTracks();

模型动画重复问题

选中模型中的动画,在Inspector中选中Animation,勾选下方的LoopTime。最后需要点击 Apply才会生效。


SpriteAtlas 的使用

设置Sprite Packer 模式

Edit---->ProjectSetting------->Editor--------->Mode

Mode参数意义:
(1)disabled不启用
(2)enabled for builds(legacy sprite packer):打包时启用(针对sprite packer这种打包方式)
(3)always enabled(legacy sprite packer):总是启用(针对sprite packer这种打包方式)
(4)enabled for builds:打包时启用(针对sprite Atlas这种打包方式)
(5)always enabled(针对sprite Atlas这种打包方式)

sprite Atlas是2017版本之后的图集打包方式, Sprite Atlas 针对旧版本的图集打包系统Sprite Packer在性能和易用性上的不足,进行了全面改善。
所以笔者下面只使用spriteAtlas演示。

创建sprite Atlas

如下所示创建sprite Atlas:

加入spriteAtlas

spriteAtlas支持通过文件夹添加,所以建议通过文件夹添加,那样就不用一个一个添加了。添加完之后就可以点击PackPreview查看效果。

查看效果

这里我们可以回到上面设置Sprite Packer模式中,通过来回修改SpritePacker为enabled for builds或always enabled,然后点击Stats查看效果


模型动画优化

文件压缩方式:选中含有动作的.fbx文件,再选中Animation,修改Anim.Compression。

选项说明:
Off 关闭压缩
Keyframe Reduction 减少没有必要的关键帧
Optimal 优化压缩,官方会选择最优的压缩方式来进行压缩,建议选择这个


降低内存垃圾回收(GC)对性能的影响

String

  1. 在 C# 中,字符串属于引用类型,而非值类型。我们需要减少不必要的字符串创建或更改操作。修改字符串的方法实际上都是返回一个新的String对象原字符串仍然留在内存 中等待回收,那么当字符串较长或是操作频繁时就消耗大量的资源。如果你需要在运行时构建字符串,可使用 StringBuilder 类。
  2. 尽量避免解析 JSON 和 XML 等由字符串组成的数据文件,将数据存储于 ScriptableObjects,或以 MessagePack 或 Protobuf 等格式保存。

Unity 函数调用

  1. 缓存数组引用,避免在循环进行中进行数组的内存分配。
  2. 尽量使用那些不会产生垃圾回收的函数。比如使用 GameObject.CompareTag,而不是使用 GameObject.tag 手动比对字符串(因为返回一个新字符串会产生垃圾数据)。

Boxing(打包)

避免在引用类型变量处传入值类型变量,因为这样做会导致系统创建一个临时对象,在背地里将值类型转换为对象类型(如int i = 123; object o = i ),从而产生垃圾回收的需求。尽量使用正确的类型重写来传入想要的值类型。泛型也可用于类型覆写。

Coroutines(协同程序)

虽然 yield 不会产生垃圾回收,但新建 WaitForSeconds 对象会。我们可以缓存并复用 WaitForSeconds 对象,不必在 yield 中再度创建。

    WaitForSeconds waitSec = new WaitForSeconds(0.01f);IEnumerator TestWaitSecond(){yield return waitSec;}

降低每帧的代码量

有许多代码并非要在每帧上运行,这些不必要的逻辑完全可以在 Update、LateUpdate 和 FixedUpdate 中删去。这些事件函数可以保存那些必须每帧更新的代码,任何无须每帧更新的逻辑都不必放入其中。
如果必须要使用 Update,可以考虑让代码每隔 n 帧运行一次。

private int interval = 3;
void Update()
{if (Time.frameCount % interval == 0){ExampleExpensiveFunction();}
}

避免在 Start/Awake 中加入繁重的逻辑

当首个场景加载时,每个对象都会调用如下函数:Awake,OnEnable,Start。
应用完成第一帧的渲染前,我们须避免在这些函数中运行繁重的逻辑。否则,应用的加载时间会出乎意料地长


避免加入空事件

即使是空的 MonoBehaviours 也会占用资源,因此我们应该删除空的 Update 及 LateUpdate 方法。
如果你想用这些方法进行测试,请使用预处理指令:

#if UNITY_EDITOR
void Update()
{}
#endif

如此一来,在编辑器中的 Update 测试便不会对构建版本造成不良的性能影响。


删去 Debug Log 语句

Log 声明(尤其是在Update、LateUpdate及FixedUpdate中)会拖慢性能,因此我们需要在构建之前禁用 Log 语句。你可以用预处理指令编写一条 Conditional 属性来轻松禁用 Debug Log。比如下方这种的自定义类:

public static class Logging
{[System.Diagnostics.Conditional("ENABLE_LOG")]static public void Log(object message){UnityEngine.Debug.Log(message);}
}

使用哈希值、避免字符串

Unity 底层代码不会使用字符串来访问 Animator、Material 和 Shader 属性。出于提高效率的考虑,所有属性名称都会被哈希转换成属性 ID,用作实际的属性名称。
在 Animator、Material 或 Shader 上使用 Set 或 Get 方法时,我们便可以利用整数值而非字符串。后者还需经过一次哈希处理,并没有整数值那么直接。
使用 Animator.StringToHash 来转换 Animator 属性名称,用 Shader.PropertyToID 来转换 Material 和 Shader 属性名称

    public static int IS_WALKING;private void Awake(){IS_WALKING = Animator.StringToHash("IsWalking");}void FixedUpdate(){//使用ID修改条件m_Animator.SetBool(IS_WALKING, isWaking);}

选择正确的数据结构

由于数据结构每帧可能会迭代上千次,因此其结构对性能有着较大的影响。如果你不清楚数据集合该用 List、Array 还是 Dictionary 表示,可以参考 C# 的 MSDN 数据结构指南来选择正确的结构。


避免在运行时添加组件

在运行时调用 AddComponent 会占用一定的运行成本,Unity 必须检查组件是否有重复或依赖项


缓存 GameObjects 和组件

调用 GameObject.Find、GameObject.GetComponent 和 Camera.main(2020.2以下的版本)会产生较大的运行负担,因此这些方法不适合在 Update 中调用,而应在 Start 中调用并缓存

private Renderer myRenderer;
void Start()
{myRenderer = GetComponent<Renderer>();
}void Update()
{ExampleFunction(myRenderer);
}

使用 ScriptableObjects(可编程对象)

固定不变的值或配置信息可以存储在 ScriptableObject 中,不一定得储存于 MonoBehaviour。ScriptableObject 可由整个项目访问,一次设置便可应用于项目全局。

声明:

using UnityEngine;[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{public string prefabName;public int numberOfPrefabsToCreate;public Vector3[] spawnPoints;
}

使用:

using UnityEngine;public class Spawner : MonoBehaviour
{// 要实例化的游戏对象。public GameObject entityToSpawn;//上面定义的 ScriptableObject 的一个实例。public SpawnManagerScriptableObject spawnManagerValues;//这将附加到创建的实体的名称,并在创建每个实体时递增。int instanceNumber = 1;void Start(){SpawnEntities();}void SpawnEntities(){int currentSpawnPointIndex = 0;for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++){//在当前生成点处创建预制件的实例。GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);//将实例化实体的名称设置为 ScriptableObject 中定义的字符串,然后为其附加一个唯一编号。currentEntity.name = spawnManagerValues.prefabName + instanceNumber;// 移动到下一个生成点索引。如果超出范围,则回到起始点。currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;instanceNumber++;}}
}

打包64位安卓包

Build Setting -> Player Setting->Player ->Other Settings,
修改Scripting Backend为IL2CPP, Target Architectures勾选ARM64。
(如图所示)


生成apk后用解压软件打开lib文件夹,如果为arm64-v8a则为64位:

Unity 使用技巧与常见问题相关推荐

  1. 复习Unity优化技巧

    复习Unity优化技巧 一.引言 新的格局 有推荐的吗? 二.优化 第一章.优化图形性能 1.分析: A.GPU通常受填充率或者内存带宽制约. 填充率 渲染管线 B.CPU 通常受到需要渲染的批次数的 ...

  2. 计算机主板最常见的问题,计算机主板功能 电脑实用技巧解决常见问题

    电脑实用技巧解决常见问题 1.解决问题 插电即开机问题 现象:有些朋友有关机后断开电源板电源的习惯,可是却常常被一个问题困扰,就是电源板一通电,计算机就自动开机了,Power键形同虚设.解决问题:有些 ...

  3. unity小技巧总结

    这是对unity公众号上一个unity小技巧的介绍视频的总结 原文是这个:https://unity.cn/projects/unity-tips?signup=true 1)unity常用快捷键 1 ...

  4. 【帆软报表】使用技巧及常见问题汇总-持续更新

    [帆软报表]使用技巧及常见问题汇总-持续更新 1.重复与冻结设置,做用:冻结区域 模板-重复与冻结设置 2.单元格有效小数设置 选中单元格-格式-数字-#0.00 3.图表中有效小数设置 图表属性表- ...

  5. s00devs_Devs @ Home –现场网络研讨会– CEST:4月30日13:00:Hibernate提示和技巧–解决常见问题的15条提示

    s00devs 我们正处于大流行之中,越来越多的开发人员正在孤立的环境中或在家中工作. 通过我们的网络研讨会系列Devs @ Home,我们希望通过将困在家里的开发人员与技术讲座(由专业人员为专业人员 ...

  6. 如何消耗更少资源?Unity优化技巧(上)

    什么是优化? 为了达成相同目标,寻求并采用消耗更少资源的办法的过程 对游戏来说通过特别的技巧,在实现相同的表现效果.流畅度的前提下对硬件机能的需求更低.更平民化.或者在相同性能的平台上,实现更好的画面 ...

  7. SEO面试题与面试攻略,SEO面试技巧以及常见问题分享

    一年一度的秋招季了,有很多在校的学生开始找工作了,但这个时候他们最大的问题就是不知道怎么写简历,面试的时候时候应该怎么办.除了之外,也有一些职场的老员工在面试的适合也会些困惑,平时能说会道的一个人,在 ...

  8. Unity 优化技巧集锦

    前言 Unity性能优化是面试的时候经常被问道的一些内容,今天给大家分享一些常用的Unity的优化技巧和思路,方便大家遇到问题时候参考与学习. 包体大小优化 游戏的安装包体大小对于游戏开发而言非常重要 ...

  9. Unity进阶技巧 - RectTransform详解

    一.Pivot属性详解 首先为了让大家更好的理解内容,我在Unity中创建了两个UI控件,一个Plane控件,作为父对象,一个Image控件,作为子对象. 然后我们选中子对象,来看看它的RectTra ...

最新文章

  1. Linux_KVM虚拟机
  2. wcf系列5天速成——第一天 binding的使用(1)
  3. linux的模块化,GoboLinux 017 发布,模块化的 Linux 发行版
  4. hdu 3864 素数分解
  5. Docker中级篇|深入探究Docker
  6. 如何预防后台被攻击?Tomcat 的安全配置来啦!
  7. STM32-串口通信
  8. 说说Javascript
  9. angular源码分析之platformBrowserDynamic
  10. 用户ID生成唯一邀请码的几种方法
  11. VC Redist Installer 1.6下载
  12. dcdc模块降额设计_大功率IGBT模块及驱动技术
  13. cad图层置顶的lisp_cad中如何将一个图层置于上层
  14. 阿里云全站加速 DCDN 升级
  15. 4 书写规则
  16. 【论文笔记】图匹配的路径跟随算法
  17. 速看!!带你揭秘3D建模行业内幕!!
  18. QTcpServer 服务器监听失败
  19. 你见过最听话的狗狗有多听话?
  20. 【算法千题案例】每日一练LeetCode打卡——108.独特的电子邮件地址

热门文章

  1. 如何搭建一支拖垮公司的技术团队?
  2. 使用Blob实现文件下载
  3. 亚马逊店飞飞跟卖使用教程图文(四)
  4. 前端面试题二:ES6/7/8新特性、性能优化、数据交互、H5新特性
  5. 手游实时对战初步解决方案
  6. 斗鱼App全网下架,官方表示内部优化调整,真实原因是...
  7. yield java_yield在java中的使用
  8. JAVA EE 7 SDK Tutorial分析
  9. 输入一个字符,判断它如果是小写字母输出其对应的大写字母,如果是大写字符输出其对应的小写字母 ,如果是数字则直接输出数字,不是上述情况输出other。
  10. 计算机开机后显示器黑屏无显示,电脑开机时显示器黑屏,提示无信号,怎么办?...