第十天 Shader编程:编写简单表面着色器 Addressable资源管理系统 DOTS(面向数据技术栈)入门

前言

作为Unity初学者,在实现复杂场景时经常会遇到性能瓶颈。本文将带你通过四个关键技术的实战学习,掌握现代Unity开发的核心优化方案:

  1. Shader编程 - 编写表面着色器控制物体渲染
  2. Addressable系统 - 实现高效资源管理
  3. DOTS技术栈 - 解锁百万级物体渲染能力
  4. 综合实战 - 大规模动态场景优化演示

全程包含可运行的代码示例,所有案例基于Unity 2022.3 LTS版本。


第一部分:Shader编程入门

1.1 表面着色器基础结构

Shader "Custom/SimpleDiffuse" {  Properties {  _MainTex ("Texture", 2D) = "white" {}  _Color ("Color", Color) = (1,1,1,1)  }  SubShader {  Tags { "RenderType"="Opaque" }  CGPROGRAM  #pragma surface surf Lambert  struct Input {  float2 uv_MainTex;  };  sampler2D _MainTex;  fixed4 _Color;  void surf (Input IN, inout SurfaceOutput o) {  fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;  o.Albedo = c.rgb;  o.Alpha = c.a;  }  ENDCG  }  FallBack "Diffuse"  
}  

代码解析

  • #pragma surface surf Lambert 声明表面着色器和使用Lambert光照模型
  • Input结构体定义UV坐标输入
  • surf函数处理表面颜色计算

1.2 扩展高光效果

#pragma surface surf BlinnPhong  // 在SurfaceOutput结构中添加:  
float3 Specular;  
float Gloss;  // 在surf函数中添加:  
o.Specular = _SpecColor.rgb;  
o.Gloss = _Shininess;  

1.3 实战练习

在场景中创建材质球并应用着色器,通过脚本动态修改颜色参数:

public class ShaderController : MonoBehaviour {  [SerializeField] Material targetMaterial;  void Update() {  float hue = Mathf.PingPong(Time.time, 1);  targetMaterial.SetColor("_Color", Color.HSVToRGB(hue, 0.8f, 0.8f));  }  
}  

第二部分:Addressable资源管理

2.1 系统配置流程

  1. 安装Package Manager中的Addressables插件
  2. 创建Addressables Groups管理资源
  3. 设置远程资源加载路径(可选)

2.2 核心API示例

// 异步加载资源  
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Prefabs/Enemy");  
handle.Completed += OnEnemyLoaded;  // 场景加载  
Addressables.LoadSceneAsync("Level2");  // 内存释放  
Addressables.Release(handle);  

2.3 最佳实践

  • 使用Label分类管理资源
  • 结合Content Update构建增量包
  • 通过Analyze工具检测冗余

第三部分:DOTS技术入门

3.1 ECS核心概念

public struct RotationSpeed : IComponentData {  public float RadiansPerSecond;  
}  public class RotationSystem : SystemBase {  protected override void OnUpdate() {  float deltaTime = Time.DeltaTime;  Entities.ForEach((ref Rotation rotation,  in RotationSpeed speed) => {  rotation.Value = math.mul(rotation.Value,  quaternion.AxisAngle(math.up(), speed.RadiansPerSecond * deltaTime));  }).ScheduleParallel();  }  
}  

3.2 Burst编译器加速

[BurstCompile]  
public struct MoveJob : IJobEntity {  public float DeltaTime;  void Execute(ref Translation translation, in MoveSpeed speed) {  translation.Value += new float3(0, 0, speed.Value * DeltaTime);  }  
}  // 在System中调度:  
new MoveJob { DeltaTime = Time.DeltaTime }.ScheduleParallel();  

3.3 Hybrid Renderer配置

  1. 创建Conversion Settings将GameObject转为Entity
  2. 添加RenderMesh组件
  3. 配置LODGroup转换规则

第四部分:综合实战 - 百万物体渲染

4.1 场景搭建步骤

  1. 创建基础Entity预制体
  2. 编写生成器脚本:
public class Spawner : MonoBehaviour {  public GameObject Prefab;  public int Count = 1000000;  void Start() {  var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);  var entityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(Prefab, settings);  var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;  for (int i = 0; i < Count; i++) {  var entity = entityManager.Instantiate(entityPrefab);  var position = new Unity.Mathematics.float3(Random.Range(-50,50), 0, Random.Range(-50,50));  entityManager.SetComponentData(entity, new Translation { Value = position });  }  }  
}  

