About

记录和分享

FPSSample分析

在FPSSample项目之前Unity官方出的示例都只是展示某一项技术,没有真正完整的大型项目。要做出真正易用的引擎,引擎开发商要使用自己的引擎做实际的项目,然后根据开发体验改进引擎,这样才会不断提高引擎的易用性,厨师要吃自己做的菜才能成为好厨师。很高兴看到Unity官方能做出FPSSample这样的项目,这代表了Unity态度的转变,事情在往好的方向发展。 FPSSample的Github地址是https://github.com/Unity-Technologies/FPSSample,这是一个包括了服务器和客户端的多人射击游戏,这篇文章主要分析资源管理,网络传输和同步。 总体分析 在阅读代码前需要先了解一下ECS,可以参考这个教程。项目里所用到的ECS知识点较为简单,这里简单介绍一下。ECS是一种以数据为中心的编程范式,它分离了数据和行为,包含三个要素:实体(Entity),组件(Component)和系统(System),其中Entity是用来引用Component的,Component只包含了纯数据,System首先过滤要操作的Component然后定义行为。下面举例说明项目中怎么使用ECS的。 // Component需要是struct,并且实现IComponentData接口 public struct Foo : IComponentData { public int value; } public struct Bar : IComponentData { public int value; } // Entity的创建和组件添加 // Entity e = entityManager.CreateEntity(); // entityManager.AddComponentData(e, new Foo{value = 0}); // entityManager.AddComponentData(e, new Bar{value = 1}); // entityManager.SetComponentData(e, new Bar{value = 100}); // Unity提供了ComponentSystem和用于多线程的JobComponentSystem, // 目前项目没有用到JobComponentSystem public class FoobarSystem : ComponentSystem { ComponentGroup group; // 通过注入的方式指定过滤的Component // public struct GroupType // { // public readonly int Length; // public ComponentDataArray<Foo> Foo; // public ComponentDataArray<Bar> Bar; // } // [Inject] GroupType group; protected override void OnCreateManager(int capacity) { base....

May 3, 2022 · 10 min · 老王

MaterialPropertyBlock对性能的影响

对使用相同材质的物体设置不同的材质属性是一个常见的需求,可以使用Render.material生成一个新的材质并设置属性,这需要更多内存,并且会破坏可能的batching,所以要尽量避免使用。另一种方法是用Render.SetPropertyBlock(MaterialPropertyBlock properties)设置属性,接下来就分析这种做法对batching的影响。 首先建立一个测试工程,新建一个场景,场景中添加4个默认cube,为每个cube挂载下面的脚本 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class SetMaterialProperty : MonoBehaviour, IPointerDownHandler { int index; Renderer renderer; MaterialPropertyBlock propertyBlock; void Awake() { renderer = GetComponent<Renderer> (); propertyBlock = new MaterialPropertyBlock (); renderer.GetPropertyBlock (propertyBlock); } public void NextColorProperty() { switch (index) { case 0: propertyBlock.SetColor ("_Color", Color.red); break; case 1: propertyBlock.SetColor ("_Color", Color.green); break; case 2: propertyBlock.SetColor ("_Color", Color.yellow); break; } renderer.SetPropertyBlock (propertyBlock); index = ++index%3; } #region IPointerDownHandler implementation public void OnPointerDown (PointerEventData eventData) { NextColorProperty (); } #endregion } 运行测试场景,并打开Frame Debugger,结果如下: Frame Debugger中选中的部分就是渲染4个cube所需的draw call,可以看出unity一次渲染这四个cube。然后通过MaterialPropertyBlock设置其中一个cube的_Color属性,再次观察Frame Debugger,结果如下: 可以看出Unity需要两次draw call来渲染这四个cube,一次动态批处理,一次是设置了_Color属性的cube。红框部分说明了设置不同的MaterialPropertyBlock会破坏batching,这句话隐含的意思是使用相同的属性cube会合并一起渲染,接下来测试一下这种情况: 可以看出使用了相同属性的cube被动态批处理了,也就说通过MaterialPropertyBlock设置的属性相同时不会破坏批处理,对于不同属性相同mesh的物体可以使用GPU Instancing减少draw call。...

May 3, 2022 · 1 min · 老王