Unity3d 周分享(23期 2019.11.10 )

选自过去1~2周 本身所看到外文内容:https://twitter.com/unity3d 和各类其余博客来源吧        html

 

1\  如何批量删除Unity Missing 组件

           Unity2019中彷佛准备了专用的方法git

GameObjectUtility.RemoveMonoBehavioursWithMissingScriptgithub

 

Unity2018支持的方法web

 

 

 

 

二、  [Unity]提示:在Inspector 中显示HDR模式渐变。

HDRgradient.cs编程

[GradientUsage(true)] public Gradient color;canvas

 

只需写一个名为GradientUsage的属性。api

 

 

 

三、对 Unity 2017.3中引入的“RGB Crunched ETC”和“RGBA Crunched ETC2”的验证

Updated Crunch texture compression library – Unity Blog数组

https://blogs.unity3d.com/jp/2017/11/15/updated-crunch-texture-compression-library/缓存

        Crunch compression of ETC textures – Unity Blog架构

https://blogs.unity3d.com/jp/2017/12/15/crunch-compression-of-etc-textures/

 

          这彷佛能够在iOS上使用,但iOS有PVRTC的图像,Android有ETC,因此我试图验证这些格式是否在iOS环境中是有用的。

 

验证方法

使用Unity版2017.3.0f3。

           准备了三种类型的512x512 / 1024x1024 / 2048x2048纹理,并使用非透明(RGB)和透明(RGBA)纹理进行验证。带有image〜的纹理名称 没有透明度, 而imageTrans~具备透明度。

              在MemoryProfiler (https://bitbucket.org/Unity-Technologies/memoryprofiler)上检查实际机器上的内存消耗。

         使用Mac终端上的  ls -alh  命令检查“PNG文件”的大小。

括号中的文件大小是Build Report确认的值。

          单击此处查看用于验证的项目 https://github.com/nakamura001/Unity-TestCrunch

iOS版

*原始尺寸图像能够显示在上一页上。

         在iOS环境中,因为图形API(Metal / OpenGL ES 3 / OpenGL ES 2)而出现差别。

         因为Metal不支持ETC(支持ETC2),所以在Metal环境中执行“RGB Crunched ETC”时,实际上会消耗RGBA 32位大小的内存。即便纹理略微增长文件大小但没有透明度,使用“RGBA Crunched ETC2”也能够减小内存使用量。

         因为OpenGL ES 2环境不支持ETC / ETC2,所以在执行期间使用“RGB Crunched ETC”或“RGBA Crunched ETC2”会消耗RGBA 32位大小的内存。

           在PVRTC中,因为图形API的差别,尺寸没有差别。

         除了存储容量最重要的游戏以外,PVRTC基本上是平衡和推荐的。

Android的

在Android环境中彷佛没有问题,所以若是图形质量没有问题,您能够主动使用它。

四、计算机语言的保留字数量(英文)

image.png

 

 

五、UGUI 为何要动静分离?

记得好像 之前发过这个截图: 

 

六、[Unity]使用字符串插值时,添加ToString时GC Alloc减小

using UnityEngine;

using UnityEngine.Profiling;

public class Example : MonoBehaviour

{

    private void Update()

    {

        int num1 = 1;

        int num2 = 2;



        // 有ToString

        var sampler1 = CustomSampler.Create( " 有ToString" );

        sampler1.Begin();

        var str1 = $"{num1.ToString()} / {num1.ToString()}";

        sampler1.End();

        

        // 没有ToString

        var sampler2 = CustomSampler.Create( "没有 ToString " );

        sampler2.Begin();

        var str2 = $"{num1} / {num2}";

        sampler2.End();

    }

}

 

 

 

 

七、[Unity]使用EditorUtility.RevealInFinder打开文件夹时,打开的是父级路径。

[MenuItem( "Tools/Hoge" )]

    private static void Hoge()

    {

        EditorUtility.RevealInFinder( "Assets" );

    }

image.png

当我尝试使用System.Diagnostics.Process.Start打开Assets文件夹时

[MenuItem( "Tools/Hoge" )]

    private static void Hoge()

    {

        Process.Start( "Assets" );

    }

image.png

八、[C#]如何经过反射获取特定类的全部子类

System.Reflection.Assembly.GetAssembly(typeof(Example))

   .GetTypes()

   .Where(x => x.IsSubclassOf(typeof(Example)) && !x.IsAbstract)

   .ToArray();

子类的实例的

顺便说一下,使用Activator 实例化如上所述得到的子类。

var instance = System.Activator.CreateInstance(subClassType) as Example;

 

 

九、您是否知道可使用EditorApplication.Beep在#unity3d中播放系统提示音?

如今,当构建成功时,个人构建脚本会发出一声蜂鸣声,若是构建失败,则会发出三声蜂鸣声。 多任务处理或在其余时方便

https://docs.unity3d.com/ScriptReference/EditorApplication.Beep.html

 

十、在Visual Studio中处理Unity游戏时,请尝试:

Shift + Ctrl + V能够将您在VS中复制的内容带到剪贴板

很方便y

image.png

 

 

 

十一、 Imposter System

https://assetstore.unity.com/packages/tools/modeling/imposter-system-69651

在不进行预处理的状况下将3D对象转换为2D面片渲染。从而减小场景中多边形的数量。

看起来就像3D对象,可是消耗的资源要少得多。

开发人员http:/starasgames.xyz/

全部的相关信息都在这边tps:/forum.unity3d.com/threads/w-i-p-realtime-imposter-system-fake-3d-optimization-plugin.426478/

 

 

十二、#Unity 2020.1.0a7:

Scripting: Added a parameter to FindObjectOfType and FindObjectsOfType called includeInactive, this will return objects that are also attached to disabled GameObjects.

脚本编写:向FindObjectOfType和FindObjectsOfType添加了一个名为includeInactive的参数,这将返回还附加到禁用的GameObjects的对象。

 

 

1三、[GIMP]启用建立法线贴图(法线贴图)

https://code.google.com/archive/p/gimp-normalmap/downloads

下载“ gimp-normalmap-winXX-1.2.3.zip”,

下载完成后将其解压缩

解压缩后,将“ normalmap.exe”移动到如下文件夹

C:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins

接下来,将如下三个文件移动到下一个文件夹

glew32.dll

libgdkglext-win32-1.0-0.dll

libgtkglext-win32-1.0-0.dll

C:\Program Files\GIMP 2\bin

如今您能够建立法线贴图了

image.png

在显示的窗口中自由调整参数,而后按“肯定”

 

 

 

 

 

1四、我一直在使用协程Coroutine,可是请尝试正确地理解异步Aysync/等待Await(第1部分)

            ( 可是在Unity中是建议使用协程的)

 

 

 

 

1五、[Unity]将结构体数据“从新解释”为不一样类型

当您在ECS中执行各类操做时,内部数据是相同的,可是因为类型不一样,必须将其转换。

 

          例如float,当有一个经过注入缓冲区执行批处理的API时,NativeArray<FloatData>不能直接输入诸如本地数据之类的结构数组。可是,这两个在内存方面几乎相同。因此Reinterpret<T, U>()在和从新解释数据NativeArray<FloatData>  与 NativeArray<float> 试图把它做为。

例子不起做用

     会报错。 

例如,考虑如下代码:我想一次显示MyData此结构ShowFloatLog(NativeArray<float> inputs)。天然,即便MyData的内容是浮点型的,处理也不是浮点型的,所以下面的代码将致使错误。

 

 1using Unity.Collections;
 2using UnityEngine;
 3
 4struct MyData { public float Value; }
 5
 6public class Sample: MonoBehaviour
 7{
 8    void Start()
 9    {
10        var input1 = new NativeArray<MyData>(new[] {
11            new MyData { Value = 11 },
12            new MyData { Value = 22 },
13            new MyData { Value = 33 },
14        }, Allocator.Temp);
15
16        ShowLog(input1 );        // 注意 注意 注意  这一句会报错
17
18        input1.Dispose();
19    }
20
21    static void ShowFloatLog(NativeArray<float> inputs)
22    {
23        foreach (var data in inputs)
24            Debug.Log(data);
25    }
26}

Reinterpret<T, U>()以“从新解释”为其余类型

       使用NativeArray<MyData>()  的NativeArray解释()。该API是Collection由于它们包含在包中,你必须导入包。

以下所示使用它。因为MyData的内容只是浮点数,所以能够将它们解释为浮点数。另外,因为仅是解释,请勿配置。参考指针是相同的。

 

 1void Start()
 2    {
 3        var input1 = new NativeArray<MyData>(new[] {
 4            new MyData { Value = 11 },
 5            new MyData { Value = 22 },
 6            new MyData { Value = 33 },
 7        }, Allocator.Temp);
 8
 9        // MyDataをFloatに再解釈
10        var floatInput = input1.Reinterpret<MyData, float>();
11
12        // NativeArray<float>なので動做
13        ShowLog(floatInput);
14
15        input1.Dispose();
16    }

 这种从新解释彷佛是一个指针,若是内部数据相同,则能够解释为各类数据。例如,float3的数组能够解释为float。固然,数据的长度是不一样的,所以您须要当心,但这彷佛一点也不有趣。

 仍是float3 -> float在的状况下,特别是问题不大,但float -> float3在的状况下被3整除数的基石素数将不等于错误。许多人彷佛对矢量化更有利,可是要当心。

 

 1    void Start()
 2    {
 3        var input1 = new NativeArray<float3>(new[] {
 4            new float3(111, 222, 33),
 5            new float3(444, 555, 666),
 6            new float3(777, 888, 999),
 7        }, Allocator.Temp);
 8
 9        // float3をfloatに再解釈
10        var floatInput = input1.Reinterpret<float3, float>();
11
12        // output : input length 3, reinterpret length 9
13        // float3をfloatにするにあたり、配列の長さが変わっている
14        Debug.Log($"input length {input1.Length}, reinterpret length {floatInput.Length}");
15
16        // 111 ~ 999 までの要素を個別に出力
17        ShowLog(floatInput);
18
19        input1.Dispose();
20    }

感想

 NativeArray<Vector3>快来旧返回APINativeArray<float3>新要求的API可能会很高兴,记住,当你遭受之间英寸

 

 

 

 

1六、看到C#优化相关开发者的文章

跟池子的概念可能不太同样:

  •        C#.NET中的缓存实现  

https://michaelscodingspot.com/cache-implementations-in-csharp-net/

缓存是软件开发中最经常使用的模式之一。

缓存很是适合不常常更改的数据。甚至更好,永不改变。不断变化的数据(例如当前计算机的时间)不该被缓存,不然您将获得错误的结果。

         

  • C#.NET中8种避免GC压力并提升性能的技术

https://michaelscodingspot.com/avoid-gc-pressure/

  • .NET中致使内存泄漏的8种方法

https://michaelscodingspot.com/ways-to-cause-memory-leaks-in-dotnet/

值得思考:  

  • 面向对象语言的类实例化指南:什么时候选择单例,静态,扩展方法或依赖项注入

https://michaelscodingspot.com/class-instantiation-guidelines-2/

  • 您应该知道的5种避免C#.NET中的事件引发的内存泄漏的技术

这是一个使用Prism  受欢迎的事件汇总器(与NuGet Prism.Core一块儿提供)的示例。

https://michaelscodingspot.com/5-techniques-to-avoid-memory-leaks-by-events-in-c-net-you-should-know/

https://www.nuget.org/packages/Prism.Core/

  • 掌握bug的10条技巧

https://michaelscodingspot.com/10-tips-gain-mastery-fixing-bugs/

  • 您应该在C#.NET中了解的7种调试技术

https://michaelscodingspot.com/7-debugging-techniques-know-c-net/

 

 

 

 

这个扩展工具蛮有用的:   由于Hierarchy中进行的搜素默认应该是针对GameObject name的模糊查询。 

1七、编辑器扩展使使用Hierarchy的组件搜索更加轻松

https://github.com/Unity-Technologies/ShaderGraph/blob/master/com.unity.shadergraph/Editor/Drawing/SearchWindowProvider.cs

 

 

1八、关于Unity四元数和Vector3的手写转换

两个函数:

从四元数转换为Vector3

从Vector3转换为四元数

 

 

 

1九、性能测试(虽然数据意义不是特别大)

         https://www.shibuya24.info/entry/constructor_performance

C# 在使用new 关键字构造对象,两种方式,一种直接有参构造函数。 还有一种是自变量的模式。 

// 无参构造函数的方式

new Hoge {x = 24, foo = "shibuya24"};

// 有参构造函数方式

new Piyo (24, "shibuya24");

 

 1public class Piyo
 2{
 3    public int x;
 4    public string foo;
 5    public Piyo(int x, string foo)
 6    {
 7        this.x = x;
 8        this.foo = foo;
 9    }
10}
11public class Hoge
12{
13    public int x;
14    public string foo;
15}

 

 1void Start()
 2{
 3    int ii = 10000000;
 4    Profiler.BeginSample("#### a ####");
 5    for (int i = 0; i < ii; i++)
 6        new Piyo {x = 0, foo = "foo"};
 7    Profiler.EndSample();
 8    Profiler.BeginSample("#### b ####");
 9    for (int i = 0; i < ii; i++)
10        new Hoge {x = 24, foo = "shibuya24"};
11    Profiler.EndSample();
12}

         前者在速度上约快5%

https://sharplab.io/

              会看到下面连着的指令多与少(猜想是这个影响的性能)

 

 

 

 

20、今天看文档:  发现Unity多了一些API ; 

BoxcastCommand

Use this struct to set up a box cast command to be performed asynchronously during a job.

RaycastCommand

Struct used to set up a raycast command to be performed asynchronously during a job.

SpherecastCommand

Use this struct to set up a sphere cast command that is performed asynchronously during a job.

CapsulecastCommand

Use this struct to set up a capsule cast command that is performed asynchronously during a job.

First introduced in: 

#if UNITY_2018_3_0

Present in: 

#if UNITY_2018_3_OR_NEWER

https://blogs.unity3d.com/es/2018/11/12/physics-changes-in-unity-2018-3-beta/?_ga=2.170637536.1333645541.1572165056-1185295926.1569768188

             批处理物理查询是一种在主线程以外运行物理查询的方法。须要此API,由于一我的不能从另外一个线程执行一般的API。在Unity 2018.1中,咱们发布了RaycastCommand.ScheduleBatch,可帮助计算主线程的射线广播。在Unity 2018.3中,咱们将其扩展为添加其余单结果查询,例如SphereCast,CapsuleCast和BoxCast。

https://connect.unity.com/p/unity-2019-3zhong-de-wu-li-geng-xin

 

 

 

 

 

今天看到一个pdf的一个文章: 

2一、斯坦福大学的 : 游戏编程范例

 https://web.stanford.edu/class/cs248/pdf/CS248-PocketGems-ProgrammingParadigms.pdf

目标

1.有关您项目的游戏架构的高级技巧

2.关于Unity不足之处的一些观点

大纲

1.游戏循环和模拟

2.处理交互

3.控制

4.实体组件系统

游戏循环处理全部游戏模拟逻辑:

-添加/删除实体

-处理玩家输入

-更新游戏逻辑系统

-处理运动,物理和碰撞

-为视图层生成状态

Unity的游戏循环

在初始化步骤中,组件之间也可能具备循环依赖性。

您能够拆分组件来解决此问题,可是这可能须要更新许多预制件,并可能增长组件之间的耦合。

您能够在Awake()和Start()之间分割初始化代码,但这确实很糟糕。

解决此问题的一种好方法是将您的行为与您的状态分开,而且不要对大多数组件使用Unity的回调。

模拟Simulation

封装循环和状态的对象

在Unity中,始终有一个模拟正在运行。

您对此几乎没有控制权:

-您没法快进/快退/重播

-您没法实例化多个模拟

-您没法区分初始化顺序和更新顺序

-您不能在同一组件上定义多个初始化/更新行为

 

 

 

2二、如何启动多个Unity并共享同一项目

        Unity是不能用多个exe实例打开一个Project的。 

*请注意,此方法不是正经常使用法。

image.png

 接下来,从“ unity-proj1”复制“ unity-proj2”并建立它。

从“ unity-proj2”中删除“ Assets”,“ Pakcages”和“ ProjectSettings”

        接下来,为了与“ untiy-proj1”文件夹共享这三个文件夹,我想启动一个命令行并建立一个符号连接。

使用“管理员权限”启动命令行

而后输入如下命令共享目录:

mklink /d <パス>\unity-proj2\Assets <パス>\unity-proj1\Assets
mklink /d <パス>\unity-proj2\Packages <パス>\unity-proj1\Packages
mklink /d <パス>\unity-proj2\ProjectSettings <パス>\unity-proj1\ProjectSettings

若是命令成功,将显示如下消息。

〜<< === >>〜建立符号连接

       若是上述全部命令均成功执行,则快捷方式之类的箭头标记将显示在“ unity-proj2”的“ Assets”,“ Pakcages”和“ ProjectSettings”文件夹中,以下所示。

image.png

image.png

 

 

 

 

 

https://twitter.com/FreyaHolmer/status/1184218791334612999

2三、Inverse Lerp上的thread -超级有用,但常常被忽略的功能!✨

 

Lerp(a,b,t)=值

InvLerp(a,b,value)= t

 

•lerp基于分数t返回a和b之间的混合

•逆lerp根据a和b之间的值返回分数t

lerp1.gif

用例! 🔊

说您要根据距离控制音频源的音量

•在10米处,您须要音量1

•在20米处,您要音量0

而后volume由

volume = InvLerp(20,10,distance)

lerp2.gif

 

若是您曾经使用过Photoshop的色阶工具,那么您会同时使用lerp和逆lerp! 🎨

 

输入值使用inverse lerp,输出值使用lerp!

 

 

当与图像一块儿使用时,可使用inverse lerp来增长值对比度! 例如,这是inverse lerp先后的自拍

lerp3.gif

 

另外,请注意,某些Lerp / InvLerp函数也能够推断(例如在着色器中),而其余函数会将值限制在给定范围内(例如Unity的Mathf.Lerp / InverseLerp函数)。

make sure you clamp unless you want to extrapolate 📈

确保钳位📈,除非您想推断clamp

 

这是一个有趣的用例!

一个inv lerp,其中a和b是颜色,而且value参数是该水的深度,您能够经过深度实现色相平移以消除颜色

不管如何,仅此而已! 但愿你以为这个有用〜

 image.png

 

 

附录-另外一个有用的功能是Remap!

remap将给定输入范围内的值转换为给定输出范围,该值基本上是反lerp和lerp的组合!

这是这三个代码!

(此外,这些都不是固定的-它们均可以推断)

 

 

若是您想了解更多关于lerp的信息,请访问另外一个主题!

https://twitter.com/FreyaHolmer/status/1175925033002254338

 

 

 

 

2四、[Unity]编辑器扩展现例,使用UIElements将工具栏添加到“场景”视图

 

 1using UnityEditor;
 2using UnityEngine;
 3using UnityEngine.UIElements;
 4[InitializeOnLoad]
 5public static class Example
 6{
 7    static Example()
 8    {
 9        foreach ( var sceneView in Resources.FindObjectsOfTypeAll<SceneView>() )
10        {
11            var toolbar           = new VisualElement();
12            var style             = toolbar.style;
13            var backgroundColor   = new Color32( 203, 203, 203, 255 );
14            var rootVisualElement = sceneView.rootVisualElement;
15
16            style.flexDirection   = FlexDirection.Row;
17            style.top             = 20;
18            style.backgroundColor = new StyleColor( backgroundColor );
19            style.height          = 20;
20
21            toolbar.Add( new Label { text = "ピカチュウ" } );
22            toolbar.Add( new Button( () => Debug.Log( "ピカチュウ" ) ) { text = "ピカチュウ" } );
23            toolbar.BringToFront();
24
25            rootVisualElement.Clear();
26            rootVisualElement.Add( toolbar );
27        }
28    }
29}

image.png

使用后:

image.png

 

 

 

2五、[Unity]启用移动和移动World Space uGUI元素的功能

 

canvas的渲染模式Render Mode是世界空间World Space的状态。 

 

 1public class Draggable : MonoBehaviour
 2{    
 3    Canvas canvas;
 4    Vector2 diff;
 5    static public void SetEventTrigger(Graphic element, EventTriggerType eventType, UnityEngine.Events.UnityAction<BaseEventData> callbackFunc)
 6    {        
 7        // 任意のエレメント(Buttonなど)に 任意のトリガーで発生する コールバック関数を登録する。
 8        EventTrigger trigger = element.gameObject.AddComponent<EventTrigger>();
 9        EventTrigger.Entry entry = new EventTrigger.Entry();
10        entry.eventID = eventType;
11        entry.callback.AddListener(callbackFunc);
12        trigger.triggers.Add(entry);
13        // EventTriggerTypeによって、BaseEventDataを派生クラスにキャストできる。
14        // https://docs.unity3d.com/ja/2017.4/ScriptReference/EventSystems.EventTrigger.html
15    }
16    private void Awake()
17    {
18        Graphic element = GetComponent<Graphic>();
19        // Canvasを探す。
20        canvas = null;
21        Transform parent = element.transform.parent;
22        while (parent != null)
23        {
24            canvas = parent.GetComponent<Canvas>();
25            if (canvas != null)
26                break;
27            parent = parent.parent;
28        }
29        SetEventTrigger(element, EventTriggerType.PointerDown, data => Donw(data));
30        SetEventTrigger(element, EventTriggerType.Drag, data => Drag(data));
31    }
32    Vector2 GetLocalPos()
33    {
34        Vector2 localPoint = Vector2.zero;
35        Vector3 screenPoint = Input.mousePosition;
36        // 【Unity】【uGUI】RectTransformUtilityでスクリーン座標をUIのローカル座標やワールド座標に変換する - LIGHT11
37        // http://light11.hatenadiary.com/entry/2019/04/16/003642
38        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint);
39        return localPoint;
40    }
41    void Donw(BaseEventData data)
42    {        
43        Vector2 v = transform.localPosition;
44        diff = GetLocalPos() - v;
45    }
46    void Drag(BaseEventData data)
47    {
48        transform.localPosition = GetLocalPos() - diff;
49    }
50}
51public class DragSample : MonoBehaviour
52{
53    public Button button;
54    public Scrollbar scrollbar;
55    public RawImage rawImage;
56    void Start()
57    {
58        // 任意のuGUIエレメントにDraggableをアタッチすることで、ドラッグ移動できるようになる。
59        button.gameObject.AddComponent<Draggable>();
60        scrollbar.gameObject.AddComponent<Draggable>();
61        rawImage.gameObject.AddComponent<Draggable>();
62    }
63}

 

 

 

2六、使处理Unity GL类更加容易

Unity中的线条绘制

       绘制一条简单的线(例如用于在3D空间中的Unity中进行调试)时,彷佛常用GL,可是若是使用此GL类,则只能使用OnRenderObject方法,或者若是您有多个摄像头 有些点难以使用,难以使用。

诸如Debug.DrawLine之类的Debug类也具备线条绘制功能,可是仅在“Scene”视图中显示,不能由实际计算机处理。

所以,我尝试使用GL复制易于处理的内容,例如Debug.DrawLine和Debug.DrawRay。

像Debug.DrawLine同样易于处理

能够从Update方法中调用

也能够显示在“Game”视图中

https://qiita.com/NegiuraRoman/items/09df1d4f72fc44099db0

 

2七、Mesh Optimizer   插件:、

我尝试使用网格优化器,它能够免费将高多边形更改成低多边形
https://qiita.com/matchyy/items/a4b1e232c3531ab8272a

 

 

2八、GameCreator概述

什么是GameCreator?           (这种编辑器的设计思想值得学习!!)

Visual Scripting和UnityEditor扩展资产

指令处理已添加到Unity的Inspector中,而且处理从顶部开始按顺序执行

           基本逻辑由动做,触发器和条件三部分组成,将它们组合在一块儿便可构建游戏。

  • Actions将动做赋予GameObject等。
  • Triggers火灾事件,例如动做
  • Conditions执行控制处理,例如条件分支

除上述内容外,还包括用于操做播放器的播放器,用于管理变量的变量,用于控制相机操做的相机电机等。

添加您本身的动做,触发器和条件(适用于工程师)

几个额外的扩展模块正在销售中,能够添加以添加各类游戏功能

https://assetstore.unity.com/packages/templates/systems/game-creator-89443

https://docs.gamecreator.io/game-creator/game-creator