本篇文章的内容以各种tips为主,不间断更新

2020/5/27 最近更新:Unity节点视图中快速定位回中心位置

Unity DEMO学习

===========================

Unity3D Adam Demo的学习与研究

Unity3D The Blacksmith Demo部分内容学习

Viking Village维京村落demo中的地面积水效果

Viking Village维京村落demo中的粒子距离消隐

The Courtyard demo学习

ShadowGun Demo学习(非技术向)

Unity AngryBots愤怒的机器人demo研究

Unity Generic Tips

===========================

Unity3D 材质球设置参数无效果的解决方法

Unity3D欧拉和四元数两种旋转的用法

使用四元数点乘比较插值是否即将完成

解决摄像机旋转约束问题(RotateDelta,RotateClamp)

Unity中通过类名字符串取组件的方法

Unity在编辑器状态下清空控制台信息

双面MeshCollider脚本

运行时修改代码不自动刷新

然后按Ctrl+R手动刷新,或者在Project面板下右键刷新

在代码中指定,暂停当前帧

Debug.Break或者Debug.LogError然后在控制台勾选报错暂停。

快速查看非闭合的MeshCollider

关闭MeshRenderer组件,即可显示出Collider的网格。

去除当前脚本警告

#pragma warning disable 0168

此示例可以清除变量未使用警告,具体对应警告ID。并且该预编译指令只对本文件有效。

也可以包裹使用

#pragma warning disable 0168
....
#pragma warning restore 0168

一种更为简短的惰性字段初始化写法

object mObj;
object Obj { get { return mObj ?? (mObj = new object()); } }

之前一直这么写:

object Obj { get { mObj = mObj ?? new object(); return mObj; } }

无重复随机数创建

public int EliminateRepeatRandom(int last, int min, int max)
{
var current = Random.Range(min, max); if (last == current)
return (current + (int)Mathf.Sign(Random.value) * Random.Range(min + , max - )) % max;
else
return current;
}

编辑器窗口滑动缩放(相较直接滑动滚轮步幅更小)

Alt+鼠标右键滑动

编辑器Scene窗口,便捷操控3D场景的方法

按住鼠标右键,wasdqe按键移动,分别对应3个轴向

将选中物品立刻移动到编辑器相机位置

ctrl+shift+f

显示当前选中物体的网格

在gizmos中勾选Selection Wire

去除恼人的standard shader高光

我们在用standard shader调制反射质感时,会有一块高光区域非常碍眼。

可以在Specular Hightlights处将其关闭

打印Vector3类型,但不保留2位小数

vector3有一个重载,可以指定format,其中f10就是保留到小数10位

不过由于是自己实现的,不能在string.format里用

xx.position.ToString("f10")

比较浮点数一致

Mathf.Approximately

删除Project面板里文件夹的展开状态

在Library/expandedItems,删除这个文件会重置展开状态

N卡显存占用查看

C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe

控制台内执行

Unity GI缓存目录

C:\Users\...\AppData\LocalLow\Unity\Caches\GiCache

unity资源商店缓存目录

C:\Users\...\AppData\Roaming\Unity

unity资源商店下载的资源包目录

...\AppData\Roaming\Unity\Asset Store-(具体unity版本).x\

Unity打包后Log日志文件存放路径

C:\Users\XXXX\AppData\LocalLow\DefaultCompany

在Unity中使用快捷键重命名

按F2

Unity节点视图中快速定位回中心位置

按F(Animator、VisualEffectGraph等都支持)

从中间删除数组元素,或者复制数组中间元素

复制中间元素:ctrl+d

从中间删除数组元素:shift+delete

或者右键数组中某个元素也会出现操作选项

快速打开所有可展开内容

Shift+Ctrl+Alt 点击可展开内容

判断目标是否在相机的平截头体内

var planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
var isContain = GeometryUtility.TestPlanesAABB(planes, bounds); if(isContain)
{
//in frustum..
}

