Unity3d 周分享(22期 2019.8.30 )

选自过去1~2周 自己所看到外文内容:https://twitter.com/unity3d 和各种其他博客来源吧        早就有了,抱歉才发! 

1、 Unity Transform 性能优化摘要

https://qiita.com/sator_imaging/items/ff5811885f515a0a4998

由于我有机会在逐帧的基础上处理大量的Transform ,我想总结一下Unity中更新Transform 的方法以及比较和优化性能的方法。

 

这意味着值得考虑是否有数百或更多个Transform 的 .position 或 .rotation / .eulerAngles 。

 

  • Unity 2018.4.0f1(Unity 2018 LTS)
  • Windows 10 64bit @ Intel Core i9-9900K 3.6GHz

 

始终在rotation / eulerAngles中缓存对xyzw的访问

有些数据Transform中是没有缓存的!

vector3.x = 0 和 transform.position.x = 0 看起来访问方式很像。但实际上很大差别。 即使你缓存了Transform (高版本的Unity已经在底层进行了缓存,不需要开发者进行缓存了)

..... = new Vector3(cache.eulerAngles.x, cache.eulerAngles.y, cache.eulerAngles.z);

例如上,如果您访问成员三次,将生成三个Vector3副本。

 

在Transform.position,Transform.rotation,Transform.eulerAngles等中,getter不是在字段中而是在属性中设置,每次访问时都有结构体拷贝。 原因是Unity的Transform 存有的是 local 相关的数据, 如果访问世界坐标下的内容 必须现算!!!!!

localRotation是最快的

四元数比欧拉角更快

本地空间比世界空间更快

.localRotation,比.rotation, .localEulerAngles比.eulerAngles快。

Transform.Rotate()要好于 localEulerAngles + =

调整偏移等很容易,因为Euler的角度更直观,.localEulerAngles += .....但Transform.Rotate()更快。

当数量很大时,会产生相当大的性能影响。

https://docs.unity3d.com/ScriptReference/Transform.Rotate.html

 

如果可用,请使用HumanPoseHandler.SetHumanPose()

如果目标是Humanoid,则HumanPoseHandler的SetHumanPose可能更快。

https://github.com/Bizcast/NoitomHi5InertiaToFingerMuscle

摘要

  • 我们尽可能地不处理欧拉角。
  • 将值设置为.eulerAngles / .localEulerAngles 或者访问成员,性能将极度下降。
  • 访问Quaternion / Vector 3的成员是昂贵的,应始终缓存。
    • 缓存Quaternion/ Vector3而不是Transform。

四元数很快

如果添加偏移 = Quaternion * Quaternion是最快的

严禁访问Quaternion / Vector3的xyzw成员

  • 访问.rotation的每个成员而不缓存(4次访问)
    • : .rotation = transform.rotation.xyzw + Time.time;
      • 约200fps
    • 使用缓存后 大约320 fps
      • : .rotation = cachedRotation.xyzw + Time.time;
  • 访问.eulerAngles的每个成员而不进行缓存(3次访问)
    • 伪: .eulerAngles = transform.eulerAngles.xyz + Time.time;
      • 约110fps
    • 使用缓存后 大约190 fps
      • 伪: .eulerAngles = cachedEulerAngles.xyz + Time.time;

 

 

 

 

2、您知道可以在自己的脚本中使用ParticleSystems MinMaxCurve和MinMaxGradient。 它序列化并包含编辑器支持!

Unity3d 周分享(22期 2019.8.30 )_第1张图片

 

Unity3d 周分享(22期 2019.8.30 )_第2张图片

 

 

 

3、刚刚发布了OSS项目UnityNuGet https://github.com/xoofx/UnityNuGet ...提供服务,通过Unity Package Manager使用作用域注册表将@nuget软件包安装到@ unity3d项目中。 这真的是一个早期的预览。

https://github.com/xoofx/UnityNuGet

Unity3d 周分享(22期 2019.8.30 )_第3张图片

 

 

 

 

 

 

 

4、#unitytips 不要忘记100 * 0.5比100/2更快。 可以的话,用乘法代替除法。 (这适用于任何引擎,而不仅仅是Unity。)

https://twitter.com/ffs_nonamesleft/status/1143436080580112384

“注意: 他举得例子不好都是常量计算, 现代编译器都会进行常量展开(编译时直接计算结果了)”

 

还可以 看看 位运算 `100 >> 1` 可能 是最快的!!!

在值不是常数的情况下,iOS上的乘法速度是除法的两倍。在Unity编辑器中,它的速度提高了约20%。

 

 

 

 

 

 

 

 

 

5、 快速脚本只是为了更好地可视化编辑器中的精灵字段。 使用PropertyDrawer将您的精灵显示为缩略图。

将脚本复制到“Assets / Editor”文件夹。

脚本: https://pastebin.com/Y1R7eSA0

Unity3d 周分享(22期 2019.8.30 )_第4张图片

建议您在使用drawer 之前添加对hasMultipleDifferentValues的检查,以防止它覆盖在检查器窗口中多选时所选的所有图像

https://pastebin.com/UipmTQKg

 

 

 

 

 

 

 

6、 关于四元数 Quaternion 的结构:

在四元数可视化中找到了一个存储库,我将在本文后面使用它:

https://github.com/uvivagabond/Visualization-of-physics-in-Unity

在Scenes 文件夹中打开名为TestForQuaternions 的场景。

表示旋转的方法有很多种。借助旋转矩阵,四元数和其他表示,可以借助于欧拉角度来表示旋转。

在本系列中,我将重点介绍四元数。我主要关注他们在Unity中的实现和操作。

https://www.youtube.com/watch?v=OBTU0v0MeeQ

Unity3d 周分享(22期 2019.8.30 )_第5张图片

  • 我们如何定义参数x,y和z

Unity3d 周分享(22期 2019.8.30 )_第6张图片

参数x ,y 和z 负责旋转轴的方向。

  • AngleAxis(), ToAngleAxis(), Angle(), Inverse(), eulerAngles, Euler(), operator *

AngleAxis方法()此方法允许您基于给定(绝对)旋转轴和围绕此轴旋转的角度创建四元数。

我们将四元数的乘法视为连续的身体旋转。A * B≠B * A. 四元数从右向左相乘

欧拉角表示围绕全局坐标系的轴的旋转,即围绕全局轴z ,x 和y 的旋转。

  • Dot(), operator == 和 !=, FromToRotation(), SetFromToRotation(), LookRotation(), SetLookRotation()
  • Lerp(), Slerp(), SlerpUnclamped(), LerpUnclamped(), RotateTowards()

 

四元数的可视化:

https://quaternions.online/

几乎没有困难的四元数描述

https://github.com/NickCuso/Tutorials/blob/master/Quaternions.md

来自fspace的四元数描述

https://www.f-sp.com/entry/2017/08/11/194125

Unity Answers(Bunny 83)

https://answers.unity.com/questions/1297214/quaternions-not-exact.html

https://answers.unity.com/questions/1417640/get-local-euler-angles-by-quaternion.html

https://answers.unity.com/questions/1496797/multiplying-quaternions-and-multiplying-quaternion.html?childToView=1497375#comment-1497375

https://answers.unity.com/questions/1551885/is-quaternion-really-do-not-suffer-from-gimbal-loc.html?childToView=1551892#answer-1551892

https://answers.unity.com/questions/1125215/how-to-flip-a-quaternion-to-face-the-opposite-dire.html?childToView=1496615#comment-1496615

https://answers.unity.com/questions/1365419/locking-rotation-world-z-axis-quaternions-are-shav.html

 

数学描述

https://www.vcalc.com/wiki/KurtHeckman/Quaternion+Calculator+Collection

Mateusz Kowalski

https://www.youtube.com/watch?v=ZgOmCYfw6os

其他

https://www.gamasutra.com/view/feature/3278/rotating_objects_using_quaternions.php

https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation

 

 

 

7、 官方博客: 可寻址资产系统

已经宣布 脱离预览版了 ~~~~

https://blogs.unity3d.com/2019/07/15/addressable-asset-system/

这个支持分析工具也很到位: 比如提供引用计数 功能。

  • Play Mode Simulation: assets load directly from disk without requiring a build process, while still providing the ability to debug asset reference counts through the profiler.
  • Fast Incremental Builds: Addressables ships with the newScriptable Build Pipeline that improves the speed and reliability of incremental builds.
  • Editor Hosting Services: A built-in facility for serving Addressable content to local, LAN connected devices provides a fast, convenient method for iterating content on device.

Unity3d 周分享(22期 2019.8.30 )_第7张图片

 

 

 

 

8、 Unity3D研究院之使用Android的硬件缩放技术优化执行效率

原理如下 http://android-developers.blogspot.it/2013/09/using-hardware-scaler-for-performance.html

https://developer.nvidia.com/content/android-development-using-hardware-scaler-performance-and-efficiency

https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/HardwareScalerActivity.java

https://forum.unity.com/threads/interesting-article-from-google-on-android-hardware-scaler.202625/

这两个文章可以对 分辨率有更好的理解!!!

https://www.cinemablend.com/games/Xbox-One-Unlikely-Hit-1080p-With-DX12-Says-Witcher-3-Dev-66567.html

https://www.cinemablend.com/games/DirectX-12-May-Help-Xbox-One-Much-According-Developer-64410.html

https://www.cinemablend.com/games/1080p-Hard-Achieve-Xbox-One-Due-Complex-GPU-Says-Xbox-Director-62893.html

根据开发人员的说法,DirectX 12可能无法帮助Xbox One

Witcher 3 Dev表示Xbox One不太可能通过DX12达到1080p

当人们说“PS4比Xbox One强大50%”时,这就是他们所谈论的内容的一部分。PS4的GPU上有更多着色器单元,因此每帧输出的视觉效果比Xbox One更多。这就是为什么游戏将更频繁地在PS4上达到1080p

此外,当Xbox One上的游戏可以达到1080p时,通常它会这样做而牺牲其他正在渲染到屏幕上的东西。简而言之,每一块硬件都具有技术上限,而Xbox One的GPU由于较旧和较低等级的架构而具有如此低的上限,因此难以在游戏中始终如一地达到1080p。

最终,DirectX 12之前曾被提及为更好的CPU流水线指令,而不是检修GPU的运行方式。(还是跟硬件有关呗,这是因为GPU较弱,ESRAM有限)

这就像尝试使用软件优化来使GTX 7800达到2K分辨率。是的,这是可能的,但你必须做出巨大的牺牲才能在屏幕上显示什么来达到分辨率。你不能用软件神奇地升级硬件; 优化不能解决这个问题。

Xbox 360的1040x600分辨率与Xbox One的1408x792输出相差500,736像素。战地4在Xbox One上的720p相比PS4的900p输出相差518,400像素。

 

Unity3d 周分享(22期 2019.8.30 )_第8张图片

Unity 4.x 的代码中确实有使用:

Unity3d 周分享(22期 2019.8.30 )_第9张图片

 

Unity3d 周分享(22期 2019.8.30 )_第10张图片

    // $TODO Make this less complicated ;)
    // This code is unnecessarily complicated, just to cover the fact that it can be called both from
    // native code (through scripts Screen.SetResolution) and from Java (GLThread onSurfaceChanged).
    protected void setScreenSize(final int w, final int h, final boolean low_profile)
    {
        final SurfaceView view = mGlView;
        Rect rect = view.getHolder().getSurfaceFrame();
        if (Log.LOG_INFO)
            Log.Log(Log.INFO, String.format ("setScreenSize: %dx%d (%dx%d / %dx%d)",
                                          w, h, rect.width (), rect.height (),
                                          view.getWidth (), view.getHeight ()));

        // If w/h matches the view, or if w/h is 0/0, we use the layout size (and disable any fixed-size surface holder)
        final boolean reset = view.getWidth() == w && view.getHeight() == h || w == 0 && h == 0;
        // If w/h is -1/-1, we keep whatever was set before (no change to screen resolution)
        final boolean keep = w == -1 && h == -1;
        if (!keep)
        {
            if (reset)
            {
                if (Log.LOG_INFO) Log.Log(Log.INFO, "setScreenSize: setSizeFromLayout()");
                mSurfaceFixedW = 0;
                mSurfaceFixedH = 0;
            }
            else
            {
                if (Log.LOG_INFO) Log.Log(Log.INFO, "setScreenSize: setFixedSize(" + w + ", " + h + ")");
                mSurfaceFixedW = w;
                mSurfaceFixedH = h;
            }
        }
        else
        {
            boolean fixed = (mSurfaceFixedW != 0 || mSurfaceFixedH != 0);
            if (fixed)
            {
                if (Log.LOG_INFO) Log.Log(Log.INFO, "setScreenSize: keeping fixed size " + mSurfaceFixedW + "x" + mSurfaceFixedH);
            }
            else
            {
                if (Log.LOG_INFO) Log.Log(Log.INFO, "setScreenSize: keeping layout size " + view.getWidth() + "x" + view.getHeight());
            }
        }

        runOnUiThread(new Runnable () {
            public void run () {
                if (!keep)
                {
                    if (reset)
                        view.getHolder().setSizeFromLayout();
                    else
                        view.getHolder().setFixedSize(w, h);
                    view.invalidate();
                }
                if (HONEYCOMB_SUPPORT)
                    HONEYCOMB.setSystemUiHidden(UnityPlayer.this, low_profile);
            }
        });
    }

 

 

9、基于 Chrome DevTools 的 Lua 5.3 调试器

https://mare.js.org/zh-cn/?tdsourcetag=s_pcqq_aiomsg

Unity3d 周分享(22期 2019.8.30 )_第11张图片

 

 

 

 

 

10、多线程同步I/O和单线程异步I/O

http://linzhi.github.io/multithread-io-singlethread-io

多线程带来的好处是在多核CPU的情况下利用更多的核, 单线程事件编程模式的异步I/O与多线程阻塞式I/O相比,异步I/O少了多线程的开销。对OS来说,创建一个线程的代价比较昂贵,需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU的缓存被清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。

单线程事件驱动的异步I/O有个缺点就是异步程序不是很好理解,编写异步程序比较困难。

 

Python进阶:聊聊IO密集型任务、计算密集型任务,以及多线程、多进程

https://zhuanlan.zhihu.com/p/24283040

不管文章中的结论, CPU密集型任务分为 IO(网络/磁盘读写)密集型任务, 计算密集型任务

常见的IO请求有网络IO,磁盘IO。

也有一种说法: https://blog.csdn.net/o83290102o5/article/details/78723329

IO密集/CPU密集

Unity的 Job 强调的是针对CPU 多核, 利用多线程加速,针对的就是CPU密集,文章中有提到对IO密集 可能提升。 https://blogs.unity3d.com/cn/2018/10/22/what-is-a-job-system/?_ga=2.203082005.526565089.1561874920-1366382285.1535636176

What problem does it not solve?

A Job System is not designed to be a solution for long running low priority tasks, and it is not designed for operations waiting instead of using CPU resources, like IO. It’s still possible to do these things, but it’s not the primary purpose of the Job System, which means they come with some limitations you need to be aware of.

 

这里的问题和答案是想要的:

http://cn.voidcc.com/question/p-uzupaljk-hp.html

执行多次磁盘操作时,多线程是否有帮助,阻碍或没有任何影响?

到目前为止,大部分答案都与操作系统调度程序有关。但是,我认为还有一个更重要的因素会导致您的答案。你正在写入一个物理磁盘还是多个物理磁盘?

即使您与多个线程并行... IO到单个物理磁盘本质上是一个序列化操作。每个线程都必须阻塞,等待有机会访问磁盘。在这种情况下,多个线程可能无用......甚至可能导致争用问题。

但是,如果你正在写多个流到多个物理磁盘,处理它们同时应该给你的性能的提高。这是管理的磁盘尤其如此,像RAID阵列,SAN设备等

我不认为这个问题有很多工作要做,因为它更多的是与磁盘的物理方面(OS调度器s)你的写作。

 

https://blueswind8306.iteye.com/blog/1983914

发编程系列-多线程IO vs 单线程IO

结论: 可以看出,当测试文件增多时,在单线程情况下,性能没有降低。但多线程情况下,性能降低的很明显,由于IO阻塞导致CPU基本被吃满。所以在实际编码过程中,如果遇到文件读写操作,最好用一个单独的线程做,其它线程可以分配给计算/网络IO等其它地方。而且要注意多个进程之间的文件IO的影响,如果多个进程分别做顺序IO,其实全局来看(如果是一块磁盘),就变成了随机IO,也会影响系统性能。

 

 

 

 

 

11、 关于UGUI 组件的 Inspector扩展困难问题。

https://stackoverflow.com/questions/32754210/can-ui-text-inspector-be-extended-in-unity3d

这个问题的解决方案有两个关键点:

用继承的方式避开同系统编辑器扩展的冲突

所扩展的编辑器类要继承ImageEditor类而不是Editor类

一开始就不要使用系统默认组件, 而是继承他们弄自己的一个类。 个人觉得不是特别美好。

当然了,不使用默认的DLL ,而是使用源代码方式【Unity又提供了程序集定义文件 可用】,这这样在处理源代码等方面就方便多了。

或者升级到Unity2019 UGUI本身作为 Package 出现了,就是可以查看和编辑源代码的!!!

 

 

 

好奇一个点就是怎么查看 动态字体动态生成的 Font Texture . 没有找到答案,只能设置为Unicode,然后设置贴图可读。但这就不是动态字体了。

看到其他不太有用的链接。

从 Font 中生成对应字符的贴图。 可以直接取,如果不存在就生成。

https://pastebin.com/SZ3S6WyQ

Create a font texture

https://www.lynda.com/Unity-tutorials/Create-font-texture/444940/483622-4.html

http://blog.almostlogical.com/2010/08/20/adding-text-to-texture-at-runtime-in-unity3d-without-using-render-texture/

在不使用渲染纹理的情况下在Unity3D中运行时添加文本到纹理

http://blog.almostlogical.com/2010/08/20/adding-text-to-texture-at-runtime-in-unity3d-without-using-render-texture/

TextToTexture.cs

http://blog.almostlogical.com/workingExamples/TextToTextureDemo/TextToTexture.cs

 

 

 

 

 

12、 FPS 的显示到底怎么处理比较合适?

https://github.com/Unity-Technologies/UniteAustinTechnicalPresentation/blob/48cbbffc485b7b9fd5d48a861136d60a644c740f/StressTesting/Assets/Scripts/Rendering/TextureAnimatorSystemGui.cs

还是一句代码就可以计算? 这个变动更频繁~

https://github.com/Unity-Technologies/Animation-Instancing/blob/d753877b6d0626989cff0d99971df712a10e33d9/Assets/AniInstancing/Example/Scripts/showFPS.cs

还区分Render FPS 和 Game FPS: 看了下这两个时间基本一致。

https://github.com/Unity-Technologies/GenLockProofOfConcept/blob/aca504b942e5d0288d5c070a3589b9003b0b5324/Assets/UpdateStatsText.cs

概念证明Unity项目可以更精确地控制帧率和GenLock

https://github.com/Unity-Technologies/GenLockProofOfConcept/tree/aca504b942e5d0288d5c070a3589b9003b0b5324

或者 :

https://github.com/Unity-Technologies/FPSSample/blob/147f4719b61c2857d342bc0722c88d165bab3378/Assets/Scripts/Game/Core/GameStatistics.cs

MiniProfiler.cs

https://github.com/Unity-Technologies/ScriptableRenderPipeline/blob/dc09aba6a4cbd997f11e32a51881bf91d1b55b5e/com.unity.render-pipelines.high-definition/Runtime/Core/Script/Profiler/MiniProfiler.cs

https://github.com/Unity-Technologies/Benchmark/blob/master/Assets/Scripts/FPSTest.cs

好奇Unity Game 视图中 Stats 面板中的帧率是怎么计算的? 时间取Mathf.Max(frameTime, renderTime); 主线程和渲染线程的最大值。

https://github.com/Unity-Technologies/UnityCsReference/blob/9034442437e6b5efe28c51d02e978a96a3ce5439/Editor/Mono/GameviewGUI.cs

 

 

 

13、 https://answers.unity.com/questions/210953/mobile-bump-performance.html

法线贴图是每像素效果。对象数量无关紧要; 重要的是使用法线贴图着色器绘制了多少像素。如果您可以使用对象空间法线贴图,则无需担心。如果需要切线空间法线贴图,那么在编写着色器时需要更加小心。假设你提到了一个亮点。每增加一盏灯就需要额外通过,这很容易破坏性能。

---------------------------------------------

五年前的一个讨论: https://www.reddit.com/r/Unity3D/comments/29qtbt/is_there_a_performance_impact_for_using_different/

使用不同的纹理贴图会产生性能影响,例如凹凸贴图,高光贴图等与纯纹理相对的?

-----------------------------------

是。为了使它成为真实的教诲:将每??种不同类型的纹理视为另一种纹理,其中每种纹理都比下一种更昂贵。漫反射是所有点亮纹理中最便宜的,然后是法线贴图,然后是镜面贴图,依此类推。

 

