Unity3d 周分享(21期 2019.7.30 )

unity3d 周分享 专栏收录该内容
24 篇文章 15 订阅

选自过去1~2周 自己所看到外文内容:https://twitter.com/unity3d 和各种其他博客来源吧 

 

1、 官方文档中提到一个优化: 不知道性能到底如何~~

Mass object movement & CullingGroups

As mentioned in the section on Transform Manipulation, moving large Transform hierarchies has a relatively high CPU cost due to the propagation of change messages. However, in real development environments, it is often impossible to collapse a hierarchy to a modest number of GameObjects.

At the same time, it is good development practice to only run enough behavior to maintain the believability of the game world while eliminating behavior the user will not notice – for example, in a Scene with a large number of characters, it is always more optimal to only run Mesh-skinning and animation-driven Transform movement for characters that are on-screen. There is no reason to waste CPU time calculating purely visual elements of the simulation for characters that are off-screen.

Both of these problems can be neatly addressed with an API first introduced in Unity 5.1: CullingGroups.

Instead of directly manipulating a large group of GameObjects in the scene, change the system to manipulate the Vector3 parameters of a group of BoundingSpheres within a CullingGroup. Each BoundingSphere serves as the authoritative repository for a single game-logical entity’s world-space position, and receives callbacks when the entity moves near/within the frustum of the CullingGroup’s main camera. These callbacks can then be used to activate/deactivate code or components (such as Animators) governing behavior that should only run while the entity is visible.

大量对象移动和剔除群组

如同 Transform Manipulation 那节所述,移动有超大层级结构的 Transform 对象会造成很大的 CPU 消耗。但在现实的环境中,通常不可能将对象结构精简到最少的 GameObjects。

同时,如果可以最好在玩家不发现的前提下,删除玩家看不到的行为。例如,在有大量角色的场景时,只针对屏幕可见范围内的角色计算网格蒙皮(Mesh-skinning)和处理角色动作等等。不需要浪费CPU的资源在计算屏幕外看不到的角色行为。

这两个问题都可以透过 Unity 5.1 导入的 API 来完美解决:CullingGroups。

与其直接操作场景中一大群的 GameObject,而是改变系统操作 CullingGroup 里的一组 BoundingSpheres 的Vector3 参数。每个 BoundingSphere 作为这些 GameObject 在游戏世界中的代表,当 CullingGroup 接近或进入CullingGroup 设定的主镜头的锥体范围内时成员才会收到 callback。然后这些 callback 就可以用来执行启用/停用的程序代码或组件(例如Animators)让物体执行在可见范围内该有的行为。

https://docs.unity3d.com/2018.2/Documentation/Manual/BestPracticeUnderstandingPerformanceInUnity8.html

 

https://docs.unity3d.com/ScriptReference/CullingGroup.html

https://docs.unity3d.com/2018.2/Documentation/Manual/CullingGroupAPI.html

https://unitycoder.com/blog/2018/10/31/find-nearby-objects-using-cullinggroup/

有两种方式来触发CullingGroup的事件:

  • 相机裁剪
  • 相对距离(相机或主主角相对于目标物体的距离)

这两种方式可以混用,也可以只使用其中一个

应用场景有:

  • 粒子当前不可见时,将其暂停
  • 粒子与相机或主角在不同距离阶段时,使用不同的简化版粒子。
  • ai不在视野内时停止更新

剔除组是Unity API的一部分,它有效地允许我们创建自己的自定义LOD系统,作为一种方法来提出我们自己的动态替换某些游戏玩法或渲染行为的方法。我们可能希望应用LOD的一些示例包括 用具有较少骨骼的版本替换动画角色,应用更简单的着色器,远距离跳过粒子系统生成,简化AI行为等等。它在游戏玩法领域也有其他用途,

例如确定某些敌人出生点当前是否对玩家可见或者Player是否正在接近某些区域。有各种各样的可能性可与Culling Group系统一起使用,值得考虑。当然,花在实施,测试和重新设计场景上的时间可能很重要。

unity_2017_game_optimization_second_edition.pdf : 建议有时间阅读一下此书 http://www.dphgame.com/lib/exe/fetch.php?media=unity_2017_game_optimization_second_edition.pdf

Mesh-based LOD :基于网格的LOD也将耗费我们的磁盘空间以及RAM和CPU;

有些可能真的不要使用这个技术,比如 总是在室内或固定视角的俯视相机,包括实时战略(RTS)和多人在线战斗竞技场(MOBA)游戏。

 

 

 

2、 关于微软自己的 Excel比较工具: 好像Office 2013 就有这个工具了~

https://support.office.com/en-us/article/compare-two-versions-of-a-workbook-by-using-spreadsheet-compare-0e1627fd-ce14-4c33-9ab1-8ea82c6a5a7e

https://support.office.com/en-us/article/merge-copies-of-a-shared-workbook-aa7c3598-5ad7-4fea-8c00-2daa7a934239#OfficeVersion=Windows

https://answers.microsoft.com/en-us/msoffice/forum/all/comparing-excel-files/bb190de7-a029-4a6b-87b4-08db6a28f397

这个比较看着挺舒服的。

 

git工具中使用

https://www.syntevo.com/doc/display/SG/External+Tools%3A+configuring+Microsoft+Excel+spreadsheet+diffs

External Tools: configuring Microsoft Excel spreadsheet diffs

转至元数据结尾

转至元数据起始

If one has Microsoft Office installed, a tool called "SpreadSheet Compare" exists which is usually located at C:\Program Files (x86)\Microsoft Office\root\Office16\DCF\spreadsheetcompare. From command line, it takes a text file with two lines; each line is a file name.

To call this from SmartGit, in the Preferences, create a Diff Tool for e.g. *.xls pattern with Arguments ${leftFile} ${rightFile} and set Command to a script like the following:

@ECHO OFF rem smartgit diff passes two arguments: old-file, new-file. set TEMP_FILE=%TEMP%\smartgit-excel-diff.txt ECHO %1 > %TEMP_FILE% ECHO %2 >> %TEMP_FILE% "C:\Program Files\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\spreadsheetcompare" %TEMP_FILE%

For older/ 32-Bit MS Office versions, the executable's path may be:

"C:\Program Files (x86)\Microsoft Office\root\Office16\DCF\spreadsheetcompare"

 

 

Office 2019 快捷键中指认的是 : 第二个路径根本不存在,真不清楚是怎么执行的?

"C:\Program Files\Microsoft Office\root\Client\AppVLP.exe" "C:\Program Files (x86)\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE"

最后搜索到在这里:

C:\Program Files\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE

 

 

SVN :http://www.voidcn.com/article/p-nnccujmi-ro.html http://www.aichengxu.com/other/2533376.htm 有解释原理,但是注意这个是C盘路径,可能程序没有写的权限等 不会执行成功, 提供没有提供给SPREADSHEETCOMPARE路径,是因为 temp.txt 文件没有创建出来,更没有写入内容了。 设置路径权限就可以了。~~~

创建一个 ExcelCompare.bat 放到 SPREADSHEETCOMPARE.exe 同路径下。 然后SVN 设置中指认。 : C:\Program Files\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\ExcelCompare.bat %base %mine

 

@echo off

chcp 65001

set toolpath=%~dp0

echo %~1> "%toolpath%temp.txt"

echo %~2>> "%toolpath%temp.txt"

"%toolpath%SPREADSHEETCOMPARE.EXE" "%toolpath%temp.txt"

 

可以把 C:\Program Files\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF 整个路径拷贝到其它地方或者 分享给其他组员使用(测试没有问题)。

 

 

 

 

 

3、 [Unity]提前检查播放器构建期间发生的编译错误

https://qiita.com/k7a/items/ef5753e736d288fecc89

一个很烦的就是 哪个非Editor文件夹下的 脚本引用了using UnityEditor ;

优点:

能够检查编译错误而不必故意进行播放器构建是很有用的。

此外,可以在没有交换机平台的情况下执行不同的BuildTarget编译。

 

使用Scriptable Build Pipeline(SBP)可以轻松实现编译检查。

所以,首先我们介绍Scriptable Build Pipeline。

将以下内容添加到manifest.json中。(1.5.0-preview最新版本是2019/06/24)

manifest.json

"com.unity.scriptablebuildpipeline": "1.5.0-preview",

或者,如果您使用依赖于SBP的包(例如Addressables),则无需单独添加SBP。

执行编译检查:

它可以用以下来实现。当然,您需要将此脚本放在Editor文件夹下,或仅为Assembly Definition中的Editor指定它。

ScriptCompileTester.cs