即使做了池来缓存,依旧第一次激活GameObject时游戏会卡一下(即播技能特效顿卡问题)

个人猜测是贴图和mesh没传到GPU,mesh倒还好,主要是贴图。

目前我建议的方法是用Graphics把所有经常用的对象全部实时DrawMesh去画,且包含贴图材质球。

可以新建一个16X16的RT画上去,骗过unity。缺点是会多几百个批次。

方法很极端,但有用。

自定义ScriptableObject所生成对象的图标

只需要为原始ScriptableObject脚本对象赋上图标即可

清空StringBuilder

StringBuilder sb = new StringBuilder();
sb.Length = ;

有多种方法,但修改Length属性效率最高,参考这位园友的测试:https://www.cnblogs.com/SpiderKevin/p/3891425.html

Process执行的程序当前目录不正确问题(例.bat文件在d盘,但取到的当前目录是unity文件的目录)

var cacheDirectory = Directory.GetCurrentDirectory();
Directory.SetCurrentDirectory("your directory");
Process.Start("...");
Directory.SetCurrentDirectory(cacheDirectory);

执行之前设置一次当前目录即可。

Unity中快速将当前窗口放大至全屏

shift+space

获取当前项目中的所有程序集

AppDomain.CurrentDomain.GetAssemblies()

Unity Optimize Tips

===========================

遍历list或者数组时,缓存count,可以减少调用次数(10万次循环测试)

for (int i = , iMax = temp.Count; i < iMax; i++)
temp[i].GetHashCode();

在极端情况下,直接用枚举器遍历字典会更快,而且不会产生GC

UnityEngine.Profiling.Profiler.BeginSample("-----1");
foreach (var item in temp)
item.Value.GetHashCode();
UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("-----2");
foreach (var item in temp.Values)
item.GetHashCode();
UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("-----3");
using (var handle = temp.GetEnumerator())
{
while (handle.MoveNext())
handle.Current.Value.GetHashCode();
}
UnityEngine.Profiling.Profiler.EndSample();

使用Instantiate初始化参数去实例对象

public class Foo : MonoBehaviour
{
void Start()
{
var sw = new Stopwatch();
sw.Start(); var go = new GameObject();
go.transform.position = Vector3.one; for (int i = ; i < ; i++)
{
var instancedGO = Instantiate(go);
instancedGO.transform.SetParent(transform);
instancedGO.transform.localPosition = Vector3.zero;
instancedGO.transform.localRotation = Quaternion.identity;
instancedGO.transform.localScale = Vector3.one;
//102ms //Instantiate(go, transform.position, transform.rotation, transform);//74ms
}
sw.Stop();
UnityEngine.Debug.Log("sw: " + sw.ElapsedMilliseconds);
}
}

可以实例化出来再赋值,也可以使用参数直接复制

但是1万次循环测试下两种方法差了20多ms

动态批次/GPU Instancing的优化方向

动态批次的合批操作依然是在渲染前处理,将网格较少的动态模型筛选后在渲染前使用CPU合并。

类似使用MeshBaker手动去合并动态对象,但是限制比MeshBaker多,所以存在关闭系统动态合批,手动处理的优化考量。

GPU Instancing需要硬件/底层接口支持,其内部类似于享元机制,通过索引访问差异的数据。

可以减少较多非GPU的额外开销,但缺点是绘制网格是固定的(如使用GPU Instancing代替以往Geom shader生成草坪,草的类型就被限定死几种了)。

在条件允许下,使用位运算代替乘除法

左移代替2为倍数的整数乘法:

var a = ;
var b = a << ;
//b = 100 50*2
b = a << ;
//b = 200 50*4

右移代替2为倍数的整数除法:

var a = ;
var b = a >> ;
//b = 128 256/2
b = a >> ;
//b = 64 256/4

经测试没有编译器优化的情况,并且有一定速度提升。

关于Unity事件函数空调用

尽量少使用封装Unity事件的通用基类,这样会造成函数空调