4.2 性能优化技巧

  • 使用Chunk Component优化内存布局
  • 结合GPU Instancing
  • 配置合适的LOD策略

4.3 性能对比数据

方案10,000物体帧率1,000,000物体帧率
传统GameObject24 FPS崩溃
DOTS+Hybrid60 FPS52 FPS

结语与进阶建议

通过本文的学习,你已经掌握了:

  1. 基础Shader开发能力
  2. 资源生命周期管理方法
  3. DOTS高性能编程范式
  4. 大规模场景优化实战经验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/80259.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目自动化测试

一.设计测试用例(细致全面) 二.先引入所需要的pom.xml依赖 1.selenium依赖 2.webdrivermanager依赖 3.commons-io依赖 编写测试用例–按照页面对用例进行划分,每个页面是Java文件,页面下的所有用例统一管理 三.common包(放入公用包) 类1utils 可以调用driver对象,访问url …

ap无法上线问题定位(交换机发包没有剥掉pvid tag)

一中学&#xff0c;新开的40台appoe交换机核心交换机旁挂ac出口路由的组网&#xff0c;反馈ap无法上线&#xff0c;让协助解决。 组网如下&#xff1a; 排查过程&#xff1a; 检查ac的配置&#xff0c;没有发现问题 发现配置没有问题&#xff0c;vlan1000配置子接口&#xff…

第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项

第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项 赛题 B 卷 第十七届山东省职业院校技能大赛中职组网络建设与运维赛项 1 赛题说明 一、竞赛项目简介 “网络建设与运维”竞赛共分为以下三个模块&#xff1a;  网络理论测试&#xff1b;  网络建设与调试&#xf…

关于QT信号、槽、槽函数的讲解

也是好久没有发帖子了&#xff0c;最近博主主要还是在边学QT边完成任务&#xff0c;所以进度很慢&#xff0c;但确实在这几天对于QT自身槽和信号这类特殊的机制有了一定简单的理解&#xff0c;所以还是想记录下来&#xff0c;如果有初学者看到帖子对他有一定的帮助&#xff0c;…

YOLOv8 涨点新方案:SlideLoss FocalLoss 优化,小目标检测效果炸裂!

YOLOv8优化秘籍&#xff1a;用SlideLoss和FocalLoss提升小目标检测精度&#xff08;附代码实战&#xff09;​​ ​&#x1f4cc; 核心问题&#xff1a;YOLOv8在检测小物体时效果不够好&#xff1f;​​ YOLOv8虽然是强大的目标检测模型&#xff0c;但在处理小物体或类别不平…

基于cubeMX的hal库STM32实现MQ2烟雾浓度检测

一、任务目标 使用STM32F103C8T6单片机&#xff0c;使用单片机AD模块采集MQ2烟雾传感器的数据&#xff0c;在OLED屏显示检测到的AD值、电压值和浓度值&#xff08;ppm单位&#xff09;。 二、实现过程 1、MQ2烟雾传感器的浓度转化方法 &#xff08;1&#xff09;实验所用的M…

Android之AI自动化测试--Midscene

文章目录 前言一、准备工作1.安装2.准备 API Key3.安装 adb4.连接设备 二、yaml格式自动化脚本1. 脚本案例2.执行结果 三、文件结构变化android 部分 前言 字节 Web Infra团队官宣Midscene 从 v0.15 开始支持 Android 自动化测试&#xff0c;本篇文章介绍yaml方式的Android自动…

类的六个默认成员函数

如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的成员函数称为默认…

HarmonyOS Grid 网格列表可长按 item 拖动移动位置