using System.IO;
using UnityEditor;
using UnityEditor.Build.Player;
using UnityEngine;
public static class ScriptCompileTester
{
    /// <summary>
    /// 对当前BuildTarget执行编译检查
    /// </summary>
    [MenuItem("Tools/Compile Check/Current Active Target")]
    public static void CompileTestForCurrentBuildTarget()
    {
        CompileTest(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.selectedBuildTargetGroup);
    }
    /// <summary>
    ///执行iOS的编译检查
    /// </summary>
    [MenuItem("Tools/Compile Check/iOS")]
    public static void CompileTestForiOS()
    {
        CompileTest(BuildTarget.iOS, BuildTargetGroup.iOS);
    }
    /// <summary>
    /// 在Android上执行编译检查
    /// </summary>
    [MenuItem("Tools/Compile Check/Android")]
    public static void CompileTestForAndroid()
    {
        CompileTest(BuildTarget.Android, BuildTargetGroup.Android);
    }
    /// <summary>
    /// 进行编译检查
    /// </summary>
    public static void CompileTest(BuildTarget buildTarget, BuildTargetGroup buildTargetGroup)
    {
        var tempBuildPath = "Temp/CompileTest";
        var option = new ScriptCompilationSettings();
        option.target = buildTarget;
        option.group = buildTargetGroup;
        option.options = ScriptCompilationOptions.None;
        Debug.Log($"Compile Test Running - BuildTarget: {option.target}");
        // 注意:错误日志在CompilePlayerScripts中输出
        var result = PlayerBuildInterface.CompilePlayerScripts(option, tempBuildPath);
        if (result.assemblies != null && result.assemblies.Count != 0 && result.typeDB != null)
        {
            Debug.Log($"Compile Test Success! - BuildTarget: {option.target}");
        }
        // 注意:tempBuildPath具有转储后编译DLL
        if (Directory.Exists(tempBuildPath))
        {
            Directory.Delete(tempBuildPath, true);
        }
    }
}

如果执行上面的编辑器扩展,则错误和警告会以与播放器构建相同的方式出现在日志中,因此编译错误部分会被粉碎。

如果编译成功,则日志中将显示以下内容。

顺便说一句,因为它只是对编译的检查,所以即使它检查与ActiveBuildTarget不同的BuildTarget,也不需要花时间使用Switch Platform。

 

 

 

 

 

4、 为什么Android设备上的StreamingAssets资产包速度慢?

https://forum.unity.com/threads/why-the-asset-bundle-slow-in-streamingassets-on-android-device.401234/#post-3481362

之前自己没有做大量的测试,发现在 StreamingAssets和persistentData 路径下的加载时间不一定谁快。 可能是测试的量小。

有时间再试一试。 或者针对 StreamingAssets 的内容,从 AssetBundle.LoadFromFile 改为 WWW.LoadFromCacheOrDownload() 试试。

 

 

 

 

5、 Unite 2018中Ian Dundore的演讲《Unity性能优化的最佳实践》

https://connect.unity.com/p/unityxing-neng-you-hua-de-zui-jia-shi-jian

字符串比较:

运行完几次测试后,无论平台、脚本运行时版本、使用Mono还是IL2CPP,很明显String.Equals是最好的

请注意:String.Equals是字符串相等运算符==使用的方法,所以别把代码中所有“a == b”的部分改为“a.Equals(b) ”。

 

我们可以使用该Il2CppSetOptionAttribute属性修饰类型和方法,配置该属性,使它禁用自动Null检查和自动数组边界检查。这样可以加速代码的执行,有时可以大幅加快速度。在这个测试用例中,它会给手工编写的字符串比较方法带来20%的速度提升效果。

Transform

仅仅观察Unity编辑器的层级窗口无法了解Transform组件,但Transform组件在Unity 5和Unity 2018之间发生了很多变化,这也为性能提升过程提供了新的可能性。

涉及到Transform的内存缓存,是否连续。

在Unity 2017.4和Unity 2018.1中,新的TransformChangeDispatch替代了OnTransformChanged

 

 

在Unity 2017.2中,我们把物理功能转变为使用TransformChangeDispatch会造成一些性能问题。在执行光线投射的时候,我们必须查询TransformChangeDispatch,获取发生变化的Transform列表,然后把它们应用到物理世界。这会耗费较多性能,具体取决于Transform Hierarchies的大小,以及代码调用Physics API的方法。

Unity的大多数内部系统会在运行前,在每帧请求一次更新内容,例如:动画系统会在它评估场景中所有活动Animators前,请求更新内容。类似的,渲染系统会在开始剔除可见对象列表前,请求对场景中所有活动渲染器的更新。

只有一个系统与众不同,那就是Physics物理系统。

这种行为由新的设置Physics.autoSyncTransforms管理。从Unity 2017.2到Unity 2018.2,这项设置默认设为”True”,每次调用Raycast或Spherecast等物理查询API时,Unity会自动同步物理世界到Transform更新。

请注意:从Unity 2018.3开始,Physics.autoSyncTransforms将默认设为“False”。

音频系统

Audio Source组件上的Mute勾选框有一个常见问题:我们可能认为勾选“Mute”会取消所有和静音音频源相关的计算,但实际并非如此。

在每一帧上,Unity都会循环所有活动音频源。对于每个音频源,Unity会计算音频源和活动音频监听器之间的距离,以及一些其它参数。该数据用于计算音量衰减,多普勒频移等其它影响音频源的效果。

减少Virtual Voices数量会减小FMOD在检查实际播放的音频源时要检查的音频源数量。减小Real Voice数量会减小FMOD混合的音频源数量,混合的音频源用于产生游戏的音频。

请注意:这样会影响音频播放,所以建议在玩家不会注意到变化的时候进行操作,例如在加载画面或启动的时候。

动画

Unity中有二个不同系统可以用于播放动画:Animator系统和Animation系统。

Animator和 Animation这二个系统的区别不仅仅是功能,还有底层实现细节。

Animator系统会大量使用多线程功能,它的性能会在拥有不同内核的CPU上发生很大变化。通常情况下,随着动画剪辑中的曲线数量提高,它会以小于线性的增长速度变化。因此,在评估带有大量曲线的复杂动画时,它的执行效果很好,但Animator系统会有很高的性能开销成本。

虽然Animation系统几乎没有任何开销,它的性能会按照动画剪辑中播放的曲线数量而线性调整。

通用绑定和人形绑定

即使没有使用IK或动画重定向,人形绑定角色的Animator也会在每帧计算IK和重定向数据,这会比使用通用绑定多消耗30%~50%的CPU时间,因为通用绑定不会进行这些计算。如果没有使用人形绑定的特殊功能,你应该使用通用绑定。

Animator的对象池处理

使用对象池是在游戏期间避免发生性能峰值的关键策略,但Animator一直很难用于对象池。在Animator的游戏对象启用时,它必须重新构造中间数据的缓冲区,从而在评估Animator的Animator Controller时使用,这被称为Animator Rebind,它在Unity性能分析器中显示为Animator.Rebind。

在Unity 2018.1中,我们加入了Animator.KeepControllerStateOnEnable API,该属性默认设为“False”,表示Animator会以它原有的方式使用,即:在禁用Animator时,取消分配它的中间数据缓冲区,在启用Animator时,重新分配这些缓冲区。

如果把该属性设为”True”,Animator将在被禁用时保留它们的缓冲区,这意味着在Animator重新启用时,不会发生Animator.Rebind,从而使Animator可以使用对象池。

 

 

 

6、 Unity 扩展 非运行时播放声音。

当我想用Unity的编辑器扩展创建一个声音容器等时,我想要播放引用的AudioClip的内容(我不想将Inspector移动到相应的AudioClip上(不想跳转))

或者对Timeline的扩展,不使用它默认的track 方式播放。 自定义轨道, 运行时就是使用AudioSource 播放(但是希望编辑器下也可以正常播放)。

Unity 的 AudioClip的 Inspector面板是支持播放声音的。

但是没有暴露API, 这里就是使用反射 来调用。

http://baba-s.hatenablog.com/entry/2017/12/04/173920

https://github.com/jamesjlinden/unity-decompiled/blob/master/UnityEditor/UnityEditor/AudioUtil.cs

using UnityEngine;
#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
#endif
namespace Sample
{
    [System.Serializable]
    public class SampleContainer : ScriptableObject
    {
        // 要存储的数据
        [SerializeField] AudioClip soundData;

#if UNITY_EDITOR
        // SampleContainer Inspector扩展
        [CustomEditor(typeof(SampleContainer))]
        class SampleContainerEditor : UnityEditor.Editor
        {
            public override void OnInspectorGUI()
            {
                var data = target as SampleContainer;
                data.soundData = (AudioClip)EditorGUILayout.ObjectField("AudioClip", data.soundData, typeof(AudioClip));
                if (GUILayout.Button("PlayClip"))
                    this.PlayClip(data.soundData);
                if (GUILayout.Button("StopClip"))
                    this.StopClip(data.soundData);
            }

            // 编辑器上的声音播放。
            void PlayClip( 
                AudioClip clip)
            {
                if (clip == null) return;
                var unityEditorAssembly = typeof(AudioImporter).Assembly;
                var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
                var method = audioUtilClass.GetMethod
                (
                    "PlayClip",
                    BindingFlags.Static | BindingFlags.Public,
                    null,
                    new Type[] {typeof(AudioClip)},
                    null
                );
                method.Invoke(null, new object[] {clip});
            }
            // 停止编辑器上的声音。
            void StopClip(
                AudioClip clip)
            {
                if (clip == null) return;
                var unityEditorAssembly = typeof(AudioImporter).Assembly;
                var audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");
                var method = audioUtilClass.GetMethod(
                    "StopClip",
                    BindingFlags.Static | BindingFlags.Public,
                    null,
                    new Type[] {typeof(AudioClip)},
                    null
                );
                method.Invoke(null, new object[] {clip});
            }
        }
#endif
    }
}

 

 

