type
status
date
slug
summary
tags
category
icon
password
fullWidth
fullWidth

Unity的VideoPlayer在编辑时指定到某帧

问题描述

做舞蹈视频时需要将歌曲PV视频作为背景板,在编辑时希望视频停留在某一帧(为了好看!),然而,VideoPlayer组件的Inspector面板没有直接提供设置属性的选项。

主要原因

  • 帧是运行时状态值,而非配置参数,Inspector面板主要用于编辑静态配置属性(如视频路径、播放速度等)。
  • 设置帧需要视频已加载并解码(isPrepared == true),在编辑模式下,视频资源可能尚未加载。
  • 跳转到特定帧需要解码前面的所有帧,在编辑器频繁更新会卡顿。

解决方法

扩展VideoPlayer的Inspector面板,增加编辑时跳转到指定帧的功能;把这个脚本放在Assets/Editor文件目录,会自动应用于场景中所有的VideoPlayer组件。

使用效果

notion image

Unity内置管线保存渲染中间结果到RenderTexture

问题描述

在内置管线的卡通渲染中,有一步屏幕后处理效果为“暗部晕染”,需要拿到卡通渲染ForwardPass通道中根据diffuse值计算出来的暗部遮罩,模糊后叠入原暗部;也即在对diffuseColor色阶离散化之前的计算结果要预存下来,为后处理的Pass通道所用。
💡
内置管线的限制
  • Pass之间无法共享数据:内置管线的Pass是独立执行的,Pass 0的SV_Target输出(如Diffuse值)无法直接传递给Pass 1。
  • 无法动态插入渲染步骤:内置管线没有可编程的渲染管线逻辑,无法在运行时插入自定义的渲染操作(如先渲染Diffuse到 RT,再使用RT做后续计算)。
  • 缺少原生的Multi-Pass数据传递机制:Built-in 管线没有类似URP的_CameraColorTexture或HDRP的Render Graph资源管理,无法自动保存中间结果(如Diffuse值)。

解决方法

RenderTexture作为显式的数据中转站:手动创建RT,用CommandBuffer渲染到RT,再传给后续Pass。

使用案例

多Pass的Shader

这是一个卡渲Shader,包含Diffuse值计算、主渲染和描边三个Pass;其中Diffuse值计算Pass的输出结果需要保存到RenderTexture

挂在摄像机上的Csharp脚本

创建一个挂在摄像机上的Csharp脚本,作用是:
  1. 动态创建RenderTexture,保存渲染中间数据。
  1. 通过CommandBuffer在特定时机(如CameraEvent.BeforeForwardOpaque)插入到渲染流程。
  1. 传递RT数据给Shader的属性。
💡
针对角色有多个MeshRenderer,且每个Renderer有多个Material的情况,需要遍历每个Material并在DrawRenderer命令中指定submeshId
OnRenderImage中可将中间结果的RenderTexture输出到窗口进行调试查看。

编辑器扩展脚本

由于将CommandBuffer插入到流程中一般在OnEnable中进行(因为OnEnable是最早的可控初始化点之一,且可配合OnDisable清理旧CommandBufferRenderTexture以避免内存泄漏),修改了Shader的属性后需要重新激活脚本才能生效,可创建一个编辑器扩展脚本,用于点击按钮刷新渲染。

实现效果

亮部Mask输出测试

ShadowThreshold = 0.2
ShadowThreshold = 0.2
notion image
ShadowThreshold = 0.8
调节ShadowThreshold
调节ShadowThreshold

叠加渲染效果

ShadowThreshold = 0.2
ShadowThreshold = 0.2
ShadowThreshold = 0.8
ShadowThreshold = 0.8
调节ShadowThreshold
调节ShadowThreshold

.gitignore文件的使用方法

.gitignore 文件用于指定Git版本控制中需要忽略的文件或目录。
  • gitignore对已跟踪的文件无效(需先执行git rm --cached <file>)。
  • 可配置全局规则:git config --global core.excludesfile ~/.gitignore_global
  • 每行一个规则,空行和注释不影响规则。