所以,基本上:渲染一个凸起的镜面反射纹理(漫反射,正常和镜面反射)比仅仅漫反射纹理贵两倍。

----------------------------

显然也一定是的。真正的问题是它是否以及如何引人注目。并且总是以“它取决于”来回答,特别是在......其他一切。正在使用的硬件,正在使用的操作系统,GPU驱动程序,设备插入或未插入,每帧执行多少,我们谈论了多少个调用等等等。

 

请注意,纹理需要是:

 

上传到VRAM(一次)

 

然后,对于着色器进行采样,他们需要“绑定到纹理采样器”,这是一个很小的CPU和GPU开销,但它总共加上1000s的drawcalls 30-even-even-60x / second

 

片段着色器是一个为每个片段(像素)并行运行的程序,每个程序都从VRAM读取纹理中略有不同的纹素分数

 

压缩起到了作用,更小的纹理上传速度更快,访问速度也更快,即使在动态解压缩的情况下也是如此

 

我们现在拥有极其强大的硬件......如果你有一点室内设计师的场景,或者展示一个非常详细的车型或其他东西,不要担心。但是就像现在这样强大,它仍然无法扩展到无限数量的纹理,材质和用于实时60FPS渲染的绘图调用。因此,在某些时候,您可能正在研究关闭颠簸或大规模雾化几何形状的颠簸或规格。

 

最好是在开发过程中使所有内容都处于开/关状态。不一定是最终产品的最终用户,而是让您了解随着项目的发展每个小功能的不同之处。对于个人自定义环境,项目环境等,它始终是独一无二的。

 

除了以上内容之外,特别谈论某些纹理:

 

bumpmaps添加更多计算,而不仅仅是将其采样到着色器。现在,他们通过内插器将计算出的切线帧从顶点发送到片段着色器,以便可以在几何法线的顶部应用法线贴图。发送的数据越多,使用的带宽越多,两个着色器都会发生更多的计算。我记得第一款使用凹凸贴图的游戏,这是一项仅在一个恐龙皮肤上用于特写镜头的特殊功能。如今已经不再那么重要了,但没有任何东西是免费的。

 

镜面着色器(以及为什么你会使用spec-map)比基本的“仅漫反射”Lambert执行稍微更密集的光照计算,Lambert是一个简单的视图无关点积。依赖于视图的内容(如反射或镜面反射高光)需要在使用它的所有着色器中进行更多计算。在现代硬件和驱动程序上它仍然相当快,但成本是存在的,在某些时候你可能会开始注意它,因为你增加了你在GPU上投入的东西,特别是在移动设备上。

 

甚至最简单的视差映射的高度图也将依赖于视图的计算引入着色器

 

这是所有“特定于用例的成本” ,除了基本的真正纹理 - 甚至是反照片外,每当有更多纹理添加到材质时,都会消耗更高的内存和带宽。

 

 

数学上,一个spec地图只增加了一个额外的乘法照明方程(specularity_final * map),所以它被认为是一个非常“自由”。任何与表面形貌混淆的东西都是昂贵的(凹凸)。

 

对于地图,将斑点/凹凸/自发光/某些地图映射到一个RBGA纹理并单独引用这些通道非常常见,这样可以节省开销。

 

DOTA 2的建模指南非常适合用于实现这一点。

 

------------------------------

 

好的 从技术上讲,你是对的。如果你在做镜面反正,规范地图只会增加平时的质感“开销”和乘法。

 