7、 Burst vs. IL2CPP:泛型

(Burst vs. IL2CPP: Generics) https://jacksondunstan.com/articles/5282

泛型,无论是变量,方法还是函数,都是触发IL2CPP意外的语言特性 IL2CPP surprises。Burst会做得更好吗?我们来看看吧!

 

结论

今天我们已经看到Burst处理各种C#泛型同样或者比IL2CPP更好。在每种情况下,它都生成了最小的装配而没有开销。另一方面,IL2CPP经常(但不总是)if在使用泛型的函数中插入另一个分支。因此,虽然两个编译器有时会导致CPU执行相同的汇编代码,但在大多数情况下,Burst会生成更小,更快的代码

 

 

 

Burst中数组的危险

Dangers of Arrays in Burst : https://jacksondunstan.com/articles/5274

结论

托管Arrays可以在Burst中使用,但有许多警告。这些警告执行不一致。有时在构建或查看Burst Inspector时会出现编译器错误,但有时却没有。有时,编辑器和构建中的行为是不同的,Unity没有指示作业代码中存在问题。因此,了解Burst中托管数组的规则以及在使用它们时遵循良好的规则非常重要!

 

 

 

 

8、 用另一个阴影替换3D模型的阴影

我希望场景内的角色的阴影不使用自己的而使用另外一个模型的样子。

https://raspberly.hateblo.jp/entry/2018/12/02/000000

 

摘要

·阴影由Renderer默认完成。

·您可以通过更改渲染器的设置来打开/关闭阴影。

- 您可以通过关闭主角的阴影并准备另外阴影模型来轻松替换阴影(一个是显示关闭阴影, 一个是不显示只显示阴影)。

 

 

 

9、 有人改善 官方文档还是挺好的:

https://twitter.com/siobhangx/status/1143857554646274048

比如开发版本的 宏定义不是 DEBUG, 而是 DEVELOPMENT_BUILD

 

 

 

 

10、

关于 AssetBundle的压缩设置测试:

https://docs.unity3d.com/540/Documentation/Manual/AssetBundleCompression.html

http://tsubakit1.hateblo.jp/entry/2016/03/19/022019

https://veniegames.com/?p=262

https://qiita.com/vui/items/e25dacb22c085606e15f

所以现在采用 LZ4 的方式较多。 ChunkBasedCompression

 

 

 

 

11、 游戏开发中常用到的策略算法:

https://baike.baidu.com/item/LRU

LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最久未使用的页面予以淘汰。

游戏中资源卸载, 缓存策略 可以使用。 对于存储有一个量的上限的都可以采用

 

 

Bugly 的替代方案: http://www.testplus.cn/clientprofiler

http://www.testplus.cn/crasheye

 

 

https://answer.uwa4d.com/question/5985785a46dafb521451bd85

一般来说,开启“Optimize Mesh Data”选项,引擎会在发布时遍历所有的网格数据,将其多余数据进行去除,从而降低其数据量大小。需要注意的是,这里的“多余”数据是指Mesh数据中包含了渲染时Shader中所不需要的数据,即如果Mesh数据中含有position、uv、normal、color、tangent等顶点数据,但其渲染所用的Shader中仅需要position、uv和normal,则Mesh数据中的color和tangent则为“多余”数据,引擎在发布游戏时,将会将这些数据自动去除。

需要注意的是,开启这个选项是一把双刃剑。对于在Runtime情况下有更换Shader需求的Mesh,建议研发团队对其进行额外的注意。如果Runtime时需要为某一个GameObject更换更为复杂、需要访问更多顶点属性的Shader的话,则建议先将这些Shader挂载在相应的Prefab上再进行发布,以免引擎去除Runtime中会进行使用的网格数据。

但是,根据你的描述,该问题ms仅在移动平台上出现,而在PC平台上不出现,这个确实有点奇怪,可否上传一个这样的Mesh文件,这样我们可以帮忙进行进一步的研究。

 

 

 

 

 

12、 在Unity游戏画面中制作Profiler功能

https://github.com/hineko/InGameProfiler

https://qiita.com/hinagawa/items/4388f2f61cb33b9975e8

图像说明

第一个图显示了CPU,BehaviorUpdate,LateUpdate等脚本的测量结果,以毫秒为单位。

第二个图显示了除上述脚本测量之外的CPU的测量结果。此波形几乎与Profiler CPU项的波形匹配。

第三个图显示Profiler.GetMonoHeapSizeLong()从图中接收的内存量。

线的绘制方式: https://docs.unity3d.com/ScriptReference/GL.html 需要事先准备着色器。