unity会在C++层面检测是否实现某个事件函数(Start,Update,LateUpdate...etc)

如果没有这个函数则不会加入调用列表中

使用localPosition代替position

调用Position时背后会有许多操作执行,在代码允许的情况下可使用localPositiond代替position

使用质数作为延迟量可避免最小公倍数出现的情况

例如设计某BOSS的AI时,特殊弹幕A的发射延迟为7,特殊弹幕B的发射延迟为11。

那么将低概率出现这两种特殊弹幕被同时发射的情况。

使用Matrix MultiplyPoint3x4而不是MultiplyPoint

对于非投影矩阵,使用MultiplyPoint3x4进行变换更快。

详见官方文档:https://docs.unity3d.com/ScriptReference/Matrix4x4.MultiplyPoint3x4.html

使用CopyTo将List无GC的转为数组,而不是ToArray

var tempArray = new int[];
void Test()
{
list.CopyTo(tempArray);//0 GC
}

避免直接调用Camera.main

Camera.main内部会去调用FindGameObjectWithTag,1万次循环的测试下造成了1ms左右的开销

而缓存后大约在0.2ms

mCacheCamera = mCacheCamera ?? Camera.main;

Profiler.BeginSample("Foo");
for (int i = ; i < ; i++)
mCacheCamera.GetHashCode();
Profiler.EndSample();

高效向量投影

有时候我们只需要投影轴上的值,而不是坐标。所以可以一行代码搞定:

var value = Vector3.Dot(point, onNormal);

并且少了normal向量的检查。比起Vector3的向量投影省了2步操作。

设置合理的各向异性过滤级别Aniso Level

贴图Aniso Level(Anisotropic filtering level)设置,可以改善mipmap贴图造成的远处模糊

但会增加图形硬件的性能开销,对该值要求不高的贴图,我们可以降低它的值进行优化

实时反射探针优化

如果需求必须使用实时反射探针,可以将其更新模式设为脚本驱动,在渲染前对反射内容进行模型lod替换或shader、材质上的替换

可达到一定优化作用。

阴影优化

在场景中我们可以使用lod模型来投射阴影,场景中对于一些阴影对画面美观影响不大的模型,我们可以关闭这些模型的阴影投射

来进行优化。

NGUI Panel优化(动静分离)

Ngui中panel内的内容是会静态合批的,所以当内容较多时把静态的物件和会变化的动态物件放在不同的panel里

以提高性能。而相比uGUI在其内部有一定的优化操作,类似的优化方式在uGUI中并不会立竿见影。

Unity Editor Tips

===========================

Animator在Editor状态下预览工具

Unity3D中Console控制台的扩展

在Editor下获得时间

EditorApplication.timeSinceStartup

获得编译器自打开到当前的时间。

Editor下获得滚轮滑动值

Event.current.delta

https://docs.unity3d.com/ScriptReference/Event-delta.html

注意要先判断当前鼠标按钮id,滚轮的id是1

获取Project面板中当前选中物体的路径

AssetDatabase.GetAssetPath(Selection.activeObject);

取Unity当前目录的路径(是Unity自身安装目录,取当前项目目录请用Directory.GetCurrentDirectory())

EditorApplication.applicationPath

EditorApplication.applicationContentsPath

显示对话框

EditorUtility.DisplayDialog

UnityDatabase拷贝文件

AssetDatabase.CopyAsset(需要拷贝文件,目标目录);

1.只能拷贝单个文件,不能拷贝目录

2.目标必须是目录路径,不能是文件路径

3.不用System.io而用它,因为插件能够跨平台

Editor状态下设置Scene窗口的相机位置

SceneView.lastActiveSceneView.pivot = ...;
SceneView.lastActiveSceneView.Repaint();

Editor下使用右键菜单

使用GenericMenu可以直接调出Unity的右键菜单

Editor下检查prefab是否都打了标签/读写标签Labels

AssetDatabase.GetLabels