但是人们经常会以特别自发的方式解决这个问题:“嘿,我这里有一个规格图,所以我选择了一个规范着色器”。然后他们添加了与朗伯漫反射相比的镜面光照的额外(通常是现在完全可接受且合理但是额外的)开销。;)在那种情况下,他们增加了更多的工作,而不是“再多一次特征提取和乘法”。在内置BlinnPhong照明模型(即任何内置镜面着色器)的情况下,它是一个永远不会自由的pow()和内置Lambert照明模型的其他几个指令(即任何内置的非所有不需要的特殊着色器(如漫反射)。镜面光照需要视图方向,即在垂直着色器中进行更多计算,将更多数据发送到frag着色器,以及在最终照明功能中执行更多工作。完全值得的,

 

----------------------------

在性能影响方面,不同类型的纹理之间几乎没有区别,它们只是位,通常是每通道8位压缩RGB占用一定量的内存和一定量的时间流入其中。而已。在那里画了什么,镜面地图,漫反射,一些超奇怪的splat地图与自定义频道排列,绝对没有任何改变

单词“性能影响”与使用这些纹理的着色器效果的复杂性有关,而不是纹理本身。他们只能用它们的分辨率来影响它(需要更多的内存,样本,带宽,流媒体时间等),但我假设你不是在问这里的分辨率。如果一个纹理是以一种格式编码的,比方说,只使用一个通道而不是三个,好,它会更快 - 但仅仅因为它是要处理的数据的三分之一,而不是因为它绘制的东西在某种程度上更好对于性能而言,比如说,漫反射贴图。

GPU对类型之间的差异一无所知。有一些特殊的压缩类型,如果使用的话,会让GPU做一些额外的东西,但是当你比较像镜面和漫反射这样的地图时,它们不会弹出,这些地图通常是普通的DXT,具有相同的平面成本。如果您突然将镜面反射贴图作为输入提供,则性能差异永远不会出现在漫反射着色器中。如果您需要采样两个地图而不是一个地图,或者使用来自它们的样本执行不同的,更重的计算,它会跳转,依此类推。

-------------------------------------------------- 顺便提一下 看到过的文章:

http://www.procedural-worlds.com/gaia/tutorials/mobile-unity-scene-optimisation-with-gaia/

  1. Use a maximum of 4 textures on your terrain. Every multiple of 4 textures causes the unity terrain shader to render an additional pass (draw the terrain all over again). So even adding 1 texture over this boundary of 4 will cause another pass.
  1. 在地形上最多使用4个纹理。4个纹理的每个倍数使统一地形着色器渲染一个额外的通道(再次绘制地形)。因此,即使在4的这个边界上添加1个纹理也会导致另一个传递。

 

 

 

 

 

 

14、 【技術講座】1080322-Unity璀璨奪目篇:獨立製作MMORPG【阿比頓:無盡之島】歷程分享 - 半角鹿遊戲工作室

看一下他们用到的插件: Odin, Status Indicators, Amplify Shader, SyntyStudio , Post Processing Stack , Aura Volumetric Lighting , Text Mesh Pro for UGUI ,

Unity3d 周分享(22期 2019.8.30 )_第12张图片

后端框架选择 : Photon Server (使用这个) , SmartFoxServer , KBEngine

数据库的选择(都有用 ): MySql - 存储游戏内部设定资料

PostgreSQL - 玩家资料存储,大量IO

Redis - 排行榜 等, 需要即时大量捞数据 但丢失疼痛度低着。

 

 

 

 

15、 [Unity]关于在2019.2中添加的TryGetComponent

Unity3d 周分享(22期 2019.8.30 )_第13张图片

到目前为止,当获取“未分配组件的状态”时,GetComponent通常的方法是暂时获取它并检查内容是否为空。

var component = array[i].GetComponent(); if (component != null) component.Value++;

TryGetComponent 将检查它是否可以获得返回值的组件。例如,可以如下描述与上述相同的操作。

if( TryGetComponent(out SampleComponent comp)) comp.Value++;

做一下性能测试:

        SampleComponent comp;
        Profiler.BeginSample("test_TryGetComponent");
        for (int i = 0; i < data.capacity; i++)
        {
            if( TryGetComponent(out  comp))
                comp.Value++;
        }
        Profiler.EndSample();
        Profiler.BeginSample("test_GetComponent");
        for(int i=0; i();
            if (component != null)
                component.Value++;
        }
        Profiler.EndSample();

编辑器下:

Unity3d 周分享(22期 2019.8.30 )_第14张图片

Build 之后:

Unity3d 周分享(22期 2019.8.30 )_第15张图片

没有组件的情况下 编辑器中测试:

Unity3d 周分享(22期 2019.8.30 )_第16张图片

没有组件的情况下 Build中测试:

也就是说,组件存在的情况下使用GetComponent似乎更快? 什么情况?。

http://tsubakit1.hateblo.jp/entry/2019/07/16/233235

 

 

 

 

16、每次阅读文档都会有不一样的收获!

https://unity3d.com/fr/learn/tutorials/topics/best-practices/camera?playlist=30089

RenderTexture切换

切换渲染目标时,图形驱动程序在帧缓冲区上执行加载和存储操作。例如,如果在两个连续帧中渲染到视图的颜色缓冲区和纹理,系统会在共享内存和GPU之间重复传输(加载和存储)纹理内容

Geometry几何

必须将场景中GameObjects的几何复杂度保持在最低限度,否则Unity必须将大量顶点数据推送到图形卡。200k静态三角形是低端移动的保守目标。但是,这还取决于您的GameObjects是动画还是静态。

Unity3d 周分享(22期 2019.8.30 )_第17张图片

在Unity中,通过使用具有高多重计数的游戏对象,而不是具有低多边形数量的许多游戏对象,可以获得更好的渲染性能。

从几何体中删除无法看到的面,并且不渲染玩家从未看到的东西。例如,如果您从未看到橱柜的背面靠在墙上,则橱柜型号的后侧不应有任何面。

尽可能简化网格。根据目标平台(特别是在移动设备上),请考虑通过高分辨率纹理添加细节以补偿低多边形几何,可能的视差映射和曲面细分。请注意并记住要定期进行配置,因为这会影响性能,并且可能不适合或在目标平台上可用。

通过尽可能多地将详细信息烘焙到纹理中来降低像素复杂度(每像素计算。例如,将镜面高光烘焙到纹理中以避免必须计算片段着色器中的高光

 

https://unity3d.com/fr/learn/tutorials/topics/best-practices/framebuffer

双重和三重缓冲

如果设备支持双缓冲或三缓冲,则图形驱动程序分别需要两个或三个帧缓冲区。使用多个帧缓冲带有图形内存含义,尤其是当应用程序在Native Resolution上运行时,尤其是在高分辨率显示器上。

颜色缓冲

使用的帧缓冲区数量主要取决于图形驱动程序,每个帧缓冲区有一个颜色缓冲区。

模板和深度缓冲

该模板缓冲和深度缓冲,如果图形功能使用它们只能绑定到帧缓冲区。如果您知道应用程序不需要它们,则应禁用它们,因为帧缓冲区会根据分辨率占用大量图形内存,并且需要创建资源。

要禁用深度缓冲区和模板缓冲区,请转到“ 播放器设置”(菜单:“ 编辑”>“项目设置”>“播放器”)窗口,向下滚动到“ 分辨率和演示文稿”部分,然后选中“ 禁用深度和模板*”复选框。

在移动GPU上,深度缓冲区和模板缓冲区是两个独立的缓冲区,深度缓冲区为24位,模板缓冲区为8位。它们不会组合在一个缓冲区中,这与桌面平台不同,在桌面平台上缓冲区被组合成一个32位缓冲区,深度缓冲区使用24位缓冲区,模板缓冲区使用8位缓冲区。

原始分辨率

现代手机的显示器分辨率非常高。原始分辨率通常超过1080p。即使对于现代游戏机,1080p也很难在不降低性能的情况下提供支持。

提示: 控制应用程序的分辨率,甚至可能将其曝光,以便用户在想要节省电池寿命时降低分辨率。

使用Screen.SetResolution命令可以降低默认分辨率并在不降低质量的情况下恢复性能。

注意:将分辨率设置为原始分辨率的一半可能并不总是对视觉保真度产生积极影响。

缓冲区大小

计算帧缓冲区大小并比较从本机探查器获得的结果。例如,全高清屏幕的分辨率为1920 x 1080,即2073600像素:

将此乘以用于颜色通道分辨率的位数后,得到66355200,这是位所需的内存。

现在将它除以8,1024和1024,得到字节数,千字节数和兆字节数。

下表按分辨率和位/通道提供内存。

Unity3d 周分享(22期 2019.8.30 )_第18张图片

运行在三星Galaxy S8上的分辨率为1440 * 2960的应用程序在使用32位颜色缓冲区,24位深度缓冲区和8位缓冲区进行三重缓冲操作时,将使用97.68MB的图形内存作为帧缓冲区。位模板缓冲区。这些数字可帮助您比较内存统计信息,同时使用iOS上的本机分析器(仪器中的IOKit分配)和Android(dumpsys meminfo中的 EGL mtrack分配)分析内存。

 

https://unity3d.com/fr/learn/tutorials/topics/best-practices/shaders?playlist=30089#Shader%20Preloading

光照贴图

在适当的情况下,您应该使用最基本的着色器。利用便宜的Mobile> Unlit(支持光照贴图)着色器为场景添加光照贴图。

着色器关键字

着色器关键字是全局的。目前,您只能使用196个关键字,因为Unity本身在内部使用60个。

构建着色器时,可以使用下划线_来禁用/启用目的功能,以避免占用全局关键字(例如,使用#pragma multi_compile _SUPER_FEATURE时)。

提示:在multi_compile上使用shader_feature,因为它通过剥离不需要的关键字来节省内存。

着色器变体

着色器通常包含多种变体,这些变体会增加构建大小,而这可能不是必需的。

如果在着色器中使用以下定义,Unity将生成定义了A和C的变体:

#if 1

#pragma multi_compile A B

#else

#pragma multi_compile C D

#endif

Unity在预处理步骤之前运行用于解析变体的#pragmas的代码。避免在着色器代码中使用#defines。要了解有关着色器变体的更多信息,请参阅制作多个着色器程序变体的文档。

提示:如果不需要,请在图形设置中禁用着色器设置(如线性雾)。这将删除变体,以便在进行构建时处理来自所有着色器的这些设置。

 

https://unity3d.com/fr/learn/tutorials/topics/best-practices/textures?playlist=30089

GPU上传 (GPU Upload)

完成加载后,Unity会将纹理直接上传到GPU,并且不会等到纹理在摄像机视锥中看到。

当加载线程完成加载场景或资产时,Unity需要唤醒它们。加载的位置和方式取决于Unity版本和用于初始化加载的调用。

加载行为

如果从AssetBundles,Resources或Scenes加载资产,Unity会从预加载线程(磁盘I / O)转到图形线程(GPU上载)。如果您使用Unity 5.5或更高版本,并且启用了图形作业,Unity会从预加载作业直接进入GPU。

觉醒行为

在唤醒所有场景游戏对象后,Unity直接唤醒主线程上的资产。如果使用AssetBundle.LoadAsset,Resources.Load或SceneManager.LoadScene来加载资产和场景,Unity会阻止主线程并唤醒所有资产。如果您正在使用这些调用的非阻塞版本(例如,AssetBundle.LoadAssetAsync),Unity会使用时间切片来唤醒资产。

记忆行为

在一次加载多个纹理时,如果上传速度不够快或主线程停止,您可以调整纹理缓冲区。但是,更改默认值可能会导致高内存压力。在Unity指南中的Memory Management的RingBuffer部分中使用时间片唤醒时,您可以阅读有关纹理缓冲区中内存限制的更多信息。

注意:如果GPU内存过载,GPU会卸载最近最少使用的纹理,并强制CPU在下次进入相机平台时重新上传它。

https://docs.unity3d.com/560/Documentation/Manual/AsyncTextureUpload.html

异步纹理上传

异步纹理上载允许从磁盘异步加载纹理数据,并在Render-thread上启用时间片上传到GPU。这减少了主线程中GPU上传的等待时间。

笔记

对于非读/写启用的纹理,TextureData是resS(流媒体资源)的一部分,现在上传发生在Render-Thread上。在调用AwakeFromLoad之前,可以保证Texture的可用性,因此在加载顺序或渲染上的Textures的可用性方面没有变化。

对于其他类型的纹理加载,例如启用读/写的纹理,直接使用LoadImage(byte []数据)函数加载的纹理,或从Resources文件夹加载,不使用异步缓冲区加载 - 使用较旧的同步方法。

优化加载性能:了解异步上载管道中文翻译: https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247495299&idx=1&sn=8f0a56a98a3c17fb6ccfacbccbda3000&chksm=fe1dda28c96a533e8fdfcf8feb5b41ccd595d66cd31968a5748413dacc95ae9e2f78f4d7802d&scene=21#wechat_redirect

Texture Mipmap Streaming()2018.2 》 有很多调试脚本的功能!!!!

https://docs.unity3d.com/Manual//TextureStreaming.html

https://docs.unity3d.com/Manual//TextureStreaming-API.html

 

 

首先,没弄懂 这个东西是否带来了性能上的提升?

它用少量CPU资源以节省潜在的大量GPU内存。

Texture mipmap Streaming系统使您可以控制实际加载到内存中的mipmap级别。 通常Unity会加载存储在磁盘上的所有mipmap级别,但是使用此系统,您可以直接控制加载哪些mipmap级别。

通常,这样的系统通过仅加载渲染场景中当前相机位置所需的mipmap来减少纹理所需的总内存量。 它可以节省少量CPU成本,从而节省大量GPU内存。

在维京村的场景中,系统节省了25-30%的纹理内存,具体取决于相机的位置。

 

 

https://docs.unity3d.com/Manual/AsyncTextureUpload.html

这个异步纹理上传 和 Texture Streaming 有关系么????

 

使命召唤手游有 使用 : Texture Streaming

https://mp.weixin.qq.com/s?src=11×tamp=1563935430&ver=1747&signature=qIm5L3zeFnOXEUDvHZn0BMxfp1TMSsc7e9cPfY4CEwtFIS4wzaMGEchnXLOE*7NPjmxY9rO2WSANiqc*ujdkEanX7o6njUbrLaJutf4clUjAJfg7bSW4OTHHloVpGEsM&new=1

 

 

17、 关于RenderTexture :

RenderTexture.format颜色格式可以指定,但内存负载很高,因为不能使用PVRTC等压缩系统。因此,请注意不要使用太多的尺寸或数量。您可以检查

终端是否支持指定的颜色格式SystemInfo.SupportsRenderTextureFormat。

 

Using Graphics.CopyTexture vs. Texture2D.ReadPixels????

if (SystemInfo.copyTextureSupport == UnityEngine.Rendering.CopyTextureSupport.None)

{

//High GC allocs here

Color[] pixelBuffer = sourceTexture.GetPixels((int)r.x, (int)r.y, width, height);

output.SetPixels(pixelBuffer);

} else { // GC的数量在这里大大减少

Graphics.CopyTexture(sourceTexture, 0, 0, (int)r.x, (int)r.y, width, height, output, 0, 0, 0, 0);

}

 

Google 提供了一个插件: Tilt Brush : https://www.tiltbrush.com/?source=post_page---------------------------

https://medium.com/google-developers/real-time-image-capture-in-unity-458de1364a4c

Unity 2018.1引入了一个新的异步GPU回读 API,这将使这个过程变得更加容易。(2018.2 版本被转正的)

允许异步读回GPU资源。

此类用于将资源数据从GPU复制到CPU而不会出现任何停顿(GPU或CPU),但会增加几帧延迟。

https://docs.unity3d.com/2018.1/Documentation/ScriptReference/Experimental.Rendering.AsyncGPUReadback.Request.html?source=post_page---------------------------

https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadback.html

https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadbackRequest.html

更关注文章中提到的 性能问题:

要在Unity中捕获帧缓冲区,您需要两件事:RenderTexture和Texture2D。然后 复制像素 。

// Setup a camera, texture and render texture

Camera cam = ...;

Texture2D tex = ...;

RenderTexture rt = ...;

// Render to RenderTexture

cam.targetTexture = rt;

cam.Render();

// Read pixels to texture

RenderTexture.active = rt;

tex.ReadPixels(rectReadPicture, 0, 0);

// Read texture to array

Color[] framebuffer = tex.GetPixels();

以下是缓慢的根本原因: (他们的用例是视频,所以需要在Update中处理)

1、GetPixels()函数会阻塞以等待ReadPixels()完成

2、刷新GPU时,ReadPixels()会阻塞

3、GetPixels()在每次调用时分配一个新数组,使垃圾收集器崩溃

第一个问题实际上很容易避免。我们将在ReadPixels()和GetPixels()之间放置一帧延迟。

更棘手的是ReadPixels()将触发GPU刷新。这究竟是什么意思?

当向GPU发出命令/绘制调用commands/draw calls时,这些命令被批处理到驱动程序中的批量命令缓冲区中。“刷新GPU”意味着等待当前命令缓冲区中的所有剩余命令执行。CPU和GPU可以并行运行,但在刷新期间,CPU处于空闲状态,等待GPU也变为空闲,这就是为什么这也称为“synchronization point.”“同步点”。为什么会发生这种情况呢?

https://docs.microsoft.com/zh-cn/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-mapping

“GPU / CPU并行性的最坏情况是需要强制一个处理器等待另一个处理器完成的工作结果。”

如文档所述,GPU拷贝可以流水线化并与CPU并行执行。但是,如果在复制完成之前请求数据,则返回一致值的唯一方法是完成所有挂起的命令,从而强制CPU-GPU同步。

OnPreRender()似乎很有希望,但正如您在下面的跟踪中所看到的,这种方法略微提高了性能,但是在开始传输之前,CPU仍然阻止了一些工作要完成:

 

问题: https://forum.unity.com/threads/rendertexture-to-texture2d-too-slow.693850/

RenderTexture只存在于GPU上,这就是为什么你需要将数据复制到Texture2D资产的原因,这在GPU和CPU上都存在(尽管两个版本是分开的,并且它们并不总是匹配!)。ReadPixels要求GPU将数据复制回CPU。这很慢,部分原因是GPU被设计为从CPU接收数据,而不是将其发回,而且因为GPU在发出请求时可能正忙。无论哪种方式,在许多情况下,恢复数据可能会非常缓慢。

所以解决方案通常是不使用ReadPixels。如果要将渲染纹理复制到纹理2D中以在场景中的其他内容上使用它,您可以使用在GPU上执行复制的Graphics.CopyTexture(),或者直接使用渲染纹理本身。

如果您希望以某种方式处理图像,您可能希望使用blit()和自定义着色器或计算着色器在GPU上完成这项工作。如果数据确实需要在CPU上,比如为了某些游戏代码原因而使用其中的信息,或者为了获取屏幕截图,那么您希望研究使用AsyncGPUReadback。

问题来了: 如果只是使用RenderTexture, 而不去读像素等数据呢? 下面的答案解开了我的疑惑!!!

RenderTexture 只是引用,其中的像素等数据并没有从GPU获取,现在把RenderTexture赋值给UGUI的 RawImage 是不会有性能问题的, RawImage在渲染的时候Shader采样的对象是已经在GPU中存在的,也不会有Upload等操作。

“ 基本的Texture类基本上是一个带有一堆共享属性的虚拟类。除了明显的共享属性集之外,主要的共同点是它们作为一种将CPU端与实际GPU端资产相关联的方式。将纹理指定给材质时,它只是附加的参考编号。当CPU告诉GPU渲染一个对象时,它会“使用这个着色器ID渲染此网格ID,并使用这些设置和纹理ID”。

每个Texture子类都在其上实现了一些独特的功能。其中大多数,如Texture2D和TextureCube等,都有一个可选的CPU端数据存储,用于暂时从磁盘加载纹理资源时暂时使用,然后在上传到GPU后清除,或者保留在CPU端阅读和操纵。如果修改CPU上的Texture2D,用于渲染的GPU侧图像将不会显示这些更改,直到您调用Apply(),将数据从CPU复制到GPU。或者,如果您使用CopyTexture()将一个纹理复制到另一个纹理,如果您正在复制的纹理在CPU上不存在(如已清除其CPU侧数据或渲染纹理的纹理),则只有GPU数据已更改,CPU端数据不会显示副本的结果。

RenderTexture永远不会有数据的CPU端版本。它假设它始终完全存在于GPU上。渲染纹理具有GPU可以渲染的区别。特别是可以绑定为渲染目标的东西,片段着色器的输出可以写入。普通纹理不能这样做。但是当在材质上设置为纹理属性时,两者都可以在着色器中读取,并且着色器不知道存在任何差异。

*一些旧的移动硬件有一些渲染纹理格式可供渲染,但不能读取,或至少不能很好地读取。但这不再是一个问题了。

性能优化点: https://docs.unity3d.com/ScriptReference/RenderTexture.GetTemporary.html

分配临时渲染纹理。

当您需要快速RenderTexture进行一些临时计算时,此功能已经过优化。一旦完成,就使用ReleaseTemporary释放它,因此如果需要,另一个调用可以开始重用它。

内部Unity保留了一组临时渲染纹理,因此对GetTemporary的调用通常只返回已创建的纹理(如果大小和格式匹配)。这些临时渲染纹理在不用于几帧时实际上会被破坏。

如果你正在进行一系列后期处理“blits”,那么最好为每个blit获取和释放一个临时渲染纹理,而不是预先获得一个或两个渲染纹理并重用它们。这对于移动(基于磁贴的)和多GPU系统来说非常有用:GetTemporary将在内部执行DiscardContents调用,这有助于避免对先前渲染纹理内容进行昂贵的恢复操作。

您不能依赖从GetTemporary函数获得的RenderTexture的任何特定内容。它可能是垃圾,或者可能会被清除为某种颜色,具体取决于平台。

 

 

 

18、 一组测试数据,低端手机(画质,分辨率,后处理等都最高)

,主要测试在不牺牲显示上画质的情况下测试顶点,三角面等渲染数据对性能影响,减模减面合批处理到底什么样的数据比较合适????。 (可以通过只改变 Camera的 Far Clipping Planes的值,这样场景中的动画模型都在,只是摄像机内看到内容多少变化。前提所有场景元素的消耗认为都是等级的!)

30帧:

SetPass Calls: 47 Draw Calls: 74 Total Batches: 68 Tris: 8.2k Verts: 10.2k

(Dynamic Batching) Batched Draw Calls: 6 Batches: 1 Tris: 0 Verts: 0

(Static Batching) Batched Draw Calls: 2 Batches: 1 Tris: 2.0k Verts: 5.1k

Used Textures: 0 - 0 B

RenderTextures: 21 - 11.9 MB

RenderTexture Switches: 22

Screen: 64x64 - 48.0 KB

VRAM usage: 11.9 MB to 11.9 MB (of 0 B)

VBO Total: 0 - 0 B

VB Uploads: 27 - 48.0 KB

IB Uploads: 27 - 1.0 KB

Shadow Casters: 0

 

22帧:

SetPass Calls: 53 Draw Calls: 80 Total Batches: 76 Tris: 14.3k Verts: 19.5k

(Dynamic Batching) Batched Draw Calls: 5 Batches: 1 Tris: 0 Verts: 0

(Static Batching) Batched Draw Calls: 0 Batches: 0 Tris: 0 Verts: 0

Used Textures: 0 - 0 B

RenderTextures: 21 - 11.9 MB

RenderTexture Switches: 22

Screen: 64x64 - 48.0 KB

VRAM usage: 11.9 MB to 11.9 MB (of 0 B)

VBO Total: 0 - 0 B

VB Uploads: 26 - 33.0 KB

IB Uploads: 26 - 1.0 KB

Shadow Casters: 0

 

14帧:

SetPass Calls: 111 Draw Calls: 233 Total Batches: 155 Tris: 92.2k Verts: 105.5k

(Dynamic Batching) Batched Draw Calls: 182 Batches: 13 Tris: 4.1k Verts: 13.3k

(Static Batching) Batched Draw Calls: 115 Batches: 31 Tris: 29.7k Verts: 42.0k

Used Textures: 0 - 0 B

RenderTextures: 22 - 13.9 MB

RenderTexture Switches: 24

Screen: 64x64 - 48.0 KB

VRAM usage: 13.9 MB to 13.9 MB (of 0 B)

VBO Total: 0 - 0 B

VB Uploads: 53 - 1.1 MB

IB Uploads: 36 - 29.0 KB

Shadow Casters: 2

 

10帧:

SetPass Calls: 152 Draw Calls: 661 Total Batches: 210 Tris: 267.3k Verts: 380.9k

(Dynamic Batching) Batched Draw Calls: 564 Batches: 21 Tris: 18.4k Verts: 51.2k

(Static Batching) Batched Draw Calls: 694 Batches: 63 Tris: 155.6k Verts: 250.9k

Used Textures: 0 - 0 B

RenderTextures: 22 - 13.9 MB

RenderTexture Switches: 24

Screen: 64x64 - 48.0 KB

VRAM usage: 13.9 MB to 13.9 MB (of 0 B)

VBO Total: 0 - 0 B

VB Uploads: 64 - 2.6 MB

IB Uploads: 40 - 109.0 KB

Shadow Casters: 2

 

9帧:

SetPass Calls: 208 Draw Calls: 894 Total Batches: 265 Tris: 360.4k Verts: 544.8k

(Dynamic Batching) Batched Draw Calls: 1511 Batches: 42 Tris: 48.1k Verts: 142.3k

(Static Batching) Batched Draw Calls: 861 Batches: 85 Tris: 231.4k Verts: 313.3k

Used Textures: 0 - 0 B

RenderTextures: 22 - 13.9 MB

RenderTexture Switches: 24

Screen: 64x64 - 48.0 KB

VRAM usage: 13.9 MB to 13.9 MB (of 0 B)

VBO Total: 0 - 0 B

VB Uploads: 52 - 3.5 MB

IB Uploads: 42 - 280.0 KB

Shadow Casters: 2

 

 

 

 

 

19、 重新思考16位颜色

UI 图片有些是渐变色, 如果使用不是RGBA32 , 就会出现类似下图中 444 的不和谐的过度。

Unity支持两种类型的16位颜色。

ARGB4444,分别对红色,绿色,蓝色和alpha应用4位(16步),红色为5位(32步),绿色为6位(64步),对于没有alpha的蓝色为5位的RGB 565。它在下面缩写并称为“4444”和“565”。

这取决于alpha通道需要多少位,所以这次我们只考虑RGB图像质量而不考虑alpha通道。

如果8位RGB有256级,可用颜色的数量将为1677万。如果这变为565存储方式,它将降至65,000种颜色(梯度还不是特别明显)。 右端是4444存储方式,只有4096种颜色,显然梯度更明显。

人类视觉存在不均匀性。

例如,就红色,绿色和蓝色而言,人类视觉对绿色敏感并且对蓝色不敏感。在上一篇文章中提到的RGB565压缩格式中,虽然有32级红色和蓝色,但是为绿色准备了64级。它考虑到人的视觉特征。

Unity3d 周分享(22期 2019.8.30 )_第19张图片

 

Unity3d 周分享(22期 2019.8.30 )_第20张图片

这里面还涉及到 “类视觉特征的问题” 人类视觉总是有一个强调对比度的过滤器。“浅色旁边的颜色稍暗的颜色显得更暗”,“浅色旁边的浅色颜色看起来更亮”等。 https://baike.baidu.com/item/%E9%A9%AC%E8%B5%AB%E5%B8%A6

解决这个问题可以使用: 抖动: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering

为了在减少颜色数量时难以注意到图像质量的劣化,抑制该侧面抑制是有效的。如果大区域彼此相邻,则可以容易地看到侧面抑制的效果,但是如果颜色像噪声一样散开,则强调的线条将变得分开并变得不太可见。

作者提供了导入后处理脚本!!!!! 但是感觉变得模糊了~~~

具有亮度+色差的纹理压缩(YUV或YCbCr)

索引颜色纹理的记忆 - 怀旧的调色板 - (有点涉及到 LUT ?)

 

宣雨凇的文章分享 和这个内容类似:

《Unity3D研究院编辑器之批处理图片添加抖动(三十三)》

 

 

20、 UGUI 的富文本标签 会增加 顶点这个问题在之前的分享中提到过, 但是会不会有性能影响?没有测试过!!!!

今天看到文章有人测试了。

UnityEngine.UI的性能调查从“富文本不增加顶点纹理?”开始。

Unity的版本是2017.4.8f1。

首先通过创建很多Text 文本 , 然后开启和不开启说明 Outline组件的影响(超多的定点数对性能的影响)。这个不用介绍了

作者使用 官方的 “Outline” 组件来比较负载。 其中多了一个组件 DegenerateQuadRemover ,就是在进行Outline处理之前把富文本的顶点数据移除掉。

Unity3d 周分享(22期 2019.8.30 )_第21张图片

只有Text 2-4

Unity3d 周分享(22期 2019.8.30 )_第22张图片

Text 富文本 44-88

Unity3d 周分享(22期 2019.8.30 )_第23张图片

Text 富文本 + 过滤 2-6 我测试这个过滤跟Outline没关系呀~~~~~~

Unity3d 周分享(22期 2019.8.30 )_第24张图片

Text 富文本+Outline 220-660

Unity3d 周分享(22期 2019.8.30 )_第25张图片

Text 富文本+Outline + 顶点过滤 10 + 30

Unity3d 周分享(22期 2019.8.30 )_第26张图片

在启用Outline时它已成为1个字符变成 6个顶点。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class DegenerateQuadRemover : BaseMeshEffect
{
    private static List _verticesCache; // 反复使用

    static DegenerateQuadRemover()
    {
        _verticesCache = new List();
    }

    public override void ModifyMesh(VertexHelper vh)
    {
        vh.GetUIVertexStream(_verticesCache);
        // TOOD: 在这做点什么
        Process(_verticesCache);

        vh.Clear();
        vh.AddUIVertexTriangleStream(_verticesCache);
    }

    /// 
    /// 循环一次处理一个字符,如果有一个区域则复制到一个新数组,如果它是一个区域0,它将通过。
    /// 但是,要严格计算区域,你必须查看所有六个顶点并且它太慢,所以这里我们只看到每个字符有两个顶点。
    /// 富文本标签的顶点对于第一个和第二个顶点具有相同的坐标,因此此x和y之间的差异的平方为0。
    /// 位置是Vector3,但您不必查看z。它完全取决于当前版本中Text的顶点生成行为,因此如果Unity版本发生更改,它可能会卡住。
    /// 
    /// 
    public static void Process(List vertices)
    {
        int letterCount = vertices.Count / 6;
        Debug.Assert((letterCount * 6) == vertices.Count); // 如果不能被6整除的顶点数量 
        int srcVertexIndex = 0;
        int dstVertexIndex = 0;
        for (int letterIndex = 0; letterIndex < letterCount; letterIndex++)
        {
            vertices[dstVertexIndex + 0] = vertices[srcVertexIndex + 0];
            vertices[dstVertexIndex + 1] = vertices[srcVertexIndex + 1];
            vertices[dstVertexIndex + 2] = vertices[srcVertexIndex + 2];
            vertices[dstVertexIndex + 3] = vertices[srcVertexIndex + 3];
            vertices[dstVertexIndex + 4] = vertices[srcVertexIndex + 4];
            vertices[dstVertexIndex + 5] = vertices[srcVertexIndex + 5];
            var p0 = vertices[dstVertexIndex + 0].position;
            var p1 = vertices[dstVertexIndex + 1].position;
            var dx = p1.x - p0.x;
            var dy = p1.y - p0.y;
            if (((dx * dx) + (dy * dy)) > 0f)  // 不是富文本标签
            {
                dstVertexIndex += 6;
            }
            srcVertexIndex += 6;
        }
        vertices.RemoveRange(dstVertexIndex, vertices.Count - dstVertexIndex);
        Debug.Assert(vertices.Count == dstVertexIndex);
    }
}

左边没有顶点移除。有84000个顶点,图表完全是紫色的。右边是顶点移除,有15,000个顶点。该图显着改善。

然而,虽然它已经下降,但它超过30毫秒。它在使用富文本之前大概是20毫秒,因此富文本可能很重。事实意味着标签字符的字体纹理相关处理完全在运行,而且它会是浪费的。能够根据一个文本中的部分生成颜色和大小不同的字符串很方便,但如果格式是固定的,则最好分成多个文本。例如,

Level:25

在这种情况下,如果您将数字从“Level:”和“25” 分开, 直接设置Text组件的属性,就可以移除富文本的标记。

注:我在Unity 2019.3 版本中测试发现富文本标记已经没有这个问题了!!!!

 

 

 

 

 

21、 当您想要使对象变暗或去饱和时

,能够直接更改HSV(色调,饱和度,亮度)非常有用。您需要使用Color.RGBToHSV和Color.HSVToRGB来更改Unity脚本中的HSV。

https://techblog.kayac.com/unity_advent_calendar_2018_15

至于Shader中使用 , 直接使用标签就可以了, 之前文章中提到过的!!

 

或者 有人自己在Shader中实现转换函数: 暴露对应的参数:

Unity3d 周分享(22期 2019.8.30 )_第27张图片

 

 

 

 

 

 

22、[Unity]一个动态绘制框的介绍

https://techblog.kayac.com/unity_advent_calendar_2018_06

Unity3d 周分享(22期 2019.8.30 )_第28张图片

在屏幕右侧绘制一个大白框,但最初这个框架是使用Image绘制的,当在Unity的场景窗口中将显示切换到Overdraw时,它如下所示。

Unity3d 周分享(22期 2019.8.30 )_第29张图片

下面是改进之后的效果:

Unity3d 周分享(22期 2019.8.30 )_第30张图片

仔细观察, 图像中的白框影响的范围已经变得特别小, 不要问 为什么不把白框做在要框住的图片内? 因为动画:

Unity3d 周分享(22期 2019.8.30 )_第31张图片

注: 记得Unity 现在已经支持 Sprite 不仅仅是 正方形框的取顶点了, 可以设置Mesh 模式, 就不会有这个问题。

 

 

 

 

 

23、您是否厌倦了在Unity中浪费宝贵的时间在 build platform switches ?

Turbo Switch PRO简单,比内置开关快100倍!

https://twitter.com/crosstales/status/1155728956068388864

Unity3d 周分享(22期 2019.8.30 )_第32张图片

https://assetstore.unity.com/packages/tools/utilities/turbo-switch-pro-60040

 

 

 

 

24、 Unity AssetBundle高效加密案例分享

https://blog.uwa4d.com/archives/USparkle_AssetBundle.html

public static AssetBundle LoadFromFile(string path, uint crc, along offset);

Parameters

Unity3d 周分享(22期 2019.8.30 )_第33张图片

利用Offset 来达到加密的。

 

Unity3D研究院之加密Assetbundle不占内存(一百零五)

宣雨凇是通过 Unity2017.2提供了一个新的API AssetBundle.LoadFromStream

 

 

 

 

 

25、 日本一个游戏学院, TECH x GAME COLLEGE

定期分享游戏开发技术; 比如游戏服务器的分享有:

  • 如何制作 一个由gumi的CTO教授的正确的游戏网络服务器(如何制作正确的游戏网络服务器#1/2)
  • 为什么共享数据的完整性很重要?游戏中服务器端设计的基础知识(如何制作正确的游戏网络服务器#2/2)

“RDBMS + NoSQL” 关系型数据库管理系统 + 非关系型数据库

游戏数据存储设计技巧之一是“保护共享数据的完整性”。

 

利用Laravel 实现游戏服务器在100ms内调整通信时间的 装置

(用Laravel#1/2调整游戏服务器)

为什么Laravel×水平分散很难? 引入横向分布的机制和实施

(用Laravel#2/2调整游戏服务器)

域驱动设计,要做多远?可以采取哪些措施来克服开发现场的“问题”

(游戏开发中的领域驱动设计和无服务器架构#1/2)

无服务器,接下来会发生什么?DDD和无服务器专家称技术的未来

(游戏开发中的领域驱动设计和无服务器架构#2/2)

从ichi学习RDB重新介绍 游戏开发的基本知识

(用于高效游戏开发的RDB简介#1/2)

哪个更快,RDBMS还是NoSQL?在游戏开发中充分利用RDB

(用于高效游戏开发的RDB简介#2/2)

服务器通用基础架构为游戏开发带来了什么 从技术选择的原因到引入的角度

(如何创建一个通用的服务器基础来提高游戏质量#1/2)

你为什么选择Kotlin?不断发展的游戏制作,直到创建一个通用的服务器平台

(如何创建一个通用的服务器基础来提高游戏质量#2/2)

支持全球网络游戏的匹配技术 ,应该考虑创造舒适的游戏体验

(在世界上使用Google云端平台)

Mastodon和Netflix所见的容器的未来 - 容器能否成为服务开发的主流?

TECH x GAME COLLEGE 2018.10.15

樱花互联网研究中心主任Ken Sugakita到目前为止谈论集装箱

TECH x GAME COLLEGE 2018.10.12

 

无中断学习从无到有的历史FaaS的诞生带来了什么

TECH x GAME COLLEGE 2018.9.27

回顾无服务器,容器或历史,在虚拟化旁边

TECH x GAME COLLEGE 2018.9.26

 

域驱动设计的概念很好理解

TECH x GAME COLLEGE 2018.9.10

领域驱动设计的基础知识,学习三个关键词

TECH x GAME COLLEGE 2018.9.7

 

 

 

 

26、 使用Unity 2019.1进行移动游戏和XR开发

https://www.qualcomm.com/news/onq/2019/07/18/mobile-game-and-xr-development-unity-20191

  • 面向数据的技术堆栈
  • 对脚本化渲染管道的更新
  • 建议API支持

Unity 2019.1现在具有对Vulkan的本机渲染插件支持。Vulkan是新一代3D图形和计算API,可为PC和移动平台上的现代GPU提供高效,跨平台的访问。Vulkan与旧版移动渲染API(如OpenGL ES 3.x)的主要优势在于速度。Vulkan旨在利用多个CPU核心,允许应用程序并行构建多个线程中的命令列表。这允许应用程序利用设备上的CPU内核来帮助提高性能。

在Unity 2019.1中为Vulkan添加本机渲染插件是一个好消息,因为Vulkan在Qualcomm Adreno 5xx和6xx系列GPU上受支持。Snapdragon开发人员可以使用Adreno GPU SDK进行支持Vulkan的渲染操作。开发人员可以使用Unity的默认Auto Graphics API,它从版本2019.1开始启用Vulkan。这意味着如果构建目标/底层硬件支持Vulkan,那么将选择Vulkan作为渲染API; OpenGL将用于所有其他情况。在Unity 2019.1之前,OpenGL是默认的渲染API,必须手动启用Vulkan支持。

有关Adreno上的Vulkan的更多概述,请查看使用Vulkan on Mobile开发3D图形。

 

在移动设备上使用Vulkan开发3D图形

https://developer.qualcomm.com/blog/developing-3d-graphics-vulkan-mobile

由于Qualcomm®Snapdragon™移动平台(Snapdragon 820及以上版本)上的Adreno™5xx和6xx系列GPU支持Vulkan

文章中提到很多优点。 我觉得最大的缺点就是设备支持范围小, 很多老机型,低端机肯定都不支持, 不过肯定是将来的趋势~~

结论

Vulkan提供的好处对于希望为移动平台开发或移植游戏和/或VR解决方案的图形程序员来说是令人兴奋的。当与我们的平台搭配Adreno 5xx和6xx GPU配合使用时,Vulkan为移动设备上的高性能图形提供了强大的API。有关更多信息,我们建议您查看以下三个链接:

  • 我们的Adreno SDK for Vulkan可在此处获取。
  • 我们在YouTube上有一个广泛的多部分系列,用于在Adreno上使用Vulkan进行开发。你可以在这里找到第1部分。
  • 还有对福尔康一个很好的入门教程在这里。

 

 

 

 

 

 

27、 看到一个截图, 发现Unity没有这个选项啊:

Unity3d 周分享(22期 2019.8.30 )_第34张图片

https://indienova.com/tag/unite-shanghai-2019/

Unite 2019 Shanghai:一步解决 Unity 游戏新安全风险

现在支持 Windows/Android 平台游戏的加密,包括 Mono/IL2CPP 模式。

 

 

 

28、关于Unity游戏的7个 GUI 优化提示

Unity 有许多优化问题以及 GUI 实现的最佳实践, 下面是其中的一些问题!

https://medium.com/@ahhaoah/unity-ui-optimization-procedures-4d0f6ca2d827

很多是老生常谈的内容:

1、 canvas 的更新代价, 尝试划分Canvas。 动静分离

2、Raycast Target属性 问题, (注,这个在2019.2版本中默认是不勾选的了)

3、Camera.main 根据World Space Canvas,Unity将每帧7-10次访问Camera.main,每个Graphic Raycaster。每次访问时,Camera.main也会调用Object.FindObjectWithTag!

4、Pooling UI Objects 池化是避免不断创建和删除对象的有用方法。 但是。 池化UI对象涉及重新生成和禁用,但这会导致层次结构被弄脏两次,并且也会污染新的层次结构。 所以: 首先禁用该对象,然后将其重新指定父级 放到池中。 从池中获取对象时,请先重新使用它,更新数据,重新指定父级等。 然后在启用它

5、Hiding a Canvas 就是, 避免Disable 对象。 或者更好的处理是 更改Canvas对象的Layer最好了, 也不会弄脏Canvas中的数据。 可以达到隐藏整体的效果。

6、 Texture Atlases ,共享相同材质的每个对象(效果粒子,纹理)都在同一个DrawCall中,并将立即发送到GPU。

7、Stacking UI 堆叠

任何启用的GUI元素都会导致draw call,无论其位置如何。 屏幕外并启用的UI对象会增加绘制调用的数量。将UI图像/文本堆叠在一起会导致更多的透支overdraw,并会减慢速度。

禁用屏幕外的游戏对象和UI元素,或将屏幕外UI游戏对象的父级更改为非UI游戏对象。 (屏幕外的对象并不会被裁剪调,依然在合拼在DrawCall , 顶点和三角面没有减少)

其他Unity UI性能提示

1、限制Text组件中“Best Fit”和“Rich Text”的使用。 (Rich Text 占用顶点和三角面的问题在2019版本中已经修复了)

2、不要使用dynamic,如果可能请使用 bitmap/static 字体。 这个是为什么? 英文可能没有内存的压力吧, 但是中文肯定不行~

3、限制Text游戏对象上Outline / Shadow组件的使用。相反,在位图字体bitmap font中烘焙效果。(应该也是针对英文)

4、如果可能的话,坚持使用'simple'的精灵。避免使用大型“tiled”精灵。

5、展平transform hierarchy。嵌套越多,正确定位子项所需的变换计算就越多。

6、取消选中“Canvas”上设置中的“Pixel Perfect”。Big performance hitter.

7、Screen Space Overlay UI 比Screen Space Camera略快。在Overlay中,UI立即绘制在屏幕顶部,避免了Camera空间必须经过的所有剔除和排序。

8、首选 enabling/disabling画布本身而不是整个游戏对象。避免整个层次结构上的OnEnable / OnDisable回调,这可能很昂贵。

9、在从池中借用对象之前启用它时,首先更新池对象属性。这样可以避免对对象层次结构造成不必要的污染

10、使用包含许多Item的ScrollRects,将Canvas(没有勾选Pixel Perfect)附加到ScrollRects,以便滚动item不会弄脏外部Canvas中的元素

References

  • College, U. (2017, Septemeber 16). Unity3D Object Pooling — How to use them & why you should. Retrieved from YouTube: https://www.youtube.com/watch?v=7UswSdevSpw
  • Unity. (2019, January). Some of the best optimization tips for Unity UI. Retrieved from Unity: https://unity3d.com/how-to/unity-ui-optimization-tips
  • Unity. (n.d.). Unity UI Performance tips — Sharing my findings. Retrieved from Unity: https://forum.unity.com/threads/unity-ui-performance-tips-sharing-my-findings.524916/

 

 

 

 

29、

Unity UI Best Practices : https://medium.com/@dariarodionovano/unity-ui-best-practices-40964a7a9aba

1.明智地命名UI元素

就像场景中的对象或层次结构中的文件一样,UI元素应该通过元素类型的指示符合理命名。

2、一份普通分辨率清单是你最好的朋友

Unity3d 周分享(22期 2019.8.30 )_第35张图片

3、保持Rect Transform中的值清洁, 尝试将数字四舍五入以避免小数。

Unity3d 周分享(22期 2019.8.30 )_第36张图片

4、将Scale保持在1

默认情况下,UI元素的Scale应始终为1,除非动画稍微更改或应用特定用例。

5、不需要时不要使用纹理

对于可以使用白色矩形构建的UI元素,不要使用任何纹理,而是使用带有空源的Image组件。 (注意,空的Image会破坏合批)

Unity3d 周分享(22期 2019.8.30 )_第37张图片

 

 

 

30、 自动测试Unity应用程序,不加选择地点击

https://techblog.kayac.com/?page=1564527600

具体运行效果查看:

https://hiryma.github.io/AutoTapTest/index.html

讨论游戏开发中耐力测试的支持工具。从技术上讲,它只是“我会让EventSystem有点脱离代码并自己点击它”,但我认为将它视为质量保证的广泛问题的一部分比仅仅认为它是一个技术问题更有成效。

Unity3d 周分享(22期 2019.8.30 )_第38张图片

怎么用? https://github.com/hiryma/UnitySamples/tree/master/AutoTapTest/Assets/Kayac/Debug

将 DefaultDebugTapper 组件 附加到某个GameObject 上。

  • 排除的对象设置
  • 我想定制在哪里Tap

例如,

我想在技能选择模式中优先击中技能卡

我很少想在战斗中按下退出按钮

按下缓存清除按钮很困难

由于拖动是主输入系统,如果游戏是随机的,则游戏不会进展

 

 

 

31、

方便在游戏内查看 问题的 可视化显示扩展:

  • 三年前的 【Unity】uGUI でゲーム内に Hierarchy と Inspector を表示できる「RuntimeEditor」紹介 http://baba-s.hatenablog.com/entry/2017/12/25/090100
  • 【Unity】横向きかつクリックやタップ可能なゲームで使用できるカスタマイズ可能なデバッグメニュー「UniDebugMenu」を GitHub に公開しました

http://baba-s.hatenablog.com/entry/2019/03/19/090000 运行时执行修改参数或者命令

  • [Unity]我们在GitHub上发布了“UniDebugPanel”,可以在游戏中显示可自定义的按钮进行调试。

http://baba-s.hatenablog.com/entry/2018/08/07/090000 如果通过宏定义控制包中是否开启这个功能。

  • [Unity]“UnityRuntimeInspector”简介,其中Hierarchy和Inspector可以在游戏中使用uGUI显示

http://baba-s.hatenablog.com/entry/2017/12/26/091500

https://github.com/yasirkula/UnityRuntimeInspector

  • [Unity]我们发布了探测器UI“UniSimpleProfiler”,它可以检查GitHub上FPS,GC发生和内存使用的发生次数。

比较简单的统计数据显示

  • [Unity]推出“Mini Profiler Pro”,它可以在游戏画面上显示FPS和内存使用情况(图5.40美元,免费版)

http://baba-s.hatenablog.com/entry/2018/01/11/230400 有两个曲线统计

  • 帧率和 内存

https://github.com/microsoft/VisualProfiler-Unity

  • 我制作了Raycaster并使调试UI独立于UGUI https://techblog.kayac.com/debugging-ui-using-raycaster-self-maded

[Unity]调试UI,可以使用一个DrawCall而不会污染场景 https://techblog.kayac.com/unity_advent_calendar_2018_01

 

 

 

32、 Shader Tips:

1) Using Unity ShaderLab's built-in Time for animating shaders, but want it to not be affected by timeScale? Use global Shader vars! Also super handy for passing in custom fog values or changing color schemes. Can pretty much pass in anything!

使用Unity ShaderLab的内置时间来设置着色器的动画,但是希望它不受timeScale的影响? 使用全局着色器变量! 传递自定义雾值或更改颜色方案也非常方便。 几乎可以传递任何东西!

https://docs.unity3d.com/ScriptReference/Shader.html 设置各种类型的 Global 参数。

 

2)Want to map objects to a 3D coord grid, but don't want/can't use multidimensional/jagged arrays due to memory? Try Dictionary, but use this IEquatable struct instead of Vector3 keys for fast int hashcode & no boxing

想要将对象映射到3D coord grid,但是由于内存不希望/不能使用多维/锯齿状数组? 尝试使用Dictionary,但是使用这个IEquatable结构而不是Vector3键来快速进行int hashcode并且没有装箱

https://pastebin.com/HfgUfNDa public struct Vector3Int : IEquatable {

枚举作为key 会产生GC 我知道, 但是struct 也会产生就忘了, 今天看到这个提示才想起来。

《IL2CPP优化:避免装箱》https://blogs.unity3d.com/cn/2016/08/11/il2cpp-optimizations-avoid-boxing/ 这个文章评论中,提示IL2cpp也没有解决。

《优化使用struct和enum作为Unity C#中的键的字典》https://ejonghyuck.github.io/blog/2016-12-12/dictionary-struct-enum-key/ 当你声明一个结构Equals(),GetHashCode()它并没有实现方法。

调用包含词典的方法时,对象object.Equals将通过比较语法运行。最简单的方法是声明并继承System.Collections.Generic命名空间IEqualityComparer中存在的接口。创建新的Dictionary实例时,将实例放在构造函数中。

// Struct.
public struct SomeStruct
{
    public int a, b;
}
class SomeComparer : IEqualityComparer
{
    bool IEqualityComparer.Equals (SomeStruct x, SomeStruct y)
    {
        return x.a == y.a && x.b == y.b;
    }
    bool IEqualityComparer.GetHashCode (SomeStruct obj)
    {
        return obj.a ^ obj.b;
    }
}
// Usage.
Dictionary dic = new Dictionary(new SomeComparer());
// Enum.
public enum SomeEnum
{
    StateA = 1,
    StateB = 2
}
class SomeComparer : IEqualityComparer
{
    bool IEqualityComparer.Equals (SomeEnum x, SomeEnum y)
    {
        return (int)x == (int)y;
    }

    bool IEqualityComparer.GetHashCode (SomeEnum obj)
    {
        return ((int)obj).GetHashCode();
    }
}
// Usage.
Dictionary dic = new Dictionary(new SomeComparer());

注意: 这个问题在.Net 4.x版本中已经不存在了

3)Want to create a distortion material that warps the view, but don't feel like painting normal maps? Try this shader instead, which distorts using mesh normals and blends edges using an inverse rim/fresnel calculation. Sphere mesh as example

想要创建一个扭曲视图的扭曲材质,但是不想绘制法线贴图? 请尝试使用此着色器,使用网格法线扭曲并使用反向边缘/菲涅尔inverse rim/fresnel计算混合边缘。 以球体网格Sphere mesh为例

Mesh Distortion着色器: https://pastebin.com/DiHD2SdC

Unity3d 周分享(22期 2019.8.30 )_第39张图片

 

 

4) Want to create a hologram effect with scanlines? Try combining fresnel/rim with alpha, plus a 2D screenspace panning scanline texture. Works best with smooth normals 想用扫描线创建全息图效果? 尝试将菲涅耳/边缘与alpha相结合,再加上2D屏幕空间平移扫描线纹理。 最平滑的法线效果最佳 https://twitter.com/phi6/status/1001220419351916545

 

5)As part of #RecompileGame's unique aesthetic, we have created a glitchy "fog-of-war" effect to gradually reveal the terrain as the player explores it. Here's a write-up on how we implemented this using a combination of shaders & VFX

作为#RecompileGame独特美学的一部分,我们创造了一个小故障的“战争迷雾”效果,以便在玩家探索时逐渐展现出地形。 我们结合使用自定义着色器,VFX和Unity的Culling Group API来实现所需的效果。

https://phigames.co.uk/rcfog.html

 

6) 回到亲子关系! 回到事物的摇摆。 这是一篇新的文章,分析了我们如何在#RecompileGame中实现了毛刺撞击着陆冲击波效果。 使用着色器,VFX,动画曲线和音频提示创建

Back from paternity! Getting back into the swing of things. Here's a new write-up breaking down how we achieved the glitchy crash landing shockwave effects in #RecompileGame. Created using shaders, VFX, animation curves & audio cues

https://phigames.co.uk/rcshockwave.html

 

7) 新的一年,一个新的Shader写作!

我用#RecompileGame全手动相机解决遮挡问题的一些技巧: -

- 蓝色噪声抖动可平滑淡出剪裁的几何体

- Render使用ZTest遮挡玩家

A new year, a new Shader writeup!

Some tricks I used to solve occlusion problems with #RecompileGame's fully manual camera :-

-Blue noise dithering to smoothly fade out clipped geometry

-Render occluded player using ZTest

https://phigames.co.uk/rcoccluded.html

Updated the article to provide further clarification on the occluded shader's rendering order. Specifically, to use a queue which is one less than what the character is normally rendered at, so that we don't run into self-occlusion issues.更新了文章,以进一步说明遮挡着色器的渲染顺序。 具体来说,要使用比正常渲染字符少一个的队列,这样我们就不会遇到自遮挡问题。

 

8)Reading some interesting things on VFX today, so I decided to capture some freeze frames from #RecompileGame. I'm using custom shaders to control our bloom ramp, alpha cutouts & distortion to give @Skepsisology maximum control to make our VFX pop (THREAD)

今天在VFX上阅读一些有趣的东西,所以我决定从#RecompileGame中捕获一些冻结帧。 我正在使用自定义着色器来控制我们的绽放渐变,alpha切除和失真

最大限度地控制我们的VFX弹出(THREAD)

All our VFX systems use a custom shader, where the output emission (and thus bloom) is derived from particle color value. We define in the material a minimum and maximum emission, with exponential decay - this way we don't have to stick to bloom threshold on the post process

我们所有的VFX系统都使用自定义着色器,其中输出发射(以及因此bloom)来自粒子颜色值。 我们在材料中定义最小和最大发射,指数衰减 - 这样我们就不必在后期处理上坚持绽放阈值

The custom shader also does NOT support any transparency. Instead we take the alpha value from the particle color and apply an alpha cutout from a noise cloud texture instead. Result: Stylized Zelda style fire and smoke

自定义着色器也不支持任何透明度。 相反,我们从粒子颜色中获取alpha值,并从噪声云纹理中应用alpha切除。 结果:风格化的塞尔达风格火与烟

Unity3d 周分享(22期 2019.8.30 )_第40张图片

Finally we also use a mesh distortion shader to add rippling distortion effects to our dashes, crashes, explosions and more. It's subtle but effective

最后,我们还使用网格失真着色器为我们的破折号,崩溃,爆炸等添加波纹失真效果。 这是微妙但有效的。 用我粗暴的编码着色器实际创建艺术作品:)

https://pastebin.com/DiHD2SdC

Yeah I hope you keep this bullet time/360 pause (can't remember if it was already in the demo), I love that feature in games and it's a great way to admire your beautiful particle effects! Beetle Adventure Racing comes to mind

是的,我希望你保持这个子弹时间/ 360暂停(不记得它是否已经在演示中),我喜欢游戏中的这个功能,这是欣赏你美丽的粒子效果的好方法!想到甲壳虫冒险赛车

We use a default threshold value so that everything else (eg terrain etc...) looks good, but we need more control for our particles as Unity's VFX system doesn't allow HDR (brightness > 1) in the Start Color/Color Over Lifetime pickers

我们使用默认阈值,以便其他所有内容(例如地形等......)看起来不错,但我们需要对粒子进行更多控制,因为Unity的VFX系统不允许在开始颜色/颜色中使用HDR(亮度> 1) 终身拣货员

 

9)、Our faux volumetric shader for #RecompileGame transforms simple meshes into fancy atmospheric lighting. Inverse fresnel on smooth normals helps soften the edges, and the variable falloff prevents clipping. Link to shader:

我们用于#RecompileGame的人造体积着色器将简单的网格转换为花哨的大气照明。 平滑法线上的反菲涅尔有助于软化边缘,可变衰减可防止削波。 链接到着色器:https://pastebin.com/AjjUrn7m

Alright! So, all 3d meshes have normals, that is, direction perpendicular to the surface. Imagine sticking a pencil into the centre of an orange. That pencil is the normal to the surface of the orange at that point. Thread cont...

好的! 因此,所有三维网格都有法线,即垂直于曲面的方向。 想象一下,将铅笔插入橙色的中心。 那支铅笔是那个时候橙色表面的法线。 线程控制...

Smooth normals means normals across the surface of the mesh are smoothed out. Imagine a lowpoly sphere. With non-smoothed normals, you'd be able to see the faceted surfaces, it would look like Kryten's head. With smoothing it would look like a real sphere, even though its lowpoly

平滑法线表示平滑网格表面的法线平滑。 想象一下低聚球。 使用非平滑法线,您将能够看到刻面的表面,它看起来像Kryten的头部。 通过平滑,它看起来像一个真正的球体,即使它是低聚物

So we have a mesh with smooth normals, for a volumetric light, we could use a cone. Now, fresnel. aka rim lighting. With regular fresnel, normals pointing away from camera are brighter than normals pointing towards you. So you get more light on the rim of the object. Like this

所以我们有一个光滑法线的网格,对于体积光,我们可以使用锥形。 现在,菲涅耳。 又名边缘照明。 使用常规菲涅耳,指向远离相机的法线比指向您的法线更明亮。 因此,您可以在物体的边缘获得更多光线。 像这样

 

10)、Oh how I love volumetric lighting! Here's a brief thread on how I made this cool scanning laser sweep thing for Recompile

哦,我喜欢体积照明! 以下是关于我如何为重新编译制作这种酷扫描激光扫描的简短线程

First I use this library as a base. You can use this to add volumetrics to any Unity spotlight. Making sure to enable shadows so the light doesn't clip through level geometry

首先,我使用这个库作为基础。 您可以使用此功能将体积添加到任何Unity聚光灯。 确保启用阴影,以便光线不会剪切水平几何体

https://github.com/SlightlyMad/VolumetricLights/

Then I add noise (to simulate fog/mist) and this simple light cookie to get the narrow sweeping beam with bright edges, instead of your usual conical spotlight shape

然后我添加噪音(模拟雾/雾)和这个简单的光饼干,以获得具有明亮边缘的窄扫描光束,而不是通常的锥形聚光灯形状

Then I layer several of these lights (2 or 3) and animate the spotlight angle to get the sweeping movement

然后我将这些灯中的几个(2或3)分层并设置聚光灯角度以获得扫描运动

Finally I make one of those lights flicker to give it a faux strobe effect! So easy, and so much fun!最后,我让其中一个灯闪烁,给它一个人造频闪效果! 这么简单,好玩!

 

你可能感兴趣的:(unity3d,周分享)