Skip to content

Commit f549083

Browse files
committed
update notes
1 parent c85883a commit f549083

File tree

3 files changed

+60
-25
lines changed

3 files changed

+60
-25
lines changed

_posts/UE/Animation/2024-11-27 Animation in Unreal.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,6 @@ struct FReferenceSkeleton
6666
TArray<FTransform> FinalRefBonePose;
6767
}
6868
```
69-
#### Slot Groups
70-
```c++
71-
// serialized slot groups and slot names.
72-
UPROPERTY()
73-
TArray<FAnimSlotGroup> SlotGroups;
74-
75-
/** SlotName to GroupName TMap, only at runtime, not serialized. **/
76-
TMap<FName, FName> SlotToGroupNameMap;
77-
```
78-
感觉是用来对动画做分类的,在第三人称模板中有两个 slot group,default group 和 additive group,然后例如 default group 中又包含 default slot,full body,upper body 等等 slot
7969
#### Socket
8070
```c++
8171
void USkinnedMeshComponent::QuerySupportedSockets(TArray<FComponentSocketDescription>& OutSockets);
@@ -107,7 +97,6 @@ FVector RelativeScale;
10797
FTransform USkinnedMeshComponent::GetSocketTransform(FName InSocketName, ERelativeTransformSpace TransformSpace);
10898
```
10999
TODO:virtual bone?
110-
TODO:bone proxy?在 animation sequence editor 中可以查看动画中每帧中每个 bone 的 local transform 和 reference transform 以及 mesh relative transform,local transform 就是相对父节点的 transform,reference transform 就是标准位姿下这个 bone 的 transform,那 mesh relative transform 是个啥玩意, 在 content example 的 示例中,有 root motion 的动画里 root 的 mesh relative transform 在持续变化
111100
### Skeletal Mesh
112101
对应 `USkeletalMesh` 类,它包含一个指向 skeleton 的指针,表示这个 mesh 对应的 skeleton
113102
```c++
@@ -160,17 +149,6 @@ TODO:animation blueprint 中的 slot node 的 `Always Update Source Pose` 选
160149
#### Slot
161150