AssetDatabase.SetLabels

Editor下拿到当前拖拽对象(跨窗口)

DragAndDrop.objectReferences

在DragExited时处理拖拽内容,就可以在松手时触发了

if (Event.current.type == EventType.DragExited && DragAndDrop.objectReferences.Length > )
{
var dragItem = DragAndDrop.objectReferences[];
...

如果是多选拖拽,数组里的就是多选的所有对象,否则就是一个。

Editor下控制控件的焦点

通常只要把focus设为空,就可以取消焦点

GUI.FocusControl("");

一些特殊的情况,比如弹出性组件,需要知道控件是否被改变过,而非值是否改变过

可以这么做,通过GetNameOfFocusedControl拿到Focus的name进行比较

var oldFocus = GUI.GetNameOfFocusedControl();
var changedIndex = EditorGUI.Popup(rect, index, array);
var newFocus = GUI.GetNameOfFocusedControl(); if (newFocus != oldFocus)
{
//Do something... GUI.FocusControl("");
}

Editor下获得'剪切','拷贝','撤销'等命令

可以使用commandName获得

Event.current.commandName == "Copy"

EditorWindow窗口大小锁死后没有边框的解决方法

var window = GetWindow(typeof(MyWindow), true);

window.minSize = new Vector2(, );
window.maxSize = window.minSize;

用GetWindow创建窗口时,第二个参数填true。创建为独立的工具窗口,即可恢复边框

Editor下Dirty掉当前修改过的场景对象内容

一般非场景对象用

EditorUtility.SetDirty(target);

而场景对象则用

EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());

Editor下BeginScrollView报错InvalidCastException

和调用顺序有关,也是Layout/Repaint和输入之间的问题。

改变调用先后顺序有可能解决。

在Editor下绘制自定义光标

比如缩放需要绘制缩放的自定义光标,滑动又需要滑动的

使用下方法即可绘制,Rect自定义Cursor区域的Rect。

需要每次OnGUI更新都调,而非只Add一次

EditorGUIUtility.AddCursorRect(Rect, MouseCursor.Pan);

Editor下的LayerMaskField

Unity并没有提供LayerMask控件,其Layer控件返回的只是层编号

下面是一个扩展的LayerMaskField:

public static LayerMask LayerMaskField(string label, LayerMask layerMask)
{
List<string> layers = new List<string>();
List<int> layerNumbers = new List<int>(); for (int i = ; i < ; i++)
{
string layerName = LayerMask.LayerToName(i);
if (layerName != "")
{
layers.Add(layerName);
layerNumbers.Add(i);
}
}
int maskWithoutEmpty = ;
for (int i = ; i < layerNumbers.Count; i++)
{
if ((( << layerNumbers[i]) & layerMask.value) > )
maskWithoutEmpty |= ( << i);
}
maskWithoutEmpty = EditorGUILayout.MaskField(label, maskWithoutEmpty, layers.ToArray());
int mask = ;
for (int i = ; i < layerNumbers.Count; i++)
{
if ((maskWithoutEmpty & ( << i)) > )
mask |= ( << layerNumbers[i]);
}
layerMask.value = mask;
return layerMask;
}

Unity3D心得分享的更多相关文章

  1. [Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手"

    [Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手" 我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的.游戏玩法来自这里(http://ww ...

  2. eclipse使用技巧心得分享

    eclipse使用技巧心得分享   习惯了eclipse开发java程序,公司最近的项目都是idea开发的,同时android studio也是idea原型开发的,在学android开发,所以脱离ec ...

  3. 【创客+】偷心锁屏创始人Jerry创业心得分享

    偷心锁屏创始人Jerry创业心得分享 作者:Jerry权泉,偷心锁屏创始人 我创业的起因非常偶然.08年在东京早稻田大学读博士期间,每周六都去社区活动中心跟日本人志愿者日语对话练习日语.有一次练习结束 ...

  4. Putty的噩梦——渗透工具PuttyRider使用心得分享

    我们在入侵到一台主机的时候,经常会看到管理员的桌面会放着putty.exe,这说明有很大的可能性管理员是使用putty远程管理主机的. 该工具主要是针对SSH客户端putty的利用,采用DLL注入的方 ...

  5. Qt在线技术交流之OpenGL、Quick以及所经历项目开发心得分享

    时间:3月25日晚上7:30 主题:Qt在线技术交流之OpenGL.Quick以及所经历项目开发心得分享 直播:http://qtdream.com 主页.全民TV,可能会加上其他的直播平台进行转播 ...

  6. CSS:命名规范心得分享

    一个好的命名习惯(当然这里指的并不仅仅是CSS命名).不仅可以提高开发效率,而且有益于后期修改和维护. 假设我们当前使用的命名方式都是约定成俗的,所有人都是这样写,那么你去到一个新团队,或者别人来接手 ...

  7. C语言课设心得分享(一)

    今儿上完课设,老师果然讲的比较少,周四还不用去,看来还是学生自己折腾.我在做课设的过程中,攒了一些心得/体会,希望能和大家分享分享,也希望能一起探讨探讨.如果是我能回答的问题,我很乐意能够提供帮助. ...

  8. 我的WebX框架学习总结与心得分享

    最近学习了webx框架, 利用博客园跟大家分享一下自己的学习心得; 周建旭 2014-08-21 网上关于webx的资料少的可怜, 怎么办?  这种情况下不用去求助别人求人只会耽误时间, 不用畏惧; ...

  9. 我的2016年终总结(PF项目框架设计心得分享 2.0rc)

    在无数的日夜里,熬出了多少的黑眼圈,致勤勤恳恳工作的各位朋友与自己.每到了年末的时候总想写的什么,主要是为了回顾以往一年里到底做了什么,这便是年终总结的主要意义.在此我将要总结的是和我在技术层面上成长 ...

随机推荐

  1. CSS基础1

    CSS是层叠样式表(Cascading Style Sheets)的缩写,它有以下优点:①提高页面浏览速度:②缩短改版时间,降低维护费用:③更好的控制页面布局:④实现表现和结构.内容相分离:⑤更方便搜 ...

  2. oracle 关键字

    Oracle 关键字(保留字) DBA账户下执行SQL语句:select * from v$reserved_words ;  可得到所有的关键字:   1 ! 1 2 & 1 3 ( 1 4 ...

  3. Quoit Design---hdu1007(最近点对问题 分治法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给你n(2<=n<=10^6)个点的坐标,然后找到两个点使得他们之间的距离最小 ...

  4. imx6 usb otg config 配置

    imx6 usb的host和slave配置,配置之后,安装gadget模块,就能够在host和slave之间切换. 参考文档: i.MX 6Dual/6Quad Linux Reference Man ...

  5. ms-sql关联表操作

    1.创建数据库employee : create database employee;2.创建员工表EMP:use employee;create table EMP( id int,sex varc ...

  6. asp.net mvc 5 web api 关于Requested resource does not support options 问题

    1.用visual studio 2015 建立一个 web api 应用程序.记住这是一个 web api 应用. 2.新建一个web api . 3.用C#访问,代码如下:[没有问题,返回正确] ...

  7. HDU 5063 Operation the Sequence(仔细审题)

    http://acm.hdu.edu.cn/showproblem.php?pid=5063 题目大意: 题目意思还是比较简单.所以就不多少了.注意这句话,对解题有帮助. Type4: Q i que ...

  8. Excel标题与索引的对应关系

    /// <summary> /// 返回对应标题的索引 /// </summary> /// <param name="columnTitle"> ...

  9. HDU-1233 还是畅通工程

    Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能 ...

  10. NDK开发-零散知识点整理

    JavaVM 标准Java平台下,每一个Process可以产生很多JavaVM对象,但在Android平台上,每一个Process只能产生一个Dalvik VM对象,也就是说在Android进程中是通 ...