Unity3D

Yoasset学习笔记和踩坑记录

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 安装YooAssets的编辑器和运行时源代码可以直接从Github下面下载,但如果要用到tuyoo公司提供的若干个示例,则还需要配置一下package manager,从Unity的package manager中下载 打开管理界面 【Edit/Project Settings/Package Manager】 // 输入以下内容(中国版) Name: package.openupm.cn URL: https://package.openupm.cn Scope(s): com.tuyoogame.yooasset // 输入以下内容(国际版) Name: package.openupm.com URL: https://package.openupm.com Scope(s): com.tuyoogame.yooasset 什么是unity的scoped registry参见本站网页。 如果碰到有如下的控制台输出: [Package Manager Window] Error searching for packages. Unable to perform online search: Cannot connect to 'package.openupm.cn' (error code: ENOTFOUND). Verify your environment firewall policies allow connection to this host name. If your system is behind a proxy, verify your proxy environment variables (HTTP_PROXY and HTTPS_PROXY) are properly set.

在unity中生成一个guid值

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com Unity中生成GUID的方法 Unity本身提供了便捷的API来生成GUID,同时也兼容C#标准库的GUID生成方式,以下是两种最常用且可靠的方法: 方法1:使用Unity内置的GUID类(推荐) Unity引擎有专门的 UnityEditor.GUID 类(编辑器环境)和 System.Guid 类(运行时/编辑器通用),其中运行时通用的方式兼容性最好: using UnityEngine; public class GuidGenerator : MonoBehaviour { void Start() { // 生成新的GUID System.Guid newGuid = System.Guid.NewGuid(); // 转换为字符串(常用格式,包含连字符) string guidString = newGuid.ToString(); Debug.Log("生成的GUID(带连字符):" + guidString); // 转换为无连字符的字符串(适合存储/传输) string guidNoHyphen = newGuid.ToString("N"); Debug.Log("生成的GUID(无连字符):" + guidNoHyphen); // 转换为Unity编辑器专用的GUID类型(仅编辑器环境可用) #if UNITY_EDITOR UnityEditor.GUID unityGuid = UnityEditor.GUID.Generate(); Debug.Log("Unity编辑器GUID:" + unityGuid.ToString()); #endif } } 方法2:编辑器扩展(批量生成/快捷生成) 如果需要在编辑器面板快速生成GUID,可以写一个简单的编辑器工具: using UnityEditor; using UnityEngine; public class GuidCreatorWindow : EditorWindow { [MenuItem("Tools/生成GUID")] static void OpenWindow() { GuidCreatorWindow window = GetWindow<GuidCreatorWindow>("GUID生成器"); window.

详解Unity3D packmanager的scoped registry

核心概念:一句话概括 Scoped Registry(作用域注册表) 是一个自定义的包服务器地址,你可以告诉 Unity Package Manager:“当我要找某个特定前缀的包时,不要再去 Unity 的官方源找了,请去我指定的这个私人地址找。” 为什么需要 Scoped Registry?(解决的问题) 在 Scoped Registry 出现之前,如果你想使用非 Unity 官方提供的包(比如公司内部的工具包、第三方供应商的插件、或自己团队开发的共享模块),通常有几种麻烦的方式: 直接导入 .unitypackage 文件:难以更新、版本控制混乱、无法清晰地管理依赖。 使用 Git URL:在 Package Manager 里直接链接到 Git 仓库。这虽然可以,但不够规范,并且对私有仓库的权限管理比较麻烦。 手动复制文件:最原始的方法,维护起来是噩梦。 这些方法都不够优雅,也不利于团队协作和持续集成。 Scoped Registry 的诞生就是为了像管理官方包一样,来管理这些“第三方”或“私人”的包。 它让 Package Manager 从一个只能连接 Unity 官方商店的工具,变成了一个可以连接多个包源的、更通用的依赖管理工具。 它是如何工作的? Scoped Registry 基于 npm 的包注册表协议。你配置两个核心信息: 注册表地址:包的服务器地址。例如: 公司内部搭建的 npm registry(如 Verdaccio、Azure Artifacts 等)。 第三方服务提供的地址(如 OpenUPM 的注册表)。 作用域:一个或多个包名的前缀。它用来“过滤”或“限定”这个注册表负责哪些包。 工作流程示例: 假设你的公司叫 “AwesomeStudio”,你们将所有内部工具包的名字都命名为 com.awesomestudio.xxx。 配置 Scoped Registry: 名称: AwesomeStudio Internal URL: https://packages.awesomestudio.com 作用域: com.