缺陷:

因为我使用OnGUI会产生GC和更多的DrawCall

参考

集成方式可以看看我的文章: 【Unity】一点想法,使用IPreprocessBuildWithReport, IPostprocessBuildWithReport优化打包流程

 

 

 

13、 看Slua的仓库,发现一个调试的提示:

https://github.com/pangweiwei/slua

https://github.com/Tencent/luapanda

LuaPanda:

LuaPanda 是一个基于 VS Code 的 lua 代码调试器。设计目标是简单易用,支持多种开发框架。它由两部分组成:

  • VS Code Extension 调试器 VSCode 插件
  • Lua Debugger 调试器的 debugger 部分

https://github.com/Tencent/LuaPanda/blob/master/Docs/Manual/quick-use.md

 

腾讯其他的Lua 开源项目:

https://github.com/Tencent/sluaunreal

https://github.com/Tencent/xLua

 

腾讯公司员工还开源过一个ide ,代码编辑器调试集成。 LuaPerfect ,LuaPerfect是TX开发的专业级的Lua调试器,致力于为广大Lua开发人员提供免费的专业的Lua调试工具。

LuaPerfect官方群: 932801740

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

前的简易网站内容已移至 https://luaperfect.net/

 

 

 

 

14、 修复错误的简单步骤

1.阅读错误

这是真正的魔术magic。读错误。这是令人难以置信的有用技巧,谁知道为什么初学者总会错过它。

2.第二次阅读错误

有些初学者真的读错了,但只读一次就够了吗?我不这么认为。这是第一次很难理解它,所以阅读并尝试理解它。

3.第三次阅读错误

我不确定你是否做了两次,但你真的应该这样做三次。一个用于阅读,第二个用于理解,第三个用于运行你的大脑以快速修复它。

4.读取错误并回答“哪一行出现了?” "which line occurs it?"

如果你还没有修好它,那么下一步就是你。您可能至少错过了前一步,因此请阅读错误,并确保您确切知道它在哪一行出现。

5.再次读取错误并回答“为什么会发生?” - 如果你不知道 - 读错误"why does it occur?"

冷静。进入这一步并不是一种耻辱。阅读错误后,您应该能够回答这些问题,因为错误确切地说明了为什么会弹出。

6.你确定你读了五遍吗?

安全比抱歉更好。It's better to be safe than sorry.

7.如果您仍然不知道错误,请将其翻译成您的母语

如果你仍然无法解决它,这可能意味着你不理解错误,也许是一些语言障碍?尝试翻译它,以确保你能理解它。

8.我说你应该读错了吗?

9.如果我还有问题,我该怎么办??

使用地球上存在的最快和最快的方式。我很确定你从来不知道这个来源。他被称为https://google.com/,问他是否知道错误说的是什么。在这一步没有更多。他可能也知道如何修复它。但他已经老了所以现在不要打扰他。

10.好的,现在您应该知道错误是什么,所以请再次阅读并解决问题

 

啊,你不知道怎么样?

我建议你阅读..不,这次没有错误。一些关于调试的文章,因为你可能不知道你的代码是做什么的。橡皮鸭调试方法很有趣,非常有用,但你不需要走这么远。只需逐行,逐字逐句阅读您的代码,以确保您100%理解它,并且您知道每行的作用。 好。现在找到你的错误并修复它。

13.什么都没发现?

好吧好吧。现在你应该向我们的https://google.com/寻求更多帮助。

14.你为什么要读这一步?

我们的https://google.com/有时会很顽固,拒绝我们的帮助。我们需要用恰当,可理解的演讲与他交谈。世界上有些人不能这样做,但没关系。尝试在论坛或任何不和谐的帮助频道上讲一些人。

 

 

15、Unity中的键盘快捷键

Unity 2018.3中的快捷方式列表

我收集了所有文档中的键盘快捷键等等,我已经包含在以下文档中。 键盘快捷键的描述包含使用快捷键的上下文。

56页的描述很实用, 虽然Unity2019 开始支持所有快捷键的查看和定制。 Unity 2018.3中的快捷方式 https://www.dropbox.com/s/o91cgthtwhlft3e/Shortcuts%20in%20Unity%202018.3.pdf?dl=0

          这只是一个截图

所有版本的文档(自2018.2起)和波兰语版本。

或者 : https://www.dropbox.com/sh/n6sv2k2kb2bol5y/AACE20b2sWxPJypr_Nh-O_eAa?dl=0

 

 

 

16、 关于机型性能适配

可以参考Unity提供的参数:

最好可以得到对应的API , 然后动态进行值设置开关。 默认情况下 PC/MAC 和 Android还不一样 ~~。

比如有人遇到 在Android平台上的法线贴图显示问题:

https://qiita.com/takasy0331/items/8371d052cf869f6568b6

 

 

 

 

17、 好奇一个点就是怎么查看 动态字体动态生成的 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

 

 

 

 

18、 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

 

 

 

 

 

 

 

19、我不知道@ unity3d何时添加它,但我喜欢用TextMesh Pro作为选项而不是文本框提供UI元素。

我也记得之前只有一个 Text- TextMeshPro , 现在有了其他元素了。

这肯定是2018.4或2019.x的事情。 在2018.3.12中,内置的TMP是最新的还没有。

 

 

 

20、 Unity Frame Debug非常好用。 您是否知道可以按住Ctrl键并单击纹理图标以获得更大的显示窗口以及某些控件(如mipmap)?

这个弹出图片我知道, 但是可以调Slider 看每个mipmap Level 就没了解过。

我想知道 这个会显示当前应用的Level么? 否则没有什么卵用! mipmap 渲染是不是针对Texture ,是像素级的 确实没办法弄

https://twitter.com/phi_lira/status/1146087832194289664

 

 

 

 

21、 看到一个有用的回调

Application.lowMemory

当iOS或Android设备在应用程序在前台运行时通知内存不足时,会发生此事件。您可以从内存中释放非关键资产(例如纹理或音频剪辑)以响应此操作,以避免应用程序被终止。您还可以加载此类资产的较小版本。

此外,您应该将任何瞬态数据序列化为永久存储,以避免数据在应用程序终止时丢失。

对运行时资源管理很有帮助, 如果遇到触发回调也可以做一些日志上传, 统计机型,内存,Unity当前内存详细信息。 这样到时候也好分析 。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
class LowMemoryTrigger : MonoBehaviour
{
    List<Texture2D> _textures;
    private void Start()
    {
        _textures = new List<Texture2D>();
        Application.lowMemory += OnLowMemory;
    }
    private void Update()
    {
        // allocate textures until we run out of memory
        _textures.Add(new Texture2D(256, 256));
    }
    private void OnLowMemory()
    {
        // release all cached textures
        _textures = new List<Texture2D>();
        Resources.UnloadUnusedAssets();
    }
}

 

但是 又看到有人解釋這個警告回调。 不要乱用吧

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

 

 

 

 

 

 

 

22、内敛 inline

当面还是在学校学习 C++ 中接触到这个概念。

.Net 中没有 这个东西, 但是 Shader 中有~~

inline int example(int x)

{

return x + x;

}

内敛的优点

inline int func2(int x)
{
    return x + x;
}
int func()
{
    int example = 2;
    example = func2(example);
    return example;
}

编译器在编译时优化为: 直接把函数体内容嵌入到调用的地方,减少了函数调用的开销。

int func()
{ int example = 2 ; 
    example = example + example;    
}

所以说函数调用是有开销的: 每次调用函数时,参数,返回地址等都会被压入堆栈。然后,当函数返回时,它根据堆栈上加载的信息移动处理位置。由于内联消除了对这些过程的需要,因此提高了处理效率。 涉及到底层的汇编指令上了

https://qiita.com/edo_m18/items/83c63cd69f119d0b9831#%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF

 

当然了 C++但是学的时候提到 内敛适合轻量的小函数体。 不适合繁重的大函数。

inline int func2(int x)
{
    //  假设这里有很多行 很重的处理
    return x + x;
}
int func()
{
    int example = 2;
    example = func2(example);
    example = func2(example);
    example = func2(example);
    example = func2(example);
    example = func2(example);
    example = func2(example);
    example = func2(example);
    return example;
}

如果在这种状态下编译,func2的内容将在func中反复写入,

编译后的信息量将非常大。

因此,对于较小的处理单元,内联更好,但对于较大的函数则不行。

 

 

 

 

23、与非运行时/非MonoBehavior执行UnityWebRequest通信

您不能在不继承MonoBehavior的类中使用协同程序。

因此,UnityWebRequest监听如下。

/// <summary>
/// Editor上使用UnityWebRequest进行通信
/// </summary>
public static void EditorSendWebRequest(this UnityWebRequest self, Action onSuccess = null, Action onError = null)
{
    self.SendWebRequest();
    EditorApplication.CallbackFunction updateFunc = null;
    updateFunc = () =>
    {
        if (self.isDone)
        {
            if (self.isHttpError || self.isNetworkError || !string.IsNullOrEmpty(self.error)) {
                onError?.Invoke();
            }
            else {
                onSuccess?.Invoke();
            }
            EditorApplication.update -= updateFunc;
        }
    };

    EditorApplication.update += updateFunc;
}

 