以下是一些常用语法规则和示例:

1. 基本规则

  • 忽略特定文件
    • 直接写文件名(含扩展名):
  • 忽略特定目录
    • 以 / 结尾表示目录:

2. 通配符

  • *:匹配任意字符(除了 /
    • ?:匹配单个字符
      • **:匹配任意层级的目录

        3. 路径规则

        • 相对路径
          • 相对于 .gitignore 文件所在目录:
        • 绝对路径(不推荐)
          • 从项目根目录开始:

        4. 排除规则(!)

        • 用 ! 取消忽略(例外规则):

          6. 其他规则

          • 忽略空格
            • 行尾的空格会被忽略,除非用 \ 转义:
          • 字符范围
            • 用 [] 匹配指定字符:

          C++循环引用的解决方法

          在C++开发中,特别是开发虚幻项目时,循环引用是一个常见问题,有几种解决方法:

          前向声明

          先在头文件中用关键字class前向声明类,让编译器知道类存在而不需要知道其完整定义。
          再在源文件中引入完整头文件。

          使用接口

          如果两个类之间有明确的交互方式,可以定义一个接口IGridGeneratorInterface
          然后让GridGenerator实现这个接口,MineCube只需要引用接口头文件。

          使用弱引用

          使用TWeakObjectPtr来避免强引用。

          UE中动画序列(Animation Sequence)和蒙太奇(Montage)的区别

          这是个UE客户端面试常见问题,仅做记录。动画序列(Animation Sequence)蒙太奇(AnimMontage) 是两种核心动画资源,但它们的用途和功能有显著区别:

          动画序列

          动画序列是单一的、连续的动画片段(如角色行走、跳跃、攻击动作),本质是原始动画数据(逐帧的骨骼变换信息),通常从3D软件导出。
          • 无逻辑控制:仅包含动画数据,无法直接处理事件、分支或混合。
          • 直接播放:通过动画蓝图的Play Animation节点直接播放。

          蒙太奇

          蒙太奇是动画复合体,可包含多个动画序列、逻辑分段和事件;本质是 动画的“容器”,用于复杂交互(如攻击连招、受击反应)。
          • 分段控制:将动画序列拆分为逻辑块(如Attack_StartAttack_LoopAttack_End)。
          • 事件系统
            • 通知(Notifies):在特定帧触发事件(如播放音效、生成伤害判定框)。
            • notion image
            • 插槽(Slots):支持动画分层(如上半身攻击 + 下半身跑步)。
            • notion image
          • 动态混合:可设置Blend In/Out 时间,平滑过渡蒙太奇。

          区别对比

          特性
          动画序列(Sequence)
          蒙太奇(Montage)
          组成
          单一动画片段
          多个动画序列+分段+事件
          逻辑控制
          支持分段、事件、插槽
          播放方式
          直接循环播放
          动态触发、可跳跃至指定分段
          动画混合
          依赖外部节点(如 Blend Space)
          内置Blend In/Out和插槽混合
          典型用途
          基础动作(走、跑、跳)
          复杂交互(攻击、受击、交互)

          使用场景

          • 用动画序列
            • 需要简单循环动画(如移动、待机)。
            • 作为混合空间状态机的输入源。
          • 用蒙太奇
            • 需要触发事件(如攻击判定、音效)。
            • 实现动画分段控制(如连招系统)。
            • 处理动画分层(上半身/下半身独立控制)。
           
          工作笔记:一些乱七八糟的踩坑记录同人插画存档
          Loading...
          Latest posts
          捣鼓记录:NotionNext+Vercel搭建自定义域名的博客流程
          2025-7-3
          捣鼓记录:创建Unity工程的Git仓库步骤和注意事项
          2025-7-3
          自制Python任务调度模块-MySchedule
          2025-7-3
          自卷笔记:一些乱七八糟的踩坑记录和小知识小技巧
          2025-7-3
          工作笔记:一些乱七八糟的踩坑记录
          2025-6-25
          游戏AI行为决策-行为树(BehaviorTree)框架搭建与应用
          2025-6-14