Visual Effect Graph

Visual Effect Graph
全新的Visual Effect Graph将提供强大功能用于制作精美的游戏特效。Visual Effect Graph是一个基于节点的系统,灵活且易于使用,能够帮助艺术家快速创作出色的视觉特效。它易于扩展,只需要拖动预制节点就能实现丰富的效果。

102040y0bwcf3zcbmvcaub
Visual Effect Graph中直观的界面对艺术家非常友好,艺术家可以轻松上手并愉快地尝试各种功能。该工具具有高效的响应性,你可以在创作过程中实时查看所有改动。

Visual Effect Graph架构为Unity带来的另一个重大创新是,它能够以高性能在GPU上处理数百万个粒子。Unity 2018.3推出了Visual Effect Graph预览版,它支持高清晰渲染管线HDRP,轻量级渲染管线LWRP支持将在之后加入。

我们希望在改进该系统的同时,了解你的想法和反馈。了解Visual Effect Graph更多内容:
https://unity.com/visual-effect-graph

观看Visual Effect Graph演示项目:
https://v.qq.com/x/page/k0769n77dao.html

 

Unity性能基准测试

我们将讲解如何使用多个Unity工具,通过简单的方法收集性能指标并创建基准,这些工具包括:

  • Unity Test Runner
  • Unity Performance Testing Extension
  • Unity Performance Benchmark Reporter

为什么在Unity中进行性能基准测试?
作为Unity的开发人员,通常会遇到以下情形:项目不久前还运行得流畅而快速,但进行一次或多次改动后,场景运行速度明显变慢,帧数也降了很多,其它性能问题开始不断出现。寻找造成性能下降的改动会非常困难。

如果你是一名得Unity合作伙伴,想要了解自己开发的SDK、驱动、平台、资源包或其它工具中的性能变化。或者想要收集自己产品在不同Unity版本的性能指标,但不知道如何进行收集和对比。

本文中示例所建立的性能基准可以带来很大帮助。现在我们将展示如何收集性能指标、通过这些指标创建基准并可视化查看性能指标的变化。

160039wh8h8h94r33bnb49.png.thumb.jpg下载示例项目
本文将使用UnityPerformanceBenchmark示例性能测试项目中的测试代码。

请从GitHub下载最新版本的XRAutomatedTests,你可以在PerformanceTests子目录中找到UnityPerformanceBenchmark项目。

下载XRAutomatedTests:
https://github.com/Unity-Technologies/XRAutomatedTests/releases

在Unity Test Runner中编写性能测试
UnityPerformanceBenchmark项目包含多个示例场景,它们将通过Unity Performance Testing Extension用于Unity性能测试。

我们需要了解如何使用Unity Test Runner 和Unity Performance Testing Extension编写性能测试。在编写前性能测试之前,我们首先介绍这二个工具的信息。

1、Unity Test Runner
我们将使用Unity Test Runner运行性能测试。Unity Test Runner是内置在Unity编辑中的测试执行框架,它允许开发人员在编辑和运行模式下针对目标平台测试代码,例如:Standalone、Android系统或iOS系统。

2、Unity Performance Testing Extension
Unity Performance Testing Extension是一个Unity编辑器扩展包,它提供API和测试用例属性,允许开发人员在Unity编辑器和播放器中对Unity Profiler性能分析器标记和非性能分析器的自定义指标进行采样和聚合。

Unity Performance Test Extension要求使用Unity 2018.1或更高版本。如果在UnityPerformanceBenchmark项目中运行示例性能测试,或者使用Unity Performance Test Extension时,请确保使用Unity 2018.1或更高版本。

使用命令行打开示例项目
UnityPerformanceBenchmark项目实现了IPrebuildSetup接口,这是Unity Test Runner的组成功能,可以用来实现Setup方法,该方法会在Unity Test Runner执行测试运行前自动调用。

UnityPerformanceBenchmark项目的IPrebuildSetup.Setup方法首先会解析命令行参数,寻找播放器构建设置。该方法允许我们使用相同Unity项目灵活地为性能测试构建播放器,具体设置可以针对不同平台、渲染线程模式、播放器图形API、脚本实现以及立体渲染路径和VR SDK等支持XR的设置而定。

因此,我们需要从命令行用Unity打开UnityPerformanceBenchmark项目,传入在Unity Test Runner运行测试时要使用的播放器构建选项。