162151
### Animation Blending
163-
blending 时动画会正常播放(不论是正在 blend in 还是 blend out 的动画)
164-
TODO:那比如在一个动画播到一半时开始插入 montage,这样一个动画的中间部分和一个动画的开始部分进行 blend 如何对齐呢?
165-
#### Blending Node
166-
TODO:文档 [Blend Nodes](https://dev.epicgames.com/documentation/en-us/unreal-engine/animation-blueprint-blend-nodes-in-unreal-engine?application_version=5.4) 中介绍了 animation blueprint 中可以使用的各种 blend 模式
167-
168-
相比对最终的顶点进行 blending,显然逐关节的变换进行 blending 更合适,这样过渡会更加自然
169-
TODO:apply additive 节点和 apply mesh space additive 节点,这个加法要怎么做呢,[ozz-animation samples](https://guillaumeblanc.github.io/ozz-animation/samples/) 中有做 additive animation 的例子,很有必要看看。另外 mesh space vs local space,看起来 local space 其实就是 bone space,而 mesh space 就是 model space,apply additive 和 apply mesh space additive 分别适用于 local space additive animation 和 mesh space animation,类似地 layered blend per bone 而也有 Mesh Space Rotation Blend 和 Mesh Space Scale Blend 选项,我尤其关心计算细节,需要看看源码,用公式把这个 blending 表示出来
170-
* 我实际试了一个例子,在三人称模板中用 layered blend per bone 混合 base pose 为 idle 的第 0 帧和 base pose 0 为 run fwd 第 0 帧,感觉开启 Mesh Space Rotation Blend 选项后的结果更符合预期。应该说,开启该选项后,混合后的结果更贴近单纯 run fwd 输出的结果。我目前的解释是因为 Mesh Space 的混合会考虑父节点的效果。例如我设置从关节 spine_02 开始混合,如果为 local space 的混合,那么在 spine_02 处混合后,最终 spine_02 的关节的矩阵应该还有乘以父节点等等的旋转结果,但是由于是从 spine_02 开始混合的,它以上的变换完全丢失了,因此最终看到的结果差异很大,但如果是 mesh space 的混合,是先算出 spine_02 在 mesh space 下的变换矩阵再进行混合,由于这个变换矩阵已经考虑过 spine_01 这些父关节的变换了,因此得到了一个与原来的位姿更接近的结果
171-
* 但上面的理解无法解释为什么我开启 Mesh Space Rotation Blend 后,将 blend 的关节从 spine_02 下调到 spine_03 后,动画中人物手的位置发生了移动。因为根据上面的理解,节点的 mesh space 变换矩阵不依赖于设置的混合的位置才对。我现在的理解是 手是只发生了移动,即只有 translation 变了,但 rotation 没有变,因此没有矛盾的地方,也许这里还需要细看源码,关注 translation 是怎么算的(动画蓝图中的一个 pose 对应到 C++ 代码是怎么样的
172-
* 另外一个问题,我将 layered blend per bone 中的 bone 设置为 root,且 blend pose 0 的权重设置为 1,得到的结果就和 blend pose 0 完全一样了。这个应该还好理解,这说明它就是做一个纯粹的 blend,而不是 additive 那种,所以权重设置为 1 就表示完全地使用 blend pose 0 的结果
173-
* layered blend per bone 的 Curve Blend Option 选项是怎么用的
174152
#### Blending Space
175153
TODO:理解 2D blending space
176154
TODO:文档 [Blend Spaces in Animation Blueprints](https://dev.epicgames.com/documentation/en-us/unreal-engine/blend-spaces-in-animation-blueprints-in-unreal-engine?application_version=5.4) 中谈到的 blend space graph 是个什么玩意

_posts/UE/Animation/2025-05-15-Sync Group in Unreal.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,29 @@ TODO:结合 [Sync Groups](https://dev.epicgames.com/documentation/en-us/unreal
145145
### Blend Space 中的同步标记
146146
TODO:解释 Blend Space 是如何利用同步标记的,可以看看 [UE4动画系统之同步组源码浅析](https://zhuanlan.zhihu.com/p/651145624)
147147
### Montage 中的同步标记
148-
TODO:解释 montage 中如何使用同步标记
148+
`UAnimMontage` 中设置 `SyncGroup``SyncSlotIndex` 表明这个 montage 的 sync group,以及应该在哪个 slot track 上搜集 marker
149+
```c++
150+
/** If you're using marker based sync for this montage, make sure to add sync group name. For now we only support one group */
151+
UPROPERTY(EditAnywhere, Category = SyncGroup)
152+
FName SyncGroup;
153+
154+
/** Index of the slot track used for collecting sync markers */
155+
UPROPERTY(EditAnywhere, Category = SyncGroup)
156+
int32 SyncSlotIndex;
157+
158+
UPROPERTY()
159+
struct FMarkerSyncData MarkerData;
160+
```
161+
`UAnimMontage::CollectMarkers` 负责实际地收集 marker,存放在 `MarkerData` 中。搜集的方法也很简单,就是这个 slot track 上按时间顺序出现的 `FAnimSegment` 对应的 animation asset 的时间轴上的 marker
162+
163+
然后在 `FAnimMontageInstance::Advance` 正常步进,当 montage 处于淡出状态时,才会搜集步进过程中跨越的 marker(由于用户可以任意设置 section 的连接顺序,步进的过程和时间轴上 `FAnimSegment` 的先后顺序可能不一样),在 `UAnimInstance::UpdateMontageSyncGroup` 中将 montage 当前的播放状态作为一个 `FAnimTickRecord` 加入到对应的 sync group 中。这些都是在 game thread 上完成的
164+
165+
然后 `UAnimMontage` 重载了 `TickAssetPlayer` 函数,因为之前已经在 game thread 上步进过了,因此重载后的函数只需要设置在该 montage 是 leader 时设置 `FAnimAssetTickContext` 的各项数据即可
166+
167+
TODO:由于 section 导致 montage 的播放顺序和时间轴上 `FAnimSegment` 的先后顺序可能不太一样,而且 montage 标记 `PreviousTime` 和 `CurrentTime` 是用的时间轴上的时间,而不是实际的播放时间,因此我感觉在用 sync group 且不用 sync marker,并且设置跳跃连接的 section 时会导致 follower 跳跃的情况....
168+
169+
Notes:`UAnimInstance` 提供的 `MontageSync_Follow` 函数是用来让多个 montage 同步播放的(在淡入和正常播放时有效,开始淡出时就无效了,因此它的作用和 sync group 没有关系)
170+
149171
150-
TODO:blending in,blending out 时动画混合的行为,混合时动画还会向前播吗
151172
152173
TODO:解释 transition leader 和 transition follower 的作用

_posts/UE/Network/2025-06-04 Network2 in Unreal.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,40 @@ TODO:解释服务器上的 UNetConnection 的 `OwningActor`,梳理 actor rep
1313
参考
1414
* [UE4之宏与预编译指令定义](https://www.cnblogs.com/kekec/p/18208393 "发布于 2024-05-25 16:53")
1515
* [What’s the difference between UE_SERVER and WITH_SERVER_CODE](https://forums.unrealengine.com/t/whats-the-difference-between-ue-server-and-with-server-code/124652)
16-
* [UE4中的网络模式](https://zhuanlan.zhihu.com/p/38074925)
16+
* [UE4中的网络模式](https://zhuanlan.zhihu.com/p/38074925)
17+
18+
`ServerReplicateActors_ProcessPrioritizedActorsRange`:根据排序好的优先级从高到低,调用 `IsActorRelevantToConnection` 检查相关性,为每个通过检测的 actor 调用 `UActorChannel::ReplicateActor`
19+
20+
### Note H
21+
NetDriver 在创建时的 outer 是 Transient Package。在客户端和服务器上切换地图时,都会把 net driver 销毁掉再重新创建(就是走一套登录流程,服务器 listen,客户端先创建 pending game 然后握手这些)
22+
23+
TODO:文档 [Travelling in Multiplayer](https://dev.epicgames.com/documentation/en-us/unreal-engine/travelling-in-multiplayer-in-unreal-engine) 中讨论了 seamless travel,**试试 在 multiplayer 中 travel world**
24+
### Note M
25+
使用 `Replicated` 以及 `ReplicatedUsing` 标记了的 uproperty 都会带有 `CPF_Net`,actor channel 创建时生成 `FRepLayout` 会用到
26+
### Note V
27+
子对象同步与 actor 同步是类似的,设置 `bReplicates` 为 true,重载 `GetLifetimeReplicatedProps` 函数
28+
29+
scene component 的 relative location / rotation 是同步的,感觉同时开了 root component 的 replicate 和 actor 的 replicate movement 会造成邪恶的后果
30+
### Note S
31+
文档 [Object Replication](https://dev.epicgames.com/documentation/en-us/unreal-engine/replicating-uobjects-in-unreal-engine) 中讨论了如何 replicate 普通的 uobject
32+
33+
### Note Y
34+
[# 关于网络同步的理解与思考](https://zhuanlan.zhihu.com/p/34721113) 中谈到从 package 中加载的对象即使没有标记为 replicate 也是可以跨网络访问的。设想一个 RPC 调用,传递了一个 uobject 指针。TODO:但我有点怀疑这个,因为都是通过 net guid 标识的,是得发送 RPC 时也同步一下 net guid 吗?得试一试才行
35+
36+
TODO:[Replicate Actor Properties](https://dev.epicgames.com/documentation/en-us/unreal-engine/replicate-actor-properties-in-unreal-engine) 中也特地说明了跨网络访问的 uobject 指针。而且对 replication condition 的说明很详细,可以后面再看看
37+
38+
### Note T:Channel 关闭
39+
`EChannelCloseReason` 中可以看到有若干 channel 关闭的原因(从 `UActorChannel::CleanUp` 可以看到,客户端的 channel 释放时才会同时析构 actor)
40+
* 当服务器上 actor destroy 时
41+
* 文档 [Actor Relevancy](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) 有说明,如果 actor 在一个 connection 中一段时间不 relevancy,将会关闭这个 connection 里对应的 actor channel
42+
* 文档 [Actor Network Dormancy](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-network-dormancy-in-unreal-engine) 中讨论了如何设置 actor dormancy(注意,dormant actor 不会再检测 relevancy),当 actor 进入 dormant 时,服务器会关闭 actor channel(具体关闭哪些 connection 的 actor channel 取决于 `ShouldActorGoDormant` 函数)
43+
* 服务器上调用 `AActor::TearOff`。服务器会关闭所有连接中该 actor 对应的 channel,客户端会将该 actor 的 role 设置为 authority(见 `UNetDriver::ClientSetActorTornOff`
44+
45+
channel 关闭的流程都是先服务器调用 `UActorChannel::Close`,然后 close bunch 到客户端,客户端析构相应的 channel(情况 1 和 2 会析构 actor,3 和 4 则不会),服务器收到客户端的 ack 后,再释放自己的 channel
46+
47+
TODO:解释 `AActor::FlushNetDormancy``AActor::ForceNetUpdate` 的区别
48+
### Note N
49+
TODO:文档 [Replicated Object Execution Order](https://dev.epicgames.com/documentation/en-us/unreal-engine/replicated-object-execution-order-in-unreal-engine) 中提到一个如果一个 unreliable rpc 在一个 reliable rpc 前调用,那么在远程客户端上这个 unreliable rpc 绝不会再 reliable rpc 后面执行,这是为什么
50+
### Note P
51+
TODO:移动组件的同步,看看 [Networked Movement in the Character Movement Component](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) 以及 [# 移动组件详解](https://zhuanlan.zhihu.com/p/34257208)
52+

0 commit comments

Comments
 (0)