Skip to content

Commit 124038f

Browse files
committed
update behavior tree in inreal
1 parent d9f67a8 commit 124038f

File tree

4 files changed

+33
-5
lines changed

4 files changed

+33
-5
lines changed

_posts/UE/2024-11-21 Delegates in Unreal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* 多播代理能够同时绑定多个需要调用的函数。`DECLARE_MULTICAST_DELEGATE` 系列宏实际上 typedef 了一下 `TMulticastDelegate<>` 模板,它内部也只有来自基类的 `TMulticastDelegateBase` 的成员变量 `InvocationList``CompactionThreshold``InvocationListLockCount`
3131
* 最核心的是这个 `InvocationList`,它是一个由 `TDelegateBase` 组成的动态列表。调用代理的 `Broadcast` 时,会遍历这个 `InvocationList` 中的 `TDelegateBase`,获取它的 `DelegateInstance`,然后调用 `DelegateInstance``ExecuteIfSafe` 函数
3232
* 当我们调用 `TMulticastDelegate``AddStatic``AddUObject` 等函数时(它们对应单播情况的 `BindStatic``BindUObject`),`TMulticastDelegate` 会创建一个 `TDelegate`,它内部的 `DelegateInstance` 保存了调用需要的所有信息(具体保存了哪些信息已经在单播代理中讲过了)。然后将这个 `TDelegate` 加入到 `InvocationList`
33-
* 每个 `DelegateInstance` 都有一个唯一的 `FDelegateHandle`,调用 `AddStatic` 等函数时,会将创建的 `DelegateInstance``FDelegateHandle` 作为返回值返回。如果要移除某一个函数,调用 `Remove` 函数时传入这个 Handle
33+
* 每个 `DelegateInstance` 都有一个唯一的 `FDelegateHandle`,调用 `AddStatic` 等函数时,会将创建的 `DelegateInstance``FDelegateHandle` 作为返回值返回。如果要移除某一个函数,调用 `Remove` 函数时传入这个 Handle**可以在回调函数内调用 `Remove`,多播内部有个 counter 来避免 for 循环过程中删除元素产生错误**
3434
* 多播代理不保证各个函数的调用顺序
3535

3636
### 动态代理(Dynamic Delegates)

_posts/UE/Basic GamePlay/2025-06-11 Behaviour Tree in Unreal.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ https://www.gamedeveloper.com/programming/behavior-trees-for-ai-how-they-work
44