示例:在Windows系统启动UnityPerformanceBenchmark项目,构建Android播放器。

[C#] 纯文本查看 复制代码
Unity.exe -projectPath
C:\XRAutomatedTests-2018.2\PerformanceTests\UnityPerformanceBenchmark
-testPlatform Android -buildTarget Android -playergraphicsapi=OpenGLES3 -mtRendering -scriptingbackend=mono

指令会在Windows系统启动Unity,针对具有OpenGLES3图形API、多线程渲染功能和Mono脚本后端的Android系统进行构建。

示例:从OSX系统启动UnityPerformanceBenchmark项目以构建iOS播放器。

[C#] 纯文本查看 复制代码
./Unity -projectPath /XRAutomatedTests-2018.2/PerformanceTests/UnityPerformanceBenchmark
-testPlatform iOS -buildTarget iOS -playergraphicsapi=OpenGLES3 -mtRendering -scriptingbackend=mono
-appleDeveloperTeamID=<yourAppleDeveloperTeamID>
-iOSProvisioningProfileID=<yourIosProvisionProfileID>

指令会在OSX系统启动Unity,并针对具有OpenGLES3图形API、多线程渲染功能和Mono脚本后端的iOS系统进行构建。该指令还提供了Apple开发团队信息和部署到iOS设备所需的配置文件信息。

当我们从命令行使用Unity打开UnityPerformanceBenchmark项目时,如以上示例所示,命令行参数将保存在内存中,以便IPrebuildSetup.Setup方法解析并用于构建播放器。

尽管在Unity Test Runner中运行测试时,不必使用从命令行启动的方法,但该方法可以避免为每个播放器配置使用单独的测试项目。

了解从命令行打开项目和运行测试时所用到的命令行选项,请参考《如何运行Unity性能基准测试》:
https://github.com/Unity-Technol … ance-Tests#howtorun

如果想要了如我们如何在测试项目中解析播放器构建设置,请查看UnityPerformanceBenchmark测试项目中,Scripts目录下的RenderPerformancePrebuildStep.cs文件。

打开Test Runner窗口
打开UnityPerformanceBenchmark项目后,我们需要在Unity编辑器中打开Unity Test Runner窗口。
1、在Unity 2018.1中,打开Window > Test Runner。
2、在Unity 2018.2中,打开Window > General      > Test Runner。

Unity Test Runner窗口打开后,如下图所示。

160039cqfbybyd2myf73yf.jpg.thumb带有测试的Unity Test Runner窗口

截图中是我们的Unity性能测试,我们可以按下窗口左上角的“Run”按钮在Unity编辑器中运行测试,也可以针对实际设备或平台按下右上角的“Run all in player”按钮来运行测试。

如果想在IPrebuildSetup.Setup方法中调试代码,可通过以下步骤实现。
1、在Visual Studio中设置IPrebuildSetup.Setup代码的断点。
2、将Visual Studio Tool for Unity扩展附加到Unity编辑器。
3、按下Unity Test Runner窗口中的“Run All”或“Run Select”按钮,在编辑器运行测试。

此时,Visual Studio调试器会分析代码,你可以根据需要进行调试。

调试技巧
如果想在IPrebuildSetup.Setup方法中调试代码,可通过以下步骤实现。
1、在Visual Studio中设置IPrebuildSetup.Setup代码的断点。
2、将Visual Studio Tool for Unity扩展附加到Unity编辑器。
3、按下Unity Test Runner窗口中的“Run All”或“Run Select”按钮,在编辑器运行测试。

此时,Visual Studio调试器会分析代码,你可以根据需要进行调试。

Unity性能测试示例
下面让我们来查看一个性能测试的示例,更好地了解性能测试如何工作。

示例:在Unity性能测试中采样性能分析器标记

[C#] 纯文本查看 复制代码
[PerformanceUnityTest]
public IEnumerator SpiralFlame_RenderPerformance()
{
yield return SceneManager
.LoadSceneAsync(spiralSceneName, LoadSceneMode.Additive);
SetActiveScene(spiralSceneName);
// 实例化场景中的性能测试对象
var renderPerformanceTest =
SetupPerfTest<DynamicRenderPerformanceMonoBehaviourTest>();
// 使时间值在测量前稳定下来
yield return new WaitForSecondsRealtime(SettleTime);
// 使用Performance Test Extension的ProfilerMarkers API
using (Measure.ProfilerMarkers(SamplerNames))
{
// 设置CaptureMetrics的标识为TRUE
// 开始采集指标
renderPerformanceTest.component.CaptureMetrics = true;
// 运行MonoBehaviour Test
yield return renderPerformanceTest;
}
yield return SceneManager.UnloadSceneAsync(spiralSceneName);
}

本示例中使用的测试方法是SpiralFlame_RenderPerformance。我们从方法装饰器[PerformanceUnityTest]可以知道,该方法是个Unity性能测试。

UnityPerformanceBenchmark测试项目中的所有测试内容都按照该测试方法中的相同模式:
1、加载场景进行测试;
2、将场景设置为活动状态,以便我们在测试方法中与其进行交互;
3、创建一个DynamicRenderPerformanceMonoBehaviourTest类型的测试对象,并将其添加到测试场景中。该过程发生在SetupPerfTest<T>方法中;
4、在开始采样指标前,并在加载和添加测试对象到场景后,等待场景的恒定时间值“稳定下来”;
5、通过Performance Test Extension API设置用于采集的性能分析标记;
6、告诉性能测试我们已准备好开始采集指标;
7、然后yield return测试对象即IMonoBehaviourTest,在渲染循环中采集指标。

我们也会在RenderPerformanceMonoBehaviourTestBase基类中不属于Unity性能分析器标记、帧计数或执行时间的自定义指标进行采样。

示例:在Monobehaviour脚本中采样自定义指标

[C#] 纯文本查看 复制代码
private void Update()
    {
        if (CaptureMetrics)
        {
            FrameCount++;
            SampleFps();
#if ENABLE_VR
            if (XRSettings.enabled)
            {
                SampleGpuTimeLastFrame();
            }
#endif
        }
        if (IsMetricsCaptured)
        {
            EndMetricCapture();
        }
    }

 

[C#] 纯文本查看 复制代码
private void SampleFps()
{
Fps = GetFps();
Measure.Custom(FpsSg, Fps);
startFrameCount = Time.renderedFrameCount;
}

 

[C#] 纯文本查看 复制代码
private void SampleGpuTimeLastFrame()
{
var gpuTimeLastFrame = GetGpuTimeLastFrame();
Measure.Custom(GpuTimeLastFrameSg, gpuTimeLastFrame * 1000);
}

 

[C#] 纯文本查看 复制代码
public void EndMetricCapture()
{
CaptureMetrics = false;
#if UNITY_ANALYTICS && UNITY_2018_2_OR_NEWER
Measure.Custom(startupTimeSg, appStartupTime);
#endif
}

上面示例中,我们采集了FPS、GpuTimeLastFrame和应用程序启动时间。

1、IsTestFinished属性
在RenderPerformanceMonoBehaviourTestBase基类中,我们实现了属性public bool IsTestFinished。我们需要实现该属性,因为RenderPerformanceMonoBehaviourTestBase会实现IMonoBehaviourTest 接口。

该属性非常重要,因为Unity Test Runner使用它来了解何时停止测试。当它为true时,测试终止。开发者需要自己实现该逻辑以确定Unity Test Runner应该何时停止测试。

示例:采集IsTestFinished属性中的自定义指标

[C#] 纯文本查看 复制代码
public bool IsTestFinished
{
get
{
bool isTestFinished = false;
if (IsMetricsCaptured)
{
Measure.Custom(objCountSg, RenderedGameObjects);
Measure.Custom(trianglesSg, Tris);
Measure.Custom(verticesSg, Verts);
isTestFinished = true;
}
return isTestFinished;
}
}

本示例中,我们采集了测试完成时场景中已渲染游戏对象、三角形和顶点的数量信息。

2、SampleGroupDefinition
现在我们了解如何调用Performance Testing Extension来采样指标的示例,下面将介绍如何配置这些指标。

Measure.*方法通常接收SampleGroupDefinition结构作为参数。创建新SampleGroupDefinition时,要定义收集样本的属性。

示例:为GpuTimeLastFrame定义新SampleGroupDefinition,使用毫秒作为采样单位,使用最小值聚合样本
下面是用于GpuTimeLastFrame的SampleGroupDefinition代码。我们通过该代码让Performance Testing Extension知道如何收集样本并为GpuTimeLastFrame聚合。

该SampleGroupDefinition来自动态场景渲染性能测试示例,因此我们在此选择使用收集到的最小值聚合样本。为什么我们不使用例如:中位数或平均值,这样更常见的聚合度量呢?

这是因为场景是动态的。在动态场景中渲染过程会不断变化,所以使用中位数或平均值聚合会使运行相同代码的相同场景得到不可靠或不一致的结果。

如果我们想跟踪动态场景中渲染指标的单个聚合,这可能是最好的方法。但是,当我们为静态场景定义类似SampleGroupDefinition时,我们会使用中位数聚合。

[C#] 纯文本查看 复制代码
new SampleGroupDefinition(GpuTimeLastFrameName, SampleUnit.Millisecond, AggregationType.Min)

示例:为FPS定义新SampleGroupDefinition,将None用作样本单位,使用中位值来聚合样本,最好能提高数值
下面是为FPS使用的SampleGroupDefinition。FPS没有特定测量单位,FPS的单位就是FPS,所以在此指定SampleUnit.None。我们将使用中位数聚合类型。

该测试发生在静态场景中,所以我们不必担心不可预测的渲染体验。我们明确为样本组设定了15%的阈值,对increaseIsBetter参数传入了true,因为提高FPS是件好事。

当从命令行运行时,最后二个参数会被收集并保存在性能测试结果的.xml文件中,稍后可用于Unity Performance Benchmark Reporter,从而建立基准。

[C#] 纯文本查看 复制代码
new SampleGroupDefinition(FpsName, SampleUnit.None, AggregationType.Median, threshold: 0.15, increaseIsBetter: true)

测试完成后,所有之前启用的指标样本都会由Performance Testing Extension进行聚合。

3、测量类型
在示例代码中,我们使用了几个不同的Unity Performance Testing Extension API,它们是:
1、Measure.ProfilerMarkers
2、Measure.Custom

Unity Performance Testing Extension还提供其它Measure方法,可以根据开发者在Unity中测试性能内容和方式来满足特定需求。其它方法包括:
1、Measure.Method
2、Measure.Frames
3、Measure.Scope
4、Measure.FrameTimes

关于不同Measure方法的更多信息,详请阅读:
https://docs.unity3d.com/Package … 1/manual/index.html

在Unity Test Runner中运行性能测试
现在我们已经展示了一些示例,了解如何使用Unity Test Runner和Unity Performance Testing Extension编写性能测试,接下来了解如何运行测试。

我们可以通过二个主要方式执行性能测试:

在命令行中使用-runTests 选项启动Unity
这是运行性能测试的首选方式,因为Unity Performance Test Extension会生成.xml文件,该文件可用于在Unity Performance Benchmark Reporter中查看并对比结果。

直接在Unity编辑器运行测试
使用条件是:
1、仅在Unity Test Runner运行测试并查看结果,不需要采集结果以供之后使用。
2、想要验证测试是否能够运行或者需要调试测试代码。

1、使用-runTests命令行选项运行性能测试
下面是如何使用Unity Test Runner从命令行运行性能测试的二个示例,。这些示例的代码似曾相识,因为我们在此使用了前面用过的示例,这些示例用来介绍如何从命令行打开UnityPerformanceBenchmark项目。

示例:在Windows系统针对Android播放器运行UnityPerformanceBenchmark性能测试
下面指令会在Windows系统启动Unity,针对具有OpenGLES3图形API、多线程渲染功能和Mono脚本后端的Android系统进行构建。

[Shell] 纯文本查看 复制代码
Unity.exe -runTests [-batchmode] -projectPath
C:\XRAutomatedTests-2018.2\PerformanceTests\UnityPerformanceBenchmark -testPlatform Android -buildTarget Android -playergraphicsapi=OpenGLES3 -mtRendering -scriptingbackend=mono -testResults
C:\PerfTests\results\PerfBenchmark_Android_OpenGLES3_MtRendering_Mono.xml -logfile
C:\PerfTests\logs\PerfBenchmark_Android_OpenGLES3_MtRendering_Mono_UnityLog.txt

示例:在OSX系统针对iOS播放器运行UnityPerformanceBenchmark性能测试
下面指令会在OSX系统启动Unity,并针对具有OpenGLES3图形API、多线程渲染功能和Mono脚本后端的iOS系统进行构建。该指令还提供了Apple开发团队信息和部署到iOS设备所需的配置文件信息。

[Shell] 纯文本查看 复制代码
./Unity -runTests [-batchmode] -projectPath /XRAutomatedTests-2018.2/PerformanceTests/UnityPerformanceBenchmark
-testPlatform iOS -buildTarget iOS -playergraphicsapi=OpenGLES3
-mtRendering -scriptingbackend=mono
-appleDeveloperTeamID=<yourAppleDeveloperTeamID>
-iOSProvisioningProfileID=<yourIosProvisionProfileID> -testResults /PerfTests/results/PerfBenchmark_Android_OpenGLES3_MtRendering_Mono.xml
-logfile /PerfTests/logs/PerfBenchmark_Android_OpenGLES3_MtRendering_Mono_UnityLog.txt

对于这二个示例,我们将引入了三到四个新命令行选项,使用IPrebuildSetup.Setup方法的命令行参数来帮助我们运行测试。

-runTests
该选项会告诉Unity Test Runner运行测试。

-testResults <pathToWritePerformanceTestResultsFile>
该选项会指定.xml文件的文件名和路径,Unity Test Runner在该文件保存性能测试结果。

-logfile <pathToWriteUnityEditorLogFile>
该选项会指定Unity编辑器所写入日志文件的文件名和路径。它是可选项,如果可以快速访问Unity编辑器日志文件,在调查失败结果和问题时,该选项会非常实用。

-batchmode
该选项会让Unity编辑器打开Headless模式。当只运行播放器性能测试且不需要打开Unity编辑器窗口时,我们会使用该选项。这可以在自动执行测试时节省时间。不使用该选项时,Unity编辑器会在执行测试前打开。

我们通常从命令行运行性能测试,在持续集成系统中使用batchmode。

示例:从命令行运行UnityPerformanceBenchmark测试

160046xa00so57s7bz0s7s
在Unity编辑器运行性能测试
选择PlayMode时,在顶部打开Unity Test Runner窗口,我们会得到三个按钮:
  • Run All:点击该按钮会在PlayMode标签页运行所有测试
  • Run Selected:点击该按钮会运行所选测试或节点,包括节点下的所有测试
  • Run  all in player:点击该按钮会让Unity编辑器构建出构建设置中设定的播放器类型,并在该播放器中运行测试。

重要要求
在Unity编辑器中从Test Runner窗口运行性能测试。不会得到Unity Performance Benchmark Reporter需要的.xml文件。

如果想要在完成性能测试时得到结果.xml文件,需要在命令行加入-runTests命令行选项来启动Unity,再运行测试。请注意,当使用-runTests命令行选项运行Unity时,编辑器会打开并开始运行测试。

得到的.xml文件包含测试运行后的结果和元数据,我们会在Unity Performance   Benchmark Reporter中使用这些结果来创建基准结果,并比较后续测试运行结果。

示例:在Unity编辑器运行性能测试

161412yxqxc75xvcz7ws5c查看性能测试结果
如果我们在编辑器中运行测试,则可以通过选中测试在Unity Test Runner窗口底部附近查看聚合值。

示例:在Unity Test Runner查看性能测试样本聚合

161413dzvh8gxmm86oocvn如果想查看从命令行运行Unity性能测试的结果,需要使用Unity Performance Benchmark Reporter,或是打开.xml文件,但该文件的内容不容易读取。

下面要讨论如何使用Unity Performance Benchmark Reporter来查看并对比结果。

使用Unity Performance Benchmark Reporter
Unity Performance Benchmark Reporter可以在带有图形可视化html报告中比较性能指标基线和后续性能指标。

Unity Performance Benchmark Reporter被构建为.NET Core 2.x程序集,所以它可以在支持.NET的不同平台上运行,例如:Windows、OSX等。因此,运行该工具,需要确保已安装.NET Core 2.x SDK。

执行Unity Performance Benchmark Reporter时,需要使用dotnet命令调用该程序集,命令如下:

[Shell] 纯文本查看 复制代码
dotnet UnityPerformanceBenchmarkReporter.dll
--baseline=D:\UnityPerf\baseline.xml
--results=D:\UnityPerf\results --reportdirpath=d:\UnityPerf

该工具运行后,将创建名为UnityPerformanceBenchmark目录,其中包含html报告以及和报告相关的.css、.js和图片文件。打开该html报告可以查看.xml文件中所采集的性能指标可视化内容。

1、命令行选项
–results
该选项指定保存非基线.xml文件的目录路径,这些文件将包含在html报告中。

至少要给UnityPerformanceBenchmarkReporter.dll程序集传入一个–results值。它是唯一必需的字段。该命令行选项还能用于指定.xml非基线结果文件。此外,你可以通过重复使用该选项来指定多个路径或文件,命令如下:

[Shell] 纯文本查看 复制代码
--results=D:\UnityPerf\results --results=D:\UnityPerf\results.xml

–baseline
该选项指定和其它结果对比的.xml文件的路径。

–reportdirpath
该选项指定Unity Performance Benchmark Reporter创建性能基准报告的目录路径。报告将创建在UnityPerformanceBenchmark子目录中。

如果未指定报告保存路径,将在调用UnityPerformanceBenchmarkReporter.dll的工作目录创建UnityPerformanceBenchmark子目录。

2、对比性能测试结果
下面来对比Performance Benchmark Reporter中的性能测试结果。

示例:在启用VR的Gear VR场景中尝试修改配置,以提高帧率。

下面有一个带有以下复杂性特征的Unity场景。

  • 732个对象
  • 95,898个三角形
  • 69,740个顶点

 

161420ohifjunz0iuxxnaiGear VR场景

我们针对该场景运行了Unity性能测试并采集了指标,这将帮助我们了解是否可以使用多通道立体渲染维持近60 FPS。

下面,对测试结果运行Performance Benchmark Reporter,发现得到的FPS接近30 FPS,是目标FPS的一半。

161420yjmgtob119mtfcfg.png.thumb.jpg然后,我们将尝试使用单通道多视图立体渲染来了解是否能得到接近60 FPS的结果。使用修改后的配置重新运行性能测试,然后创建另一个Unity性能基准报告,对比新报告和之前报告的结果。
161423mhd8x9d9wx6xppzd-2从多通道改为单通道多视图立体渲染的结果

将配置改为单通道多视图渲染后,FPS提高到了37。如果我们希望让该场景在Gear VR上运行时不发生明显的掉帧现象,我们仍需要使FPS接近60。

最后,我们将尝试减少场景中旋转的立方体数量以提高FPS。在多次尝试后,我们将性能提升到55 FPS。但必须将场景中的对象数量从732个减少为31个,减少的对象数量相当多。

现在将它用作FPS基线和之后的基准,希望能提高它的性能。

161423mhd8x9d9wx6xppzd使VR场景实现更可接受的FPS

建立基准并跟踪性能改动
建立基准可以具有多种含义,具体取决于项目。本文中指的是在Unity运行性能测试,我们将探讨建立结果的基线集,以及近期最好的性能指标集合,用来在做更改时对比后续结果。这些结果将成为我们的基准。

在上一部分中,我们为Gear VR使用了单通道多视图立体渲染的配置,并减少了场景对象数量,从而得到“可接受的”FPS。我们决定使用该测试结果作为基准。

下面让我们了解修改播放器配置时如何使用该基准。

示例:使用性能基准来检测配置改动造成的性能下降情况
我们将在场景中启用抗锯齿功能,使画面更平滑。Unity针对Android系统的默认质量设置会禁用抗锯齿功能,但我们想了解是否能启用该功能,并保持该Gear VR场景中可观的FPS。

首先在IPrebuildSetup.Setup方法中设置抗锯齿值为4。

[Shell] 纯文本查看 复制代码
QualitySettings.antiAliasing = 4;

接下来,在启用Gear VR的Android手机上重新运行性能测试。然后,使用Unity Performance Benchmark Reporter来对比此次运行结果和新建立的基准结果。

161917c1z9tq8q48jtqstj设置抗锯齿值为4后,检测到FPS下降

重新配置Unity播放器并使用等级4的抗锯齿后,FPS下降为32,该值与之前项目开始时的FPS值差不多,那时场景中有732个对象。

现在尝试降低抗锯齿值,从而了解是否能恢复为之前可观的FPS值。所以我们将抗锯齿设为2,接着设为1,得到的结果如下图所示。

161918qsiipai2psa0955j尝试降低抗锯齿值来恢复场景到可接受的FPS

在重新配置的情况下,通过使用之前建立的性能基准,我们能够尝试修改Unity播放器设置,然后在提交更改前了解性能影响。

虽然仍使用默认方差阈值15%,抗锯齿值为1,FPS现在达到了49,对VR场景而言还是和理想的60 FPS差距较大。所以不会提交这些改动。

结语
Unity非常注重默认设置下的优秀性能。但Unity引擎只是这其中的一部分,为了让用户喜欢玩自己研发的游戏,更重要的是让他们在所有平台上享受到流畅和高性能的体验。例如:使用不会影响性能的SDK、驱动或Unity资源包也非常重要,从而使所有用户得到优秀的总体性能体验。

本文介绍了Unity Performance Testing Extension和Unity Performance Benchmark Reporter,它们用来轻松收集性能指标并用来创建基准。我们建议你尝试使用这些工具,了解它们能为性能工作做些什么。

我们在本文了解了:
1、如何使用Unity Test Runner编写性能测试,用来采样性能分析器和其它指标。
2、使用Unity Test Runner执行性能测试的不同方法。
3、如何使用Unity Performance Benchmark Reporter来分析并对比性能指标,在测试游戏性能时反复运行该工具。

为这些指标建立基线,然后使用基线为场景、游戏、SDK、驱动、资源包或其它Unity集成创建基准,这样能有效地了解改动造成的影响。

使用Shader Graph实现《塞尔达传说:旷野之息》风格的着色器

Unity的技术经理Ciro Continisio在Connect上分享创作模仿任天堂游戏《塞尔达传说:旷野之息》角色风格的着色器,受到不少用户的关注,本文将在分享制作该着色器的方法。

014647qy1ofnof23f1rooj
说明事项:
1、该着色器使用Shader Graph着色器视图制作。
2、使用了全新的轻量级渲染管线LWRP
3、由于目前LWRP和Shader Graph着色器视图仍处于早期阶段,各自存在一些限制,本文将讲解如何使用技巧来解决这些限制问题。
4、受客户端所限制,为了方便大家更好阅读理解,本文中着色器完整视图图片提供了下载,请在文末获得下载地址

目标
我打算实现二个层级的着色器,它带有强光和阴影。我要以二种方法支持镜面光照:头发使用简单的颜色面片实现,而皮肤要通过画笔描边来定义。

你可以在下图看到二种方法的不同,塞尔达的衣服呈现了特有的画笔描边效果,而她的头发上的高光只是明亮颜色的硬块。

014649tnuz9wn3p73fc9vz.png.thumb.jpg希望实现的着色示例效果

我还想实现面向太阳时出现的边缘光照效果,以及当光线在特定角度时出现的几乎全白的边缘,请注意图中塞尔达的耳朵、手指和右臂。

最后,我想支持高光、法线和发射贴图。

视图流程
下图是视图流程的概述,所有重要部分都根据功能用方块突出显示。

左侧的TangentToWorld节点不是自定义节点,而是一个SubGraph。因为当时Transform节点存在bug,所以我必须使用SubGraph重新实现转换,从切线空间转为世界空间。

该节点内容如下图所示。

014650eaono4pdynoyaiia.png.thumb.jpgTangentToWorld SubGraph

让我们返回该视图,如我们所见视图从左到右,从几何体的法线开始处理,它混合了来自图中紫色方框Normal map部分的法线。法线定义了表面的方向性,对计算光照非常重要。

然后来到黄色方框Lighting部分,使用自定义节点从场景的主定向光获取光照数据。

为了创建着色效果,我计算了二个向量的数量积,即光的方向和法线。通过使用Smoothstep节点获得该遮罩,它看起来是带有硬边缘的黑色和白色。

除了作为模型实际的光线和阴影外,该遮罩还用于遮蔽高光和和镜面反射。可以看到,从Smoothstep节点中心分出了三个分支。

镜面高光和画笔效果
视图下方是蓝色方框Specular,我获得了视线和光线方向的半个向量,然后使用该向量来计算镜面的遮罩。在此阶段中,我使用了非常简单的Blinn-Phong着色模型。

我不认为该模型的实现是最完美的,但足以满足演示本项目,该效果取决于光线和视线角度,你也可以自行调整该实现。

然后,我使用这个遮罩来裁剪屏幕空间纹理,创建画笔轻触效果,即上半部分的Paint brush部分;还使用了该遮罩的原本功能,处理头发部分面片形状的镜面效果,即下半部分的Patch部分。为了切换使用这二个功能,我暴露了名为UseSpecularDabs的属性,通过分支节点验证该属性。

014651lipcgqzs0a9n2nrn.png.thumb.jpg
这个部分也是支持镜面贴图的关键部分,可以使金属物品看起来更有光泽,例如:皮肤或木材。

使用边缘效果实现有趣的反差
视图顶部的青色方框Rim highlights,在这里,我使用预制的Fresnel Effect节点,但我仍然使用了光线和视线方向的数量积来过滤该节点,这样做会得到只在对象面向光线时出现的边缘。

当对象背对着阳光或夕阳时,你知道观察此时该对象会得到什么效果吗?

对象会完全被黑暗掩盖。而通过加入该节点,角色会得到彩色的轮廓,即使这样的效果不现实。这是个伪造的效果,但它让角色看起来更有趣。

效果如下图所示。

014651f2ljzollsrbefosf.jpg.thumbFresnel节点连接到了二个Step,这是为什么呢?

下方的Step效果能在黑暗区域出现并重写这些区域,实现前面提到的“夕阳”效果。本示例中,光线没有人为加强,你会得到完全被阳光照射时的颜色。上图中角色身体和脸部轮廓可以看到该效果。

014652ar8n09zw29bnczkw.png.thumb.jpg顶部部分呈现了白色轮廓,可以从特定角度观察到,它只出现在已经受光的区域。所以该部分与表示卡通效果的Smoothstep相乘,所以它不会在黑暗区域呈现。Step函数偏移了0.2,这意味着该效果只会出现在靠近形状边缘的位置,使二个效果可以共存和重叠。

上图中女孩的手套上能清楚地看到该效果,手套几乎是全白色。

Master节点:合并所有节点
视图的剩余部分比较简单,你可以看到不同组件如何合并到着色器的“主干”,用红色表示,它最后会链接到Master节点,即右边的最后一个节点,这部分我只使用了一个技巧。

Shader Graph着色器视图如今支持二种类型的Master节点:PBR和Unlit。理想情况下,Unlit节点很适合卡通着色器,因为我要自己计算颜色。但由于我想要得到阴影,而无光照着色器不会默认获取阴影,所以我不得不使用PBR节点。如果以后Unity加入新的Master节点类型,我可能会修改Master节点类型。

014652jjs5hjjrrffxefjg.png.thumb.jpgPBR Master节点可以带来预制光照模型,适用于逼真的材质。然而,我不需要该模型,我只需要阴影而已。如果使用反照率的话,光线会再乘以已计算的颜色,这不是想要的效果,我想在视图中自行控制颜色。所以我没有使用反照率,我将反照率设为黑色,所以该材质没有得到任何PBR效果。

那么我是如何控制颜色的呢?答案是使用发射。这会带来额外问题:Emission槽需要同时充当反照率、镜面反射、金属度和发射。

发射是最难处理的:我需要计算所有着色器,将发射看作反照率,在最后为顶部添加发射值,不管它是单个值还是纹理,然后缩放它的大小,使不应具有发射效果的部分不被获取,例如:被Bloom屏幕过滤器获取。

实现该平衡的过程很麻烦,而且也不完美,但它让我得到了想要的效果:卡通风格的颜色、发射支持和自阴影。

资源下载
我很满意此次实践得到的结果,我也希望你喜欢该着色器和这篇文章。

我决定不分享视图的ShaderGraph文件,如果我分享了该文件,你会直接将它放到自己的游戏中,这样学不到任何知识。所以我将提供完整大小的着色器视图图片,你可以放大查看图片,了解所有节点和属性的细节。

当你重建该视图的话,你会学习到Shader Graph着色器视图的很多知识,了解这样的效果为什么能够实现。

完整大小的着色器视图图片地址:
https://pan.baidu.com/s/1nLIgow13HxdUzYhFUbovrw

本文中关于Blinn-Phong模型的信息,请访问:
https://paroj.github.io/gltut/Il … nPhong%20Model.html