一篇文章说透计算着色器的SV_DispatchThreadID

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com SV_DispatchThreadID 是HLSL(High-Level Shading Language)中的一个语义(Semantic),用于在Compute Shader中获取当前线程的全局线程ID。它是Compute Shader中非常重要的一个概念,用于确定每个线程处理的数据或任务。 SV_DispatchThreadID 的含义 全局线程ID: SV_DispatchThreadID 是一个 uint3 类型的变量,表示当前线程在全局线程空间中的ID。 它的三个分量(x、y、z)分别表示线程在X、Y、Z三个维度上的全局索引。 线程的全局位置: SV_DispatchThreadID 的值范围由程序语言层(例如C#) 的Dispatch 调用,和HLSL语言中的 numthreads 语句定义。 例如,如果调度了 Dispatch(10, 20, 30),并且 numthreads 是 [8, 8, 1],那么: SV_DispatchThreadID.x 的范围是 [0, 10*8-1](即 [0, 79])。 SV_DispatchThreadID.y 的范围是 [0, 20*8-1](即 [0, 159])。 SV_DispatchThreadID.z 的范围是 [0, 30*1-1](即 [0, 29])。 用途: SV_DispatchThreadID 通常用于确定当前线程处理的数据索引。 例如,在处理2D纹理时,SV_DispatchThreadID.xy 可以直接用作纹理坐标。 在处理1D数组时,SV_DispatchThreadID.x 可以直接用作数组索引。 SV_DispatchThreadID 的计算方式 SV_DispatchThreadID 的值是由以下两个因素决定的: 线程组的大小(由 numthreads 定义): 例如,[numthreads(8, 8, 1)] 表示每个线程组有 8x8x1 = 64 个线程。即是说,numthread语句,是声明“线程”的。 线程组的数量(由 Dispatch 调用定义):

使用mipmap streaming来优化GPU的纹理内存

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 本文所涉及到的API和Unity3D编辑器都是基于6000.0.25f1c1版本 1 mipmap streaming 简介 使用 mipmap 流来限制 GPU 内存中纹理的大小。 1.1 mipmap streaming的工作原理 对于每个被摄像机观察到的纹理,Unity会自动计算并加载其特定级别的mipmap,而不是加载所有级别。这意味着 Unity 只会将每个纹理的指定mipmap level的内容从磁盘传输到 CPU 和 GPU。 Unity 会以尽可能高的分辨率加载 mipmap level,但如果较高分辨率的 mipmap level不符合您设置的内存限制,则使用较低的 mipmap level。mipmap可预配置 Unity 在 GPU 上缓存指定mipmap level的纹理内容,以避免重复加载。 1.2 mipmap streaming的限制 Unity不支持对地形纹理使用mipmap streaming,因为 Unity 始终需要最高分辨率的 mipmap level。 Unity不支持对纹理数组、cubemap,3D纹理使用mipmap streaming。 如果使用Graphics.DrawMeshNow等 API来渲染纹理,Unity 将无法获得计算 mipmap level所需的信息。使用Texture2D.requestedMipmapLevel API 手动设置纹理的 mipmap level,或者禁用mipmap streaming。 如果纹理有tiling和offset属性,但又没指定使用_ST属性,Unity可能无法正确计算这种纹理的mipmap level。 2 启用 mipmap streaming 要启用 mipmap streaming,按照以下步骤操作: 点击【Edit|Project Settings】菜单项,弹出【Project Settings】面板,选中【Quality】项 在【Texture】部分中,启用【Mipmap Streaming】 在默认情况下,这时候为场景中的所有摄像机都打开了mipmap streaming。在编辑器中,mipmap streaming在edit mode或者play mode下都处于开启状态。

一段根据片元深度值重建对应的深度坐标值的代码及其解释

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com // 从深度信息重建世界空间坐标 // 参数: // screenPos - 屏幕空间坐标(通常来自顶点着色器的SV_Position) // viewDir - 视图空间方向向量 // sceneDepth - 包含原始深度和线性深度值的结构体 float3 ReconstructWorldPosition(float4 screenPos, float3 viewDir, SceneDepth sceneDepth) { // 平台深度缓冲处理 ---------------------------------------- #if UNITY_REVERSED_Z // 处理Reversed-Z平台(如DirectX) real rawDepth = sceneDepth.raw; // 直接使用原始深度值 #else // OpenGL等常规深度缓冲平台 // 将深度值从[0,1]映射到[Near,1],适配OpenGL的NDC范围 real rawDepth = lerp(UNITY_NEAR_CLIP_VALUE, 1, sceneDepth.raw); #endif // 正交投影处理 -------------------------------------------- #if defined(ORTHOGRAPHIC_SUPPORT) // 将屏幕坐标转换为NDC空间(-1到1范围) float4 viewPos = float4( (screenPos.xy / screenPos.w) * 2.0 - 1.0, // 透视除法后映射到NDC rawDepth, // 深度值 1.

一段计算场景深度与当前透明几何像素的线性深度差的代码及其解释

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com // 计算场景深度与当前透明几何像素的线性深度差 // 参数: // depth - 包含场景深度信息的结构体(包含原始深度和线性眼空间深度) // positionCS - 当前像素在裁剪空间中的位置坐标(SV_Position) float SurfaceDepth(SceneDepth depth, float4 positionCS) { // ===================== 场景深度计算 ===================== // 根据投影模式选择计算方式: // unity_OrthoParams.w: 0=透视投影 | 1=正交投影 const float sceneDepth = (unity_OrthoParams.w == 0) ? depth.eye // 透视模式:直接使用预计算的线性眼空间深度 : LinearDepthToEyeDepth(depth.raw); // 正交模式:将原始深度转换到眼空间 // ================= 当前像素深度计算 ==================== const float clipSpaceDepth = (unity_OrthoParams.w == 0) ? LinearEyeDepth(positionCS.z, _ZBufferParams) // 透视模式:裁剪空间z转线性眼深度 : LinearDepthToEyeDepth(positionCS.z / positionCS.w); // 正交模式:NDC z转眼空间深度 // ================ 深度差异计算结果 ===================== return sceneDepth - clipSpaceDepth; // 返回场景深度与当前像素深度的差值 } 首先,函数内部有两个const float变量,sceneDepth和clipSpaceDepth,然后返回它们的差值。我需要理解这两个变量是如何计算的,特别是条件判断部分unity_OrthoParams.

Unity3D的内置宏 DYNAMICLIGHTMAP_ON

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 在Unity中,DYNAMICLIGHTMAP_ON 是一个与 动态光照贴图(Dynamic Lightmaps) 相关的内置变体关键字(Shader Variant Keyword)。它的核心作用是 控制着色器是否处理动态光照贴图数据,主要用于实现动态物体的间接光照混合效果。 核心含义 动态光照贴图标识 当该宏被激活时(#if defined(DYNAMICLIGHTMAP_ON)),表示当前渲染的物体 启用了动态光照贴图,需要在着色器中采样动态光照贴图数据。 若未激活,则物体仅使用静态光照贴图或实时光照。 技术目的 允许动态物体(如可移动的物件)与烘焙的静态场景光照进行间接光交互。 结合 Enlighten 或 Progressive Lightmapper 系统,实现动态物体的间接光实时更新。 触发条件 该宏在以下情况下自动激活: 物体设置 物体的 Mesh Renderer 组件中勾选 Lightmap Static 为 Contribute GI,同时设置 Lightmap Parameters 为支持动态更新。 光照系统配置 项目中启用了 Realtime Global Illumination(实时全局光照)。 使用 Baked Indirect 或 Shadowmask 混合光照模式。 Shader编译指令 在Shader中通过 #pragma multi_compile 或 #pragma shader_feature 声明动态光照贴图支持: #pragma multi_compile __ DYNAMICLIGHTMAP_ON 技术实现机制 1. 数据传递 动态光照贴图信息通过以下方式传递到着色器: 顶点数据:动态光照贴图坐标通过 TEXCOORD2 传递。 Uniform变量:动态光照贴图纹理(unity_DynamicLightmap)和采样器(samplerunity_DynamicLightmap)。 2. 着色器代码示例 struct v2f { float2 uv : TEXCOORD0; #if defined(LIGHTMAP_ON) float2 lightmapUV : TEXCOORD1; // 静态光照贴图UV #endif #if defined(DYNAMICLIGHTMAP_ON) float2 dynamicLightmapUV : TEXCOORD2; // 动态光照贴图UV #endif }; half3 GetLightmapColor(v2f i) { half3 staticGI = 0; half3 dynamicGI = 0; #if defined(LIGHTMAP_ON) staticGI = SampleLightmap(unity_Lightmap, samplerunity_Lightmap, i.

Unity3D的内置宏 REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 在Unity URP中,REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR 是一个与阴影计算相关的内置宏(Shader Variant Keyword),它的作用是: 核心含义 控制顶点着色器是否需要生成并传递阴影坐标插值器 当该宏被激活时,Unity会在顶点着色器阶段计算主光源的阴影坐标,并通过顶点着色器输出结构体(Varyings)传递到片元着色器。这使得片元着色器可以直接使用插值后的阴影坐标进行阴影采样,避免在片元阶段重复计算。 触发条件 该宏会自动激活,当以下条件满足时: 项目中启用了 主光源阴影(Main Light Shadows) 使用了 逐顶点阴影坐标插值 的优化模式(而非逐片元计算) 在Shader中通过 #pragma multi_compile 启用了阴影相关功能(例如 _MAIN_LIGHT_SHADOWS) 典型应用场景 在URP的Shader中,你会在顶点着色器输出结构体 Varyings 中看到类似代码: struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; // 当 REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR 激活时,自动添加阴影坐标字段 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) float4 shadowCoord : TEXCOORD1; #endif }; 技术原理 阴影坐标生成 顶点着色器通过 GetShadowCoord(vertexInput) 计算阴影坐标,并存储在 shadowCoord 中。 插值优化 阴影坐标在顶点阶段计算后,通过插值器传递到片元着色器,减少片元阶段的计算量。 自动编译控制 Unity会根据项目设置和Shader特性,在编译时自动决定是否启用该宏,生成不同的Shader变体。 对比其他阴影模式 宏名称 计算阶段 性能消耗 精度 REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR 顶点着色器 较低 中等 REQUIRES_FRAGMENT_SHADOW_COORD_INTERPOLATOR 片元着色器 较高 较高 调试与手动控制 强制启用/禁用(不推荐)

Unity3D的内置宏 _LIGHT_LAYERS

Unity3D的内置宏 ADDITIONAL_LIGHTS_VERTEX 请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 在Unity URP/HDRP中,_LIGHT_LAYERS 是一个与 光源层级过滤(Light Layer Masking) 相关的内置变体关键字(Shader Variant Keyword)。它的核心作用是 实现基于层级的光源与物体交互控制,允许开发者通过层掩码(Layer Masks)精确控制哪些光源可以影响特定物体。 核心含义 1. 功能定位 光源筛选机制:激活该宏后,物体会根据自身的 Light Layer Mask 和光源的 Light Layer Mask 进行匹配,只有匹配层的光源才会对该物体产生光照影响。 渲染优化:通过层级过滤减少无效光源计算,提升复杂场景性能。 2. 技术目标 精细化光源控制:例如让装饰性灯光只影响场景道具,不影响角色 多世界渲染支持:用于分屏游戏或VR中不同视角的独立光照逻辑 触发条件 该宏的激活需要同时满足以下条件: 项目设置启用 URP/HDRP Asset 中开启光源层支持: URP: Lighting > Light Layers > Enable Light Layers HDRP: Lighting > Light Layers Shader声明 在着色器中通过#pragma指令声明支持: #pragma multi_compile _ _LIGHT_LAYERS 光源与物体配置 光源的 Light Layer Mask 设置为非"Everything"值 物体的 Renderer组件 > Rendering Layer Mask 设置为与光源匹配的层级 技术实现机制 1.