55
[UE5 行为树(1):运行逻辑](https://zhuanlan.zhihu.com/p/667581758):感觉它对 Notify Observer 的讨论有待商榷
66

7+
TODO:[AI行为树系统 目录](https://zhuanlan.zhihu.com/p/368889019) 讲得很好,再看看
8+
79
TODO:为什么只有上层是 selector 时 decorator 才能打断低优先级的节点?
810

911
TODO:为什么 service 的 on search start 被调用了两次,在一开始的时候
@@ -24,3 +26,11 @@ decorator 节点的几个回调
2426
* `OnNodeDeactivation`:对应到蓝图里是 `ReceiveExecutionFinish`,下面的节点执行完毕后,会调用该函数
2527
* TODO:`OnBecomeRelevant``OnCeaseRelevant` 什么时候调用的?
2628

29+
### 单例
30+
[AI行为树系统 其一 行为树节点的单例设计](https://zhuanlan.zhihu.com/p/369100301) 讲得挺好的。额外需要注意的是,这个单例的意思是,多个对应同一行为树资产的行为树实例,它们共享行为树上的节点。假设行为树资产 U,它的实例 A,B。该行为树有三个节点 a,b,c。那么
31+
* 实例 A 的节点 a 和实例 B 的节点 a 是同一个,除非该节点类的 `bCreateNodeInstance` 为 true(例如蓝图 task)
32+
* 实例 A 的节点 a,b,c 不是相同的,即使它们是同一类的 task(例如都是 `MoveTo`
33+
* 假设有新的行为树资产 U2,则 U2 的实例不与 U 的实例共享节点,即使这些节点可能是同一类的 task
34+
### 内存
35+
TODO:解释 special memory 和 instance memory 的区别
36+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
TODO:AI Perception Component 中的三个 update 回调有啥区别?
2+
3+
TODO:sense 中的 age 是什么意思
4+
5+
UAIPerceptionSystem
6+
7+
[UE4 关于AIPerception(二)](https://zhuanlan.zhihu.com/p/463525577) 中谈到 pawn 会直接被注册为 sense source,UAIPerceptionStimuliSourceComponent 帮助注册 sense source
8+
9+
[Should I use “Pawn Sensing or “Ai Perception” for Unreal Engine 5.1.1?](https://forums.unrealengine.com/t/should-i-use-pawn-sensing-or-ai-perception-for-unreal-engine-5-1-1/791984) 中谈到 `UPawnSensingComponent` 被 AI Perception 取代了
10+
11+
[Unreal Engine AI with Behavior Trees](https://www.youtube.com/watch?v=iY1jnFvHgbE) 中讨论了 EQS 如何让 AI 变得更智能一些

_posts/UE/Engine Basic/2025-06-17 UObject Initialization in Unreal.md renamed to _posts/UE/Engine Basic/2025-06-17 UObject System Initialization in Unreal.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ static TArray<FFieldCompiledInInfo*> DeferredClassRegistration;
4141
uobject 的 uclass 也是一个 uobject,因此这个 uclass 也有 `ClassPrivate` 指针,它指向的是 uclass 的 uclass,但 uclass 又是 uobject 的子类。因此这里会存在一个循环依赖的问题。UE 里是先构建 uobject 的 uclass,此时这个 uclass 的 `ClassPrivate` 指针为空
4242
### Note 2
4343
由于 CoreUObject 中不会使用 uproperty 等标记,因此 CoreUObject 中的类的 uclass 的 `PropertyLink` 为空。但 GC 系统需要根据 `PropertyLink` 生成 token stream,因此这些类中使用 `UE::GC::DeclareIntrinsicMembers` 显式地声明自己引用的字段
44+
### User Module 的加载时机
45+
时间顺序大概是这样
46+
* CoreUObject 先加载
47+
* `EarliestPossible``PostConfigInit` 类型的 user module 加载
48+
* `InitUObject` 被调用,此后可以使用 NewObject API 了
49+
* 然后是加载 `PostSplashScreen``PostDefault` 类型的 user module
50+
* `CloseDisregardForGC` 被调用
51+
* 加载 `PostEngineInit` 类型的 user module
4452
### Disregard From GC
4553
`FUObjectArray` 用于负责分配 `FUObjectItem`,在初始时根据最大的 uobject 数目分配 chunk 指针数组,每个 chunk 能容纳 64 * 1024 个 `FUObjectItem`**TODO:从代码上看起来全局的 uobject 数量就不能超过这个数?**
4654

@@ -57,13 +65,12 @@ index 在 `MaxObjectsNotConsideredByGC` 内的 object 不参与 GC,这意味
5765

5866
如果这个 object 在永久内存池中,可达性分析时可以直接通过指针的值来判断出它不用参与 GC,而不需要再解引用比较 `EInternalObjectFlags::Unreachable` 标记,减少 GC 的内存访问。因此永久内存池通常和 `MaxObjectsNotConsideredByGC` 同时使用,保证不参与 GC 的对象同时也在永久内存池中
5967

60-
在 UE4 的垃圾回收里,首先是 `MarkObjectsAsUnreachable`,会将非 root set 的普通 object 以及 cluster 中不包含 root set 的 cluster root 都标记上 `EInternalObjectFlags::Unreachable`
6168

6269
参考
6370
* [UObject(五)类型系统信息收集](https://zhuanlan.zhihu.com/p/26019216)
6471
* [UObject(七)类型系统注册-第一个UClass](https://zhuanlan.zhihu.com/p/57005310)
72+
* [UE4 垃圾回收](https://zhuanlan.zhihu.com/p/67055774)
73+
* [UE4 UObject管理方式](https://zhuanlan.zhihu.com/p/362228148)
6574

6675

67-
TODO:游戏模块在 `CloseDisregardForGC` 之前还是之后加载?
68-
TODO:解释 `EInternalObjectFlags::ReachableInCluster`
69-
TODO:如果 unload module 会怎样?CDO 这些会释放掉吗
76+
TODO:如果 unload module 会怎样?CDO 这些会释放掉吗:我觉得不会,就一直留在那了

0 commit comments

Comments
 (0)