方案一 @Component struct WorkCircleCreatePage {// 存储车控列表的数组@State VehicleDoorArr: IVehicleDoor[] = []// 当前移动的Item索引@State CurrentIndex: number = -1// 拖动时显示的数据@State MoveItem: IVehicleDoor = { title: , icon: }// 拖动时放大倍数@State…

海量数据笔试题--Top K 高频词汇统计

问题描述&#xff1a; 假设你有一个非常大的文本文件&#xff08;例如&#xff0c;100GB&#xff09;&#xff0c;文件内容是按行存储的单词&#xff08;或其他字符串&#xff0c;如 URL、搜索查询词等&#xff09;&#xff0c;单词之间可能由空格或换行符分隔。由于文件巨大&…

【数据结构】Map与Set结构详解

数据结构系列五&#xff1a;Map与Set(一) 一、接口的实现 1.方法上 2.成员上 二、Map的内外双接口结构 1.实现 1.1外部Map接口的实现 1.1.1临摹整体 1.1.2外部类实现整体 1.2内部Entry接口的实现 1.2.1临摹内部 1.2.2内部类实现内部 2.关系 3.意义 3.1逻辑内聚 …

Electron使用WebAssembly实现CRC-32 原理校验

Electron使用WebAssembly实现CRC-32 原理校验 将C/C语言代码&#xff0c;经由WebAssembly编译为库函数&#xff0c;可以在JS语言环境进行调用。这里介绍在Electron工具环境使用WebAssembly调用CRC-32 原理格式校验的方式。 CRC-32 原理校验函数WebAssembly源文件 C语言实现C…

【晶振】晶振的工作原理及其与单片机关系

晶振(晶体振荡器)是电子设备中常见的元件,其核心功能是提供稳定的时钟信号,而单片机(MCU)依赖这一信号来同步内部操作。以下是晶振的工作原理及其与单片机关系的详细说明: 一、晶振的工作原理 压电效应与谐振 晶振的核心是石英晶体,利用其压电效应: 当在晶体两端施加电…

【Oracle专栏】函数中SQL拼接参数 报错处理

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 最近同事反馈了一个很奇怪的问题,即有一个函数,入参是当前年月,主要作用是通过SQL语句将不合规的数据插入到指定表中,插入数据时带上入参的年月参数。当前问题:单独测试SQL没有问题可以执行成功,…

nodejs之Express-介绍、路由

五、Express 1、express 介绍 express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址: https://www.expressjs.com.cn/ 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务) (1)基本使用 第一步:初始化项目并…

Unicode和 ASCII码以及UTF-8编码的区别和联系

Unicode、ASCII 和 UTF-8 是计算机编码领域的关键概念&#xff0c;它们既有联系又有区别。以下是它们的对比分析&#xff1a; 1. ASCII&#xff08;美国信息交换标准码&#xff09; 诞生时间&#xff1a;1967 年&#xff08;7 位编码&#xff0c;共 128 字符&#xff09;。特点…

STM32F103_HAL库+寄存器学习笔记20 - CAN发送中断+ringbuffer + CAN空闲接收中断+接收所有CAN报文+ringbuffer

导言 如上所示&#xff0c;在[[STM32F103_HAL库寄存器学习笔记19 - CAN发送中断CAN接收中断接收所有CAN报文ringbuffer数据结构]]的基础上&#xff0c;为CAN发送端也引入了ringbuffer&#xff08;环形缓冲区&#xff09;机制。CAN发送有三个发送邮箱&#xff0c;为什么还另外需…

Windows 环境下安装 MariaDB 及 HeidiSQL 使用教程

引言 本报告旨在提供一份详尽的操作指南。内容将覆盖在 Windows 操作系统上安装 MariaDB Community Server 的全过程。我们还将探讨如何利用 HeidiSQL 这款图形用户界面&#xff08;GUI&#xff09;工具&#xff0c;直观地预览和管理我们新安装的数据库。除了安装与配置的步骤…

美团2024年春招第一场笔试 C++

目录 1&#xff0c;小美的平衡矩阵 2&#xff0c;小美的数组询问 3&#xff0c;小美的MT 4&#xff0c;小美的朋友关系 1&#xff0c;小美的平衡矩阵 【题目描述】 给定一个n*n的矩阵&#xff0c;该矩阵只包含数字0和1。对于 每个i(1<i<n)&#xff0c;求在该矩阵中&am…

09-DevOps-Jenkins实现CI持续集成

前面已经把harbor搭建好了&#xff0c;也可以向harbor中推送自定义镜像。 原计划是在Jenkins这台服务器上&#xff0c;完成镜像构建&#xff0c;然后把镜像推送的harbor仓库中。现在改变计划了&#xff0c;Jenkins所在的服务器&#xff08;192.168.1.10&#xff09;不负责镜像…