注: Unity在 2018.3 /.4 2019.x 版本中提供了 Editor 协程Package可以使用。 !!

 

 

 

 

 

24、看到一篇文章: 微软程序员的一个分享。

Peephole optimizations in C++ and C# https://egorbo.com/peephole-optimizations.html

“由于编译器优化的改进而带来的性能提升将使程序的速度每18年翻一番 ”© Proebsting's Law

主要提到.Net 的编译器不是最优的,目前C#中的Peephole 优化非常有限。所以Unity才会自己要弄 Unity Burst and LILLC,这些运行时基本上使用与clang完全相同的优化。

 

Unity成员分享 DOST 的 Burst, Job , ECS 每个部分

https://lucasmeijer.com/posts/

There's no such thing as an API break https://lucasmeijer.com/posts/there_is_no_such_thing_as_an_api_break/

Whats next after Burst https://lucasmeijer.com/posts/whats_next_after_burst/

C++, C# and Unity https://lucasmeijer.com/posts/cpp_unity/

 

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

Burst是一种新的基于LLVM的后端编译器技术,可以让您更轻松。它需要C#作业并利用您平台的特定功能生成高度优化的机器代码。

 

 

 

 

 

 

25、 UPA, UPR 或者 WeTest

(以腾讯手游标准判断) 这些建议的值 很重要 作为优化游戏的一个参考。

 

 

 

优化建议 > GC Alloc较高

GC Alloc越频繁,量越大,由于Mono内存池可用内存不足导致的GC.Collect(造成卡顿原因之一)调用就越频繁,并且可能引起mono内存池不必要的扩展,因此脚本函数的GC分配量是既影响CPU也影响内存的重要参数。对于GC Alloc,我们建议的参考数值为:

对于基本每帧都会进行GC Alloc的函数,GC Alloc大于2KB的建议都确认下是否有可能把每帧内统一分配的临时变量抽取为类成员变量。

对于偶尔进行GC Alloc的函数,GC Alloc大于50KB的建议都确认下分配的数据结构是否有优化空间,GC Alloc是否可以分摊到多帧内。

 

 

平均耗时排名Top10的函数需要考虑是否进行优化,如果是脚本逻辑函数,建议优化代码计算的复杂度。

 

https://wetest.qq.com/help/documentation/10234.html

  • 提供问题列表,官方优化建议(Unity官方团队提供支持);

 

 

 

 

 

26、 Unity 首尔Unit 2019年演讲所有视频

https://www.youtube.com/playlist?list=PL412Ym60h6uu-QacPQo_mCT22zYIbZ0E4

肯定是韩语, 下面机翻截图 看看都讲了哪些内容!!!!

https://uniteseoul.com/2019/agenda_day1.asp#pointer

https://uniteseoul.com/2019/agenda_day2.asp#pointer

 

 

 

 

如何使用HLOD 创建大型场景

·会议介绍

创建大型场景时最大的问题之一是减少批量。在本次会议中,我们将向您展示如何通过使用HLOD减少Batch来提高性能。

·节目内容

关于HLOD的基本知识

·推荐用于

程序员有兴趣使用Unity创建大型场景

 

 

 

压缩阴影贴图以将光照应用于大型场景

·会议介绍

阴影计算并不容易,因为大场景需要高分辨率阴影贴图。

该会议定于转换为高分辨率的阴影映射到SVO(稀疏的体素八叉树),并学习如何压缩DAG(有向无环图),它也有望对付压缩阴影贴图渲染。

·节目内容

大型场景照明解决方案,ComputeShader的工作原理

·推荐用于

如果您有兴趣了解Open World Lighting,想了解下一代照明,灯光艺术家和程序员

 

 

 

 

 

27、 复杂物体的凸面网格碰撞器

https://makaka.org/unity-tutorials/optimization

          Unity允许您仅使用凸网格对撞机,因为它们具有比非凸形的 更小的性能负载。 因为对撞机在某些点上比对象本身覆盖更多的空间。使用以下技术来实现对撞机空间的准确性:

  1. 创建许多简单形式的碰撞器并手动将它们放在游戏对象上。
  2. 要快速自动获取复杂对象的凸网格对撞机,请使用Technie Collider Creator(资源商店)。 https://assetstore.unity.com/packages/tools/level-design/technie-collider-creator-62628?aid=1100lGft&utm_source=aff

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

 

 

 

28、 一个很有用的UGUI 扩展:

文本显示不下的时候后面的文本会转换为 ... 省略号 。

 

https://github.com/kiepng/TextEllipsis

还有到顶请求网络刷新的实现。

https://github.com/kiepng/Unity-PullToRefresh

 

  • 2
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值