type
status
date
slug
summary
tags
category
icon
password
fullWidth
fullWidth
Unity的VideoPlayer在编辑时指定到某帧
问题描述
做舞蹈视频时需要将歌曲PV视频作为背景板,在编辑时希望视频停留在某一帧(为了好看!),然而,VideoPlayer组件的Inspector面板没有直接提供设置帧属性的选项。
主要原因
- 帧是运行时状态值,而非配置参数,Inspector面板主要用于编辑静态配置属性(如视频路径、播放速度等)。
- 设置帧需要视频已加载并解码(
isPrepared == true
),在编辑模式下,视频资源可能尚未加载。
- 跳转到特定帧需要解码前面的所有帧,在编辑器频繁更新会卡顿。
解决方法
扩展VideoPlayer的Inspector面板,增加编辑时跳转到指定帧的功能;把这个脚本放在Assets/Editor文件目录,会自动应用于场景中所有的VideoPlayer组件。
使用效果
.gif?t=1da92264-0ce5-8064-a300-f1b82c918879)
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脚本,作用是:
- 动态创建
RenderTexture
,保存渲染中间数据。
- 通过
CommandBuffer
在特定时机(如CameraEvent.BeforeForwardOpaque
)插入到渲染流程。
- 传递RT数据给Shader的属性。
针对角色有多个
MeshRenderer
,且每个Renderer有多个Material
的情况,需要遍历每个Material
并在DrawRenderer
命令中指定submeshId
。在
OnRenderImage
中可将中间结果的RenderTexture
输出到窗口进行调试查看。编辑器扩展脚本
由于将
CommandBuffer
插入到流程中一般在OnEnable
中进行(因为OnEnable
是最早的可控初始化点之一,且可配合OnDisable
清理旧CommandBuffer
和RenderTexture
以避免内存泄漏),修改了Shader的属性后需要重新激活脚本才能生效,可创建一个编辑器扩展脚本,用于点击按钮刷新渲染。实现效果
亮部Mask输出测试


ShadowThreshold = 0.8

叠加渲染效果



.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_Start
、Attack_Loop
、Attack_End
)。
- 事件系统:
- 通知(Notifies):在特定帧触发事件(如播放音效、生成伤害判定框)。
- 插槽(Slots):支持动画分层(如上半身攻击 + 下半身跑步)。


- 动态混合:可设置
Blend In/Out
时间,平滑过渡蒙太奇。
区别对比
特性 | 动画序列(Sequence) | 蒙太奇(Montage) |
组成 | 单一动画片段 | 多个动画序列+分段+事件 |
逻辑控制 | 无 | 支持分段、事件、插槽 |
播放方式 | 直接循环播放 | 动态触发、可跳跃至指定分段 |
动画混合 | 依赖外部节点(如 Blend Space) | 内置Blend In/Out和插槽混合 |
典型用途 | 基础动作(走、跑、跳) | 复杂交互(攻击、受击、交互) |
使用场景
- 用动画序列:
- 需要简单循环动画(如移动、待机)。
- 作为混合空间或状态机的输入源。
- 用蒙太奇:
- 需要触发事件(如攻击判定、音效)。
- 实现动画分段控制(如连招系统)。
- 处理动画分层(上半身/下半身独立控制)。
- Author:Yuki
- URL:http://shirakoko.xyz/article/study-note
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts