-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
577 lines (429 loc) · 57.9 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<title>Somewhere</title>
<meta name="author" content="eddy pang">
<meta name="description" content="不做无谓的叹息,只是向前走">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:site_name" content="Somewhere"/>
<meta property="og:image" content=""/>
<link rel="alternative" href="/atom.xml" title="Somewhere" type="application/atom+xml">
<link href="/favicon.png" rel="icon">
<link rel="stylesheet" href="/css/bootstrap.min.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/font-awesome.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/responsive.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/highlight.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/prism.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/google-fonts.css" media="screen" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<script src="/js/jquery-2.0.3.min.js"></script>
<!-- analytics -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-70812759-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-70812759-1');
</script>
<meta name="generator" content="Hexo 6.2.0"></head>
<body>
<nav id="main-nav" class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<button type="button" class="navbar-header navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Somewhere</a>
<div class="collapse navbar-collapse nav-menu">
<ul class="nav navbar-nav">
<li>
<a href="/archives" title="All the articles.">
<i class=""></i>Archives
</a>
</li>
<li>
<a href="/categories" title="All the categories.">
<i class=""></i>Categories
</a>
</li>
<li>
<a href="/tags" title="All the tags.">
<i class=""></i>Tags
</a>
</li>
<li>
<a href="/about" title="About me.">
<i class=""></i>About
</a>
</li>
</ul>
</div>
</div> <!-- container -->
</nav>
<div class="clearfix"></div>
<div class="container">
<div class="content">
<div class="page-header logo">
<h1>Somewhere<span class="blink-fast">|</span></h1>
</div>
<div class="row page">
<div class="col-md-9">
<div class="slogan">
bobbiee learn there
</div>
<div id="top_search"></div>
<div class="mypage">
<!-- title and entry -->
<!-- display as entry -->
<div class="row">
<div class="col-md-8">
<h3 class="title">
<a href="/2024/05/17/mayaLearning/" ></a>
</h3>
</div>
<div class="col-md-4">
<div class="date">post @ 2024-05-17 </div>
</div>
</div>
<div class="entry">
<div class="row">
<p>关于maya的一些操作</p>
<h3 id="1-导入fbx后尺寸不对,调整当前显示的默认单位-window-gt-preference-gt-settings"><a href="#1-导入fbx后尺寸不对,调整当前显示的默认单位-window-gt-preference-gt-settings" class="headerlink" title="1. 导入fbx后尺寸不对,调整当前显示的默认单位 window->preference->settings"></a>1. 导入fbx后尺寸不对,调整当前显示的默认单位 window->preference->settings</h3><h3 id="2-动画播放的速度不对,可能是默认的播放选项不一样,window-gt-preference-gt-时间滑块"><a href="#2-动画播放的速度不对,可能是默认的播放选项不一样,window-gt-preference-gt-时间滑块" class="headerlink" title="2. 动画播放的速度不对,可能是默认的播放选项不一样,window->preference->时间滑块"></a>2. 动画播放的速度不对,可能是默认的播放选项不一样,window->preference->时间滑块</h3><h3 id="3-创建骨骼:选中模式为绑定,然后创建骨骼,按住x点鼠标左键可以吸附到网格点上"><a href="#3-创建骨骼:选中模式为绑定,然后创建骨骼,按住x点鼠标左键可以吸附到网格点上" class="headerlink" title="3. 创建骨骼:选中模式为绑定,然后创建骨骼,按住x点鼠标左键可以吸附到网格点上"></a>3. 创建骨骼:选中模式为绑定,然后创建骨骼,按住x点鼠标左键可以吸附到网格点上</h3><p><img src="/./createSkeleton.png" alt="create skeleton"></p>
<h3 id="4-插入root骨骼,先选中原来的根节点,然后再ctrl-选中新增根节点,按下P,即可自动完成"><a href="#4-插入root骨骼,先选中原来的根节点,然后再ctrl-选中新增根节点,按下P,即可自动完成" class="headerlink" title="4. 插入root骨骼,先选中原来的根节点,然后再ctrl 选中新增根节点,按下P,即可自动完成"></a>4. 插入root骨骼,先选中原来的根节点,然后再ctrl 选中新增根节点,按下P,即可自动完成</h3><p>关于动画的一些操作</p>
<ol>
<li>动画有只包括skeleton的和有蒙皮的,如果项目里这两种动画都要使用,则需要先导入有骨骼的动画</li>
<li>导入动画时可以选择导入的范围,如全部导入<code>exported time</code>,只导入有动画的部分<code>Animated time</code>,以及指定帧数的导入<code>Set Range</code></li>
</ol>
<p>动画重定向</p>
<ol>
<li>两套骨骼需要先调整到同一个姿势,可以借助摆放到同一视图来实现</li>
</ol>
</div>
<a type="button" href="/2024/05/17/mayaLearning/#more" class="btn btn-default more">Read More</a>
</div>
<!-- display as entry -->
<div class="row">
<div class="col-md-8">
<h3 class="title">
<a href="/2024/05/13/CharaterControlling/" ></a>
</h3>
</div>
<div class="col-md-4">
<div class="date">post @ 2024-05-13 </div>
</div>
</div>
<div class="entry">
<div class="row">
<h2 id="1-旋转的实现"><a href="#1-旋转的实现" class="headerlink" title="1. 旋转的实现"></a>1. 旋转的实现</h2><h3 id="1-1-在人物BP下的根节点-Details-面板中,有如下的一些选项Use-Controller-Rotation-Yaw,Use-Controller-Rotation-Pitch,Use-Controller-Rotation-Roll。其对应的文档是-this-pawn’s-rotation-will-be-updated-to-match-the-player-controller"><a href="#1-1-在人物BP下的根节点-Details-面板中,有如下的一些选项Use-Controller-Rotation-Yaw,Use-Controller-Rotation-Pitch,Use-Controller-Rotation-Roll。其对应的文档是-this-pawn’s-rotation-will-be-updated-to-match-the-player-controller" class="headerlink" title="1.1 在人物BP下的根节点 Details 面板中,有如下的一些选项Use Controller Rotation Yaw,Use Controller Rotation Pitch,Use Controller Rotation Roll。其对应的文档是:this pawn’s rotation will be updated to match the player controller"></a>1.1 在人物BP下的根节点 Details 面板中,有如下的一些选项<code>Use Controller Rotation Yaw</code>,<code>Use Controller Rotation Pitch</code>,<code>Use Controller Rotation Roll</code>。其对应的文档是:this pawn’s rotation will be updated to match the player controller</h3><h3 id="1-2-在Character-Movement-面板下-Rotation-Settings"><a href="#1-2-在Character-Movement-面板下-Rotation-Settings" class="headerlink" title="1.2 在Character Movement 面板下 Rotation Settings"></a>1.2 在Character Movement 面板下 Rotation Settings</h3><p>有以下配置,可以实现适当的旋转速度和延时效果,<code>Rotation Rate</code>,<code>Use Controller Desired Rotation</code>,<code>Orient Rotation to Movement</code></p>
</div>
<a type="button" href="/2024/05/13/CharaterControlling/#more" class="btn btn-default more">Read More</a>
</div>
<!-- display as entry -->
<div class="row">
<div class="col-md-8">
<h3 class="title">
<a href="/2024/05/12/BPClassLearn/" title="学习 UE 的一些基础概念">常用且重要的蓝图类</a>
</h3>
</div>
<div class="col-md-4">
<div class="date">post @ 2024-05-12 </div>
</div>
</div>
<div class="entry">
<div class="row">
<h2 id="1-PlayerController"><a href="#1-PlayerController" class="headerlink" title="1. PlayerController"></a>1. PlayerController</h2><p>PlayerController 在关卡中通常可以理解为附着在 camera 上,或是第一个 activated camera上,这也可以解释摄像机接收input mouse的值并围绕着actor旋转的行为是通过去控制PlayerController去实现的。<br>功能:<br>(a) camera 的管理<br>(b) input 系统<br>(c) HUD 显示<br>(d) level 的切换<br>(e) voice 的控制</p>
</div>
<a type="button" href="/2024/05/12/BPClassLearn/#more" class="btn btn-default more">Read More</a>
</div>
<!-- display as entry -->
<div class="row">
<div class="col-md-8">
<h3 class="title">
<a href="/2022/07/24/bobbieeComing/" >bobbiee is coming</a>
</h3>
</div>
<div class="col-md-4">
<div class="date">post @ 2022-07-24 </div>
</div>
</div>
<div class="entry">
<div class="row">
<h3 id="can-i-insert-a-pic-there"><a href="#can-i-insert-a-pic-there" class="headerlink" title="can i insert a pic there?"></a>can i insert a pic there?</h3>
</div>
<a type="button" href="/2022/07/24/bobbieeComing/#more" class="btn btn-default more">Read More</a>
</div>
<!-- display as entry -->
<div class="row">
<div class="col-md-8">
<h3 class="title">
<a href="/2022/07/24/basic concpts in UE4/" title="学习 UE 的一些基础概念">some basic concpts in UE4</a>
</h3>
</div>
<div class="col-md-4">
<div class="date">post @ 2022-07-24 </div>
</div>
</div>
<div class="entry">
<div class="row">
<h2 id="1-简单基础概念"><a href="#1-简单基础概念" class="headerlink" title="1. 简单基础概念"></a>1. 简单基础概念</h2><p><font color=red size=4> color=red </font></p>
<h3 id="1-1-Actor"><a href="#1-1-Actor" class="headerlink" title="1.1. Actor"></a>1.1. Actor</h3><p>&emsp;&emsp;所有可以放入关卡的对象都是 Actor,比如摄像机、静态网格体、玩家起始位置。Actor支持三维变换,例如平移、旋转和缩放。你可以通过游戏逻辑代码(C++或蓝图)创建(生成)或销毁Actor。</p>
<p>Actor的基类是AActor.</p>
<p>Actor 功能 :挂载组件, Actor 的生命周期,官方文档:<a target="_blank" rel="noopener" href="https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Actors/ActorLifecycle/">https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Actors/ActorLifecycle/</a></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">初始化一个Actor:</span><br><span class="line"></span><br><span class="line">在蓝图中直接初始化:spawn an actor,设置transform,设置return 值为destroy,或设置life span为具体时间,到达时间后自动触发销毁</span><br><span class="line"></span><br><span class="line">在cpp中进行初始化 : 需要使用模板和GetWorld方法,比如 </span><br><span class="line">SherylActor *actor = GetWorld()->SpawnActor<SherylActor>(Fvector(0,0,0),Fvector(0,0,0));</span><br><span class="line">对应的销毁方法actor->Destroy() || SetLifeSpan(1);</span><br></pre></td></tr></table></figure>
<h3 id="1-2-component"><a href="#1-2-component" class="headerlink" title="1.2. component"></a>1.2. component</h3><p>不同的负责的component 实现了 Actor 的功能</p>
<h3 id="1-3-UObject"><a href="#1-3-UObject" class="headerlink" title="1.3. UObject"></a>1.3. UObject</h3><p>UObject提供的元数据、反射生成、GC垃圾回收、序列化、编辑器可见、Class Default Object等,UE可以构建一个Object运行的世界。</p>
<p>a. 序列化:内存中的内容保存到磁盘 ——> 存档</p>
<p>b. 反序列化:磁盘中的内容读取到内存中</p>
<p>c. Class Default Object:CDO本质上是一个默认的“模板”对象,由类构造函数生成,之后未修改。<br> CDO是在引擎初始化时创建的,当引擎为每个类生成UClass对象时。每个UClass的实例都是在引擎初始化期间创建的,并被分配为该UClass的CDO;序列化与反序列化时只对CDO中修改的部分操作</p>
<p>d. <strong>使用场景:需要用到UObject的特性时,可以继承它</strong></p>
<h2 id="2-基础类型的转换"><a href="#2-基础类型的转换" class="headerlink" title="2. 基础类型的转换"></a>2. 基础类型的转换</h2><h3 id="2-1"><a href="#2-1" class="headerlink" title="2.1"></a>2.1</h3><p>&emsp;&emsp;Fstring 与 Fname 是常用的两种字符串类型,FString更贴近C++中的string,而FName比较特别,它不直接存储字符串数据, 而是通过索引值关联到真正字符串数据。FName使用一个轻型字符串系统,在此系统中,特定字符串会被重复使用,数据表也只存储一次。__FName不可变,也无法被操作__。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//FName to FString</span></span><br><span class="line"> FString str = <span class="built_in">TEXT</span>(<span class="string">"test"</span>);</span><br><span class="line"> FName name = <span class="built_in">FName</span>(str);</span><br><span class="line"><span class="comment">//FString to FName </span></span><br><span class="line"> FString str = name.<span class="built_in">ToString</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">//std::string to FString</span></span><br><span class="line"> std::string stdStr = <span class="string">"test"</span>;</span><br><span class="line"> <span class="function">FString <span class="title">fStr</span><span class="params">(stdstr.c_str())</span></span>;</span><br><span class="line"><span class="comment">//FString to std::string</span></span><br><span class="line"> <span class="function">std::string <span class="title">stdStr</span><span class="params">(TCHAR_TO_UTF8(*fStr))</span></span>;</span><br><span class="line"><span class="comment">//FString to int32</span></span><br><span class="line"> FString fStr = <span class="built_in">TEXT</span>(<span class="string">"test"</span>);</span><br><span class="line"> int32 intValue = FCString::<span class="built_in">Atoi</span>(*fStr);</span><br><span class="line"> <span class="comment">//直接用C++ </span></span><br><span class="line"> int32 intValue = <span class="built_in">atoi</span>(<span class="built_in">TCHAR_TO_UTF8</span>((*fStr)));</span><br><span class="line"></span><br><span class="line"><span class="comment">//FString to float</span></span><br><span class="line"> <span class="type">float</span> fValue = FCString::<span class="built_in">Atof</span>(*fStr);</span><br><span class="line"> fValue = <span class="built_in">atof</span>(<span class="built_in">TCHAR_TO_UTF8</span>(*fStr));</span><br><span class="line"><span class="comment">//FString to bool</span></span><br><span class="line"> <span class="type">bool</span> boolValue = fStr.<span class="built_in">ToBool</span>();</span><br><span class="line"><span class="comment">//int to FString</span></span><br><span class="line"> FString fStr = FString::<span class="built_in">FromInt</span>(<span class="number">2</span>);</span><br><span class="line"><span class="comment">//float to FString</span></span><br><span class="line"> FString fStr = FString:<span class="built_in">SanitizeFloat</span>(<span class="number">2.2f</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//FString to char*</span></span><br><span class="line"> <span class="function">FString <span class="title">fStr</span><span class="params">(TEXT(<span class="string">"test"</span>))</span></span>;</span><br><span class="line"> <span class="type">const</span> TCHAR *charValue = *fStr;</span><br><span class="line"><span class="comment">//FString to FText</span></span><br><span class="line"> FText fText = FText::<span class="built_in">FromFString</span>(fStr);</span><br><span class="line"><span class="comment">//FText to FName</span></span><br><span class="line"> FName fName = <span class="built_in">FName</span>(*fText.<span class="built_in">ToString</span>());</span><br><span class="line"><span class="comment">//FString to TArray<uint8></span></span><br><span class="line"><span class="comment">//先将FString 转换为 char 数组, 再进行遍历</span></span><br><span class="line"> <span class="function">FString <span class="title">fStr</span><span class="params">(TEXT(<span class="string">"test"</span>))</span></span>;</span><br><span class="line"> TArray<uinit8> targetArr;</span><br><span class="line"> TCHAR *charData = fStr.<span class="built_in">GetCharArray</span>().<span class="built_in">GetData</span>();</span><br><span class="line"> int32 len = FCString::<span class="built_in">StrLen</span>(charData);</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < len; i++) {</span><br><span class="line"> uint8 *dstValue = (uint8 *)TCHAR_TO_UTF8 charData;</span><br><span class="line"> targetArr.<span class="built_in">Add</span>(*dstValue);</span><br><span class="line"> charData ++;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// use UE4 api</span></span><br><span class="line"> FBase64::<span class="built_in">DeCode</span>(fStr, targetArr);</span><br><span class="line"><span class="comment">//TArray<uint8> to FString</span></span><br><span class="line"> <span class="function"><span class="type">const</span> std::string <span class="title">stdStr</span><span class="params">((reinterpre_cast<<span class="type">const</span> <span class="type">char</span> *>(targetArr.GetData()), targetArr.GetNum()))</span></span>;</span><br><span class="line"> <span class="function">FString <span class="title">fStr</span><span class="params">(stdStr.c_str())</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//UEnum to FString ,反射用法</span></span><br><span class="line"> <span class="keyword">enum</span> <span class="title class_">ETempEnum</span> {</span><br><span class="line"> test0,</span><br><span class="line"> test1,</span><br><span class="line"> test2</span><br><span class="line"> };</span><br><span class="line"> <span class="type">const</span> UEnum *enumPtr = <span class="built_in">FindObject</span><UEnum>(ANY_PACKAGE, <span class="built_in">TEXT</span>(<span class="string">"ETempEnum"</span>), <span class="literal">true</span>);</span><br><span class="line"> <span class="keyword">if</span> (enumPtr) {</span><br><span class="line"> FString str = enumPtr-><span class="built_in">GetNameStringByIndex</span>(ETempEnum::test1);</span><br><span class="line"> }</span><br><span class="line"><span class="comment">//FString to UEnum</span></span><br><span class="line"> <span class="type">const</span> UEnum *enumPtr = <span class="built_in">FindObject</span><UEnum>(ANY_PACKAGE, <span class="built_in">TEXT</span>(<span class="string">"ETempEnum"</span>), <span class="literal">true</span>);</span><br><span class="line"> <span class="keyword">if</span> (enumPtr) {</span><br><span class="line"> ETempEnum enumVal = (ETempEnum)enumPtr-><span class="built_in">GetIndexByNameString</span>(TEXT<span class="string">"test1"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="2-2-TCHAR-类型说明"><a href="#2-2-TCHAR-类型说明" class="headerlink" title="2.2 TCHAR 类型说明"></a>2.2 TCHAR 类型说明</h3><p>&emsp;&emsp;C++ 支持两种字符:ANSI编码(使用””包裹)和Unicode编码(使用L””包裹),导致对不同字符处理的方式不同。为了将其统一,微软定义了 TCHAR,通过条件编译(_UNICODE和UNICODE宏)控制实际使用的字符集,即:</p>
<p>&emsp;&emsp;当没有定义_UNICODE宏时,程序编译为 ANSI,TCHAR = char;</p>
<p>&emsp;&emsp;当定义了_UNICODE宏时,程序编译为 UNICODE,TCHAR = wchar_t ;</p>
<h3 id="2-3-UE4中的智能指针"><a href="#2-3-UE4中的智能指针" class="headerlink" title="2.3 UE4中的智能指针"></a>2.3 UE4中的智能指针</h3><p>&emsp;&emsp;UE4 对 UObject 提供内存管理,而对原生的C++ 对象无;提供了智能指针来管理内存,是C++11智能指针的自定义实现。官方介绍文档链接:<a target="_blank" rel="noopener" href="https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/SmartPointerLibrary/%E3%80%82">https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/SmartPointerLibrary/。</a><br>可区分为:</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>适用情形</th>
</tr>
</thead>
<tbody><tr>
<td>共享指针(TSharedPtr)</td>
<td>共享指针拥有其引用的对象,无限防止该对象被删除,并在无共享指针或共享引用(见下文)引用其时,最终处理其的删除。共享指针可为空白,意味其不引用任何对象。任何非空共享指针都可对其引用的对象生成共享引用。</td>
</tr>
<tr>
<td>共享引用(TSharedRef)</td>
<td>共享引用的行为与共享指针类似,即其拥有自身引用的对象。对于空对象而言,其存在不同;共享引用须固定引用非空对象。共享指针无此类限制,因此共享引用可固定转换为共享指针,且该共享指针固定引用有效对象。要确认引用的对象是非空,或者要表明共享对象所有权时,请使用共享引用。</td>
</tr>
<tr>
<td>弱指针(TWeakPtr<code>TSharedPtr</code>)</td>
<td>弱指针类与共享指针类似,但不拥有其引用的对象,因此 <strong>不影响其生命周期</strong> 。此属性中断引用循环,因此十分有用,但也意味弱指针可在无预警的情况下随时变为空。因此,弱指针可生成指向其引用对象的共享指针,确保程序员能对该对象进行安全临时访问。</td>
</tr>
<tr>
<td>唯一指针(TUniquePtr)</td>
<td>唯一指针仅会显式拥有其引用的对象。仅有一个唯一指针指向给定资源,因此唯一指针可转移所有权,但无法共享。复制唯一指针的任何尝试都将导致编译错误。唯一指针超出范围时,其将自动删除其所引用的对象。</td>
</tr>
</tbody></table>
<h2 id="3-delegate"><a href="#3-delegate" class="headerlink" title="3. delegate"></a>3. delegate</h2><p>&emsp;&emsp;delegate 是UE中定义的一种消息机制,常用于解耦不同对象之间的关联,delegate的触发者不与监听者有直接关联,两者通过delegate间接建立联系。<strong>delegate本质是一个特殊类的对象,内部可以储存一个或多个函数指针,调用参数和返回值,作用如同函数指针,但更安全,支持编译期类型检查</strong></p>
<h4 id="3-1-单播代理"><a href="#3-1-单播代理" class="headerlink" title="3.1 单播代理"></a>3.1 单播代理</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">DECLARE_DELETGATE</span>(testDelegate);</span><br><span class="line"><span class="built_in">DECLARE_DELEGATE_TwoParams</span>(testDelegate, <span class="type">float</span> , <span class="type">const</span> FString &);</span><br><span class="line"><span class="comment">//C++ lambda</span></span><br><span class="line"><span class="comment">// C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式). Lambda表达式具体形式如下:</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// [capture](parameters)->return-type{body}</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// [capture](parameters){body}</span></span><br></pre></td></tr></table></figure>
<h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><h4 id="amp-emsp-amp-emsp-·-使用DECLARE-宏声明一个delegate类型-FDelegateXXX"><a href="#amp-emsp-amp-emsp-·-使用DECLARE-宏声明一个delegate类型-FDelegateXXX" class="headerlink" title="&emsp;&emsp;· 使用DECLARE_*宏声明一个delegate类型 FDelegateXXX"></a>&emsp;&emsp;· 使用DECLARE_*宏声明一个delegate类型 FDelegateXXX</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//cpp文件开头</span></span><br><span class="line"><span class="built_in">DECLARE_DELEGATE_RetVal_TwoParams</span>(int32, FDelegateTwoParams, <span class="type">float</span>, <span class="type">const</span> FString &);</span><br></pre></td></tr></table></figure>
<h4 id="amp-emsp-amp-emsp-·-声明一个-FDelegateXXX-类型的代理对象"><a href="#amp-emsp-amp-emsp-·-声明一个-FDelegateXXX-类型的代理对象" class="headerlink" title="&emsp;&emsp;· 声明一个 FDelegateXXX 类型的代理对象"></a>&emsp;&emsp;· 声明一个 FDelegateXXX 类型的代理对象</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//cpp class中声明一个对应代理类型的变量</span></span><br><span class="line">FDelegateTwoParmas fDelegate;</span><br></pre></td></tr></table></figure>
<h4 id="amp-emsp-amp-emsp-·-绑定需要执行的函数指针到代理对象上"><a href="#amp-emsp-amp-emsp-·-绑定需要执行的函数指针到代理对象上" class="headerlink" title="&emsp;&emsp;· 绑定需要执行的函数指针到代理对象上"></a>&emsp;&emsp;· 绑定需要执行的函数指针到代理对象上</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//eg. 在Actor类中BeginPlaty方法中绑定,这里第一个参数传 this 是因为写在类里的成员方法中,要绑定自己对应类中的方法</span></span><br><span class="line"><span class="comment">//绑定一个继承自UObject的类里的方法</span></span><br><span class="line">fDelegate::<span class="built_in">BindUObject</span>(<span class="keyword">this</span>, &your_corresponding_function);</span><br><span class="line"><span class="comment">//eg.绑定lambda</span></span><br><span class="line">fDelegate::<span class="built_in">BindLamda</span>([<span class="keyword">this</span>](<span class="type">float</span> fVal, <span class="type">const</span> FString &s)->int32 {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">});</span><br><span class="line"><span class="comment">//eg.绑定C++ 原生方法</span></span><br><span class="line"><span class="comment">//声明一个类A的对象a</span></span><br><span class="line">A a;</span><br><span class="line">fDelegate::<span class="built_in">BindRaw</span>(&a, &A::funcA);</span><br><span class="line"><span class="comment">//eg. 绑定共享指针</span></span><br><span class="line"><span class="comment">//声明一个指向A类型对象的共享指针</span></span><br><span class="line">TSharedPtr<A> aPtr = MakeSharable<<span class="keyword">new</span> A>;</span><br><span class="line">fDelegate::<span class="built_in">BindSP</span>(aPtr.<span class="built_in">ToSharedRef</span>(), &A::funcA);</span><br><span class="line"><span class="comment">//eg. 绑定一个静态函数</span></span><br><span class="line">fDelegate::<span class="built_in">BindStatic</span>(&your_static_func_name);</span><br><span class="line"><span class="comment">//Binds a shared pointer-based (slower, conditionally thread-safe) member function delegate.</span></span><br><span class="line">TSharedPtr<A, ESPMode::ThreadSafe> aPtr1 = <span class="built_in">MakeSharable</span>(<span class="keyword">new</span> A);</span><br><span class="line">fDelegate::<span class="built_in">BindThreadSafeSP</span>(aPtr1.<span class="built_in">ToSharedRef</span>(). &A::funcA);</span><br><span class="line"><span class="comment">//eg.通过函数名找到函数并绑定到代理</span></span><br><span class="line">fDelegate::<span class="built_in">BindUFunction</span>(<span class="keyword">this</span>, <span class="built_in">FName</span>(<span class="string">"your_function_name_in_this_class"</span>));</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="amp-emsp-amp-emsp-·-触发代理对象中的函数指针会立即执行"><a href="#amp-emsp-amp-emsp-·-触发代理对象中的函数指针会立即执行" class="headerlink" title="&emsp;&emsp;· 触发代理对象中的函数指针会立即执行"></a>&emsp;&emsp;· 触发代理对象中的函数指针会立即执行</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//执行时需要判断是否绑定</span></span><br><span class="line"><span class="keyword">if</span> (fDelegate.<span class="built_in">IsBond</span>()) {</span><br><span class="line"> fDelegate.<span class="built_in">Excute</span>(<span class="number">11</span>, <span class="string">"ddd"</span>);</span><br><span class="line">}</span><br><span class="line"><span class="comment">// no return val you can call</span></span><br><span class="line">fDelegate.<span class="built_in">ExecuteIfBound</span>()</span><br></pre></td></tr></table></figure>
<h4 id="amp-emsp-amp-emsp-·-不需要某个函数指针时,可将其从代理对象上解绑"><a href="#amp-emsp-amp-emsp-·-不需要某个函数指针时,可将其从代理对象上解绑" class="headerlink" title="&emsp;&emsp;· 不需要某个函数指针时,可将其从代理对象上解绑"></a>&emsp;&emsp;· 不需要某个函数指针时,可将其从代理对象上解绑</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fDelegate.<span class="built_in">Unbind</span>();</span><br></pre></td></tr></table></figure>
<h4 id="3-2-多播代理"><a href="#3-2-多播代理" class="headerlink" title="3.2 多播代理"></a>3.2 多播代理</h4><p>一对多,触发时可以执行多个函数,但无法确定多个函数的执行顺序,且多播代理无返回值。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//声明</span></span><br><span class="line"><span class="built_in">DECLARE_MULTICAST_DELEGATE_TwoParms</span>(FMultiDelegate, <span class="type">float</span> a, <span class="type">const</span> FString &fStr);</span><br><span class="line"><span class="comment">//绑定函数时使用的是AddXXX </span></span><br><span class="line">FMultiDelegate.<span class="built_in">AddUObject</span>(<span class="keyword">this</span>, &A::funcA);</span><br><span class="line"><span class="comment">// 执行时利用广播,不需要判断是否有效</span></span><br><span class="line">FMultiDelegate.<span class="built_in">Broadcast</span>(<span class="number">33f</span>, <span class="string">"test"</span>);</span><br></pre></td></tr></table></figure>
<h4 id="3-3-动态代理"><a href="#3-3-动态代理" class="headerlink" title="3.3 动态代理"></a>3.3 动态代理</h4><p>可以暴露给蓝图使用的代理。</p>
<h4 id="3-3-1-动态单播代理"><a href="#3-3-1-动态单播代理" class="headerlink" title="3.3.1 动态单播代理"></a>3.3.1 动态单播代理</h4><p><strong>注意命名规则是强制的,以F开头,且声明代理时需要给参数声明参数名</strong><br>DECLARE_DYNAMIC_DELEGATE(FDynamicDegate);<br>DECLARE_DYNAMIC_DELEGATE_RetVal_OnePram(float, FDynamicDegate, int32, intVal);</p>
<p><strong>暴露给蓝图使用的方式</strong></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//通过使动态单播代理作为函数参数的形式将其暴露给蓝图</span></span><br><span class="line"><span class="built_in">UFUNCTION</span>(BlueprintCallable)</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">testdynamicdelegate</span><span class="params">(FDynamicDelegate fdynamicdelegate)</span></span>;</span><br></pre></td></tr></table></figure>
<p><img src="/.%5CdynamicDelegateExample.png" alt="动态单播代理蓝图示意"></p>
<h4 id="3-3-2-动态多播代理"><a href="#3-3-2-动态多播代理" class="headerlink" title="3.3.2 动态多播代理"></a>3.3.2 动态多播代理</h4><p>多播没有返回值。</p>
<table>
<thead>
<tr>
<th>宏</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td>DECLARE_DYNAMIC_MULTICAST_DELEGATE[_RetVal, …]( DelegateName )</td>
<td>创建一个动态多播委托。</td>
</tr>
</tbody></table>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//声明</span></span><br><span class="line"><span class="built_in">DECLARE_DYNAMIC_MULTICAST_DELEGATE</span>(FDyMuDelegate);</span><br><span class="line"><span class="comment">//绑定函数</span></span><br><span class="line"><span class="comment">//注意需要绑定的函数必须声明为UFUNTION(),因为动态代理支持将其暴露给蓝图使用</span></span><br><span class="line"><span class="built_in">UFUNCTION</span>(BluprintAssianable)</span><br><span class="line">FDyMuDelegate fDelegate;</span><br><span class="line"><span class="comment">//打开关卡蓝图,可以对actor 绑定事件</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>PS:动态多播代理类似于事件调度器,在actor的蓝图里创建一个新的event dispatcher,然后在关卡的蓝图里bind,如下图</p>
<p><img src="/.%5CDynamicDelegateAndDispatcher.png" alt="在蓝图中绑定动态多播代理绑定event dispatcher"></p>
<h3 id="4-其他"><a href="#4-其他" class="headerlink" title="4. 其他"></a>4. 其他</h3><h4 id="4-1-单例的创建需要注意对象不被GC"><a href="#4-1-单例的创建需要注意对象不被GC" class="headerlink" title="4.1 单例的创建需要注意对象不被GC"></a>4.1 单例的创建需要注意对象不被GC</h4><p>参考资料: <a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/49046671">https://zhuanlan.zhihu.com/p/49046671</a></p>
<ol>
<li><p>UPROPERTY</p>
</li>
<li><p>AddToRoot和RemoveFromRoot, 注意成对使用</p>
</li>
<li><p>FObject 类型使用智能指针进行管理</p>
</li>
<li><p>FObject 类型中使用 UObject 指针</p>
</li>
<li><p>FStreamableManager 用法</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> <span class="function">FSoftObjectPath <span class="title">AssetPath</span><span class="params">(TEXT(<span class="string">"/Game/Mannequin/Animations/ThirdPersonWalk.ThirdPersonWalk"</span>))</span></span>;</span><br><span class="line">FStreamableManager& AssetLoader = UAssetManager::<span class="built_in">GetStreamableManager</span>();</span><br><span class="line"><span class="comment">//hold object in memory.TSharedPtr<FStreamableHandle> Handle = AssetLoader.RequestSyncLoad(AssetPath, true);</span></span><br><span class="line">UObject* Obj = Handle-><span class="built_in">GetLoadedAsset</span>();</span><br><span class="line"><span class="comment">//free memory of object.Handle->ReleaseHandle();</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>FGCObjectScopeGuard 用法</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="built_in">FGCObjectScopeGuard</span>(UObject* GladOS = <span class="built_in">NewObject</span><...>(...));</span><br><span class="line"> GladOS-><span class="built_in">SpawnCell</span>();</span><br><span class="line"> <span class="built_in">RunGC</span>();</span><br><span class="line"> GladOS-><span class="built_in">IsStillAlive</span>(); <span class="comment">// Object will not be removed by GC</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
<li><p>TArray<> TArray保持引用如果有个 TArray 容器,则这个TArray需要用一个* UPROPERTY()* 去保持容器的引用,然后里面的UObject就不需要再去AddToRoot去阻止被gc了。容器clear后,元素会自动被gc.</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">UPROPERTY</span>(EditAnywhere, BlueprintReadWrite, Category = <span class="string">"UCoolDownComponent"</span>)</span><br><span class="line"> TArray<UCoolDown*> mCDArr;</span><br><span class="line"></span><br><span class="line"> UCoolDown* cd = <span class="built_in">NewObject</span><UCoolDown>(_class);</span><br><span class="line"> cd-><span class="built_in">SetSkillId</span>(_skillId);</span><br><span class="line"> mCDArr.<span class="built_in">Add</span>(cd);</span><br></pre></td></tr></table></figure>
</li>
<li><p>TMap<> 4.15版本支持了蓝图 TMap 容器,也是可以通过 UPROPERTY()去保持容器的引用,容器内的UObject就不需要再去AddToRoot去阻止被gc了</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">UPROPERTY</span>(EditAnywhere, BlueprintReadWrite, Category = <span class="string">"MyChar"</span>)</span><br><span class="line"> TMap<int32, UBehavData*> mTestMap2;</span><br><span class="line"></span><br><span class="line">UBehavData* bh = <span class="built_in">NewObject</span><UBehavData>(<span class="keyword">this</span>, UBehavData::<span class="built_in">StaticClass</span>());</span><br><span class="line">bh->mId = <span class="number">111</span>;</span><br><span class="line">mTestMap2.<span class="built_in">Add</span>(<span class="number">111</span>, bh);</span><br><span class="line">bh = <span class="built_in">NewObject</span><UBehavData>(<span class="keyword">this</span>, UBehavData::<span class="built_in">StaticClass</span>());</span><br><span class="line">bh->mId = <span class="number">222</span>;</span><br><span class="line">mTestMap2.<span class="built_in">Add</span>(<span class="number">222</span>, bh);</span><br></pre></td></tr></table></figure>
</li>
<li><p>Destroying Objects(自己想删除)</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(!MyObject) <span class="keyword">return</span>; </span><br><span class="line"><span class="keyword">if</span>(!MyObject-><span class="built_in">IsValidLowLevel</span>()) <span class="keyword">return</span>;</span><br><span class="line">MyObject-><span class="built_in">ConditionalBeginDestroy</span>(); <span class="comment">//instantly clears UObject out of memory </span></span><br><span class="line">MyObject = <span class="literal">nullptr</span>; </span><br></pre></td></tr></table></figure>
</li>
<li><p>Destroying Actors</p>
</li>
</ol>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(!TheCharacter) <span class="keyword">return</span>; </span><br><span class="line"><span class="keyword">if</span>(!TheCharacter-><span class="built_in">IsValidLowLevel</span>()) <span class="keyword">return</span>;</span><br><span class="line"> TheCharacter-><span class="built_in">Destroy</span>(); </span><br><span class="line">TheCharacter-><span class="built_in">ConditionalBeginDestroy</span>(); <span class="comment">//essential extra step, in all my testing </span></span><br></pre></td></tr></table></figure>
<ol start="11">
<li><p>AActor gc机制</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">PostActorCreated</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//做初始化工作</span></span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">BeginPlay</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//做初始化工作</span></span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">BeginDestroy</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//引擎在gc的时候调用,并不是立即调用,一般不用</span></span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">EndPlay</span><span class="params">(<span class="type">const</span> EEndPlayReason::Type EndPlayReason)</span> <span class="keyword">override</span></span>; <span class="comment">//做清理工作</span></span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">Destroyed</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//用于释放成员,调用Destroy();会立即调用</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>UActorComponent gc机制</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Begin UActorComponent Interface.</span></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">BeginPlay</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//组件RegisterComponent注册的时候,且有OwnerActor才会立即调用,一般不用</span></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">BeginDestroy</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//引擎在gc的时候调用,并不是立即调用,一般不用</span></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">EndPlay</span><span class="params">(<span class="type">const</span> EEndPlayReason::Type EndPlayReason)</span> <span class="keyword">override</span></span>; <span class="comment">//立即调用,一般这里做清理工作(注册过才会调用),且gc时还会再调用一次,一般不用</span></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">OnComponentCreated</span><span class="params">()</span> <span class="keyword">override</span></span>; <span class="comment">//组件RegisterComponent注册的时候立即调用,一般这里做初始化工作</span></span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">OnComponentDestroyed</span><span class="params">(<span class="type">bool</span> bDestroyingHierarchy)</span> <span class="keyword">override</span></span>;<span class="comment">//立即调用,一般这里做清理工作(只要DestroyComponent就会调用)</span></span><br></pre></td></tr></table></figure></li>
</ol>
<h4 id="4-2-subsystem"><a href="#4-2-subsystem" class="headerlink" title="4.2 subsystem"></a>4.2 subsystem</h4><p>为什么要使用 Subsystems</p>
<ol>
<li>更适用的生命周期<br>引擎只支持一个 GameInstance ,运行周期是整个引擎的生命周期<br>自定义 ManagerActor,生命周期一般为当前 level 的生命周期<br>Subsystems 的生命周期可以依存于Engine,Editor,World,LocalPlayer</li>
<li>更简<br>GameInstance 或者自定义 ManagerActor,需要手动维控制创建、释放<br>Subsystems 自动创建、释放,提供 Initialize()、Deinitialize(),并且可重载</li>
<li>更模块化、更优雅、更封装、更易于维护、移植复用<br>GameInstance 中将任务系统,计分系统,经济系统、对话系统等多个Manager 写在一起,会变得臃肿<br>模块间的数据访问封装不够良好,容易污染<br>不利于业务逻辑模块的复用,特别是需要进行移植的时候,以及多个插件同时都有自己的 GameInstance<br>Subsystems 可以为不同的 Manager 创建对应的Subsystems<br>如 Manager 划分,<br>任务系统Subsystem : UGameInstanceSubsystem<br>计分系统Subsystem : UGameInstanceSubsystem<br>经济系统Subsystem : UGameInstanceSubsystem<br>对话系统Subsystem : UGameInstanceSubsystem<br>更模块化,代码显得优雅<br>解耦性高,易于维护、分工协作;易于移植复用<br>模块间的数据访问具有更好的封装性</li>
<li>更友好的访问接口<br>Subsystem 更像以全局变量的形式来访问<br>提供了 Python 脚本的访问,用于编写编辑器脚本或编写测试代码</li>
<li>Subsystem 无需覆盖引擎类。<br>一套可以定义、自动实例化和释放的类的框架。可以将其理解为 GamePlay 级别的 Component<table>
<thead>
<tr>
<th>subsystem</th>
<th>定义及用法</th>
</tr>
</thead>
<tbody><tr>
<td>UEngineSubsystem</td>
<td>代表引擎,数量1,editor或runtime模式下都是全局唯一,进程开始时创建,进程退出时销毁</td>
</tr>
<tr>
<td>UEditorSubsystem</td>
<td>代表编辑器,数量1,只在editor模式下存在,editor创建时创建,editor销毁时销毁</td>
</tr>
<tr>
<td>UGameInstanceSubsystem</td>
<td>代表一场游戏,数量1。runtime或pie模式下都算,一场游戏可能会涉及到多个world切换;游戏开始时创建,游戏退出时销毁</td>
</tr>
<tr>
<td>UWorldSubsystem</td>
<td>代表世界,数量可能>=1,生命周期与归属的world有关</td>
</tr>
<tr>
<td>ULocalPlayerSubsystem</td>
<td>代表本地玩家,数量可能>=1,UE支持本地分屏多玩家游戏,LocalPlayer往往和PlayerController一起访问,但其生命周期与GameInstance对齐(默认一开始就创建好一定数量的本地玩家);或者说其生命周期与具体的LocalPlaer相关,因为可以调用AddPlayer</td>
</tr>
</tbody></table>
</li>
</ol>
<h4 id="4-3-模块"><a href="#4-3-模块" class="headerlink" title="4.3 模块"></a>4.3 模块</h4><h4 id="4-3-1-定义"><a href="#4-3-1-定义" class="headerlink" title="4.3.1 定义"></a>4.3.1 定义</h4><p>模块是通过C#源文件声明的,扩展名为.build.cs,存储在项目的 源(Source) 目录下。属于一个模块的C++源代码与.build.cs文件并列存储,或者存储在它的子目录中。每个.build.cs文件都声明一个类,从ModuleRules基类衍生而来,并设置属性来控制如何从其构造函数进行构建。</p>
<h4 id="4-3-2-引擎Source目录下分为以下模块:"><a href="#4-3-2-引擎Source目录下分为以下模块:" class="headerlink" title="4.3.2 引擎Source目录下分为以下模块:"></a>4.3.2 引擎Source目录下分为以下模块:</h4><table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>Developer</td>
<td>Editor、Programs会使用,但不能是Games</td>
</tr>
<tr>
<td>Editor</td>
<td>只被Editor使用</td>
</tr>
<tr>
<td>Programs</td>
<td>独立的Applitcations或者工具类</td>
</tr>
<tr>
<td>Runtime</td>
<td>Editor,Games,Programs都会使用</td>
</tr>
<tr>
<td>ThirdParty</td>
<td>第三方库</td>
</tr>
</tbody></table>
<h4 id="4-3-3-其他"><a href="#4-3-3-其他" class="headerlink" title="4.3.3 其他"></a>4.3.3 其他</h4><ol>
<li>模块之间的使用类似于引用库,需要在.cs里面声明引入了其他模块</li>
<li>模块接口 IModuleInterface<br>模块加载函数 StartupModule()<br>模块卸载函数 ShutdownModule()</li>
<li>一个插件可以有多个模块,但是有且只有一个主模块</li>
<li>虚幻引擎通过在磁盘上搜索 .uplugin 文件来查找插件。将此类文件称为 插件描述文件。运行此类程序时,引擎、编辑器和 UnrealBuildTool(UBT)将自动发现并自动加载插件描述文件。</li>
<li>uproject 和 uplugin 很像,都是json格式,具体格式可参考官方文档。</li>
</ol>
</div>
<a type="button" href="/2022/07/24/basic concpts in UE4/#more" class="btn btn-default more">Read More</a>
</div>
</div>
<!-- pagination -->
<div>
<center>
<div class="pagination">
</div>
</center>
</div>
</div> <!-- col-md-9 -->
<div class="col-md-3">
<div id="sidebar">
<div id="site_search">
<div class="form-group">
<input type="text" id="local-search-input" name="q" results="0" placeholder="Search" class="st-search-input st-default-search-input form-control"/>
</div>
<div id="local-search-result"></div>
</div>
<div class="widget">
<h4>Categories</h4>
<ul class="tag_box inline list-unstyled">
<li><a href="/categories/UE4/">UE4<span>2</span></a></li>
</ul>
</div>
<div class="widget">
<h4>Recent Posts</h4>
<ul class="entry list-unstyled">
<li>
<a href="/2024/05/17/mayaLearning/" ><i class="fa fa-file-o"></i></a>
</li>
<li>
<a href="/2024/05/13/CharaterControlling/" ><i class="fa fa-file-o"></i></a>
</li>
<li>
<a href="/2024/05/12/BPClassLearn/" title="学习 UE 的一些基础概念" ><i class="fa fa-file-o"></i>常用且重要的蓝图类</a>
</li>
<li>
<a href="/2022/07/24/bobbieeComing/" ><i class="fa fa-file-o"></i>bobbiee is coming</a>
</li>
<li>
<a href="/2022/07/24/basic concpts in UE4/" title="学习 UE 的一些基础概念" ><i class="fa fa-file-o"></i>some basic concpts in UE4</a>
</li>
</ul>
</div>
</div> <!-- sidebar -->
</div> <!-- col-md-3 -->
</div> <!-- row-fluid -->
</div>
</div>
<div class="container-narrow">
<footer> <p>
© 2024 eddy pang's Blog
powered by <a href="http://hexo.io/" target="_blank">Hexo</a>.Theme <a href="https://github.com/Ares-X/hexo-theme-freemind.bithack" target="_blank">freemind.bithack</a>
</p>
</footer>
</div> <!-- container-narrow -->
<a id="gotop" href="#">
<span>⬆︎TOP</span>
</a>
<script src="/js/jquery.imagesloaded.min.js"></script>
<script src="/js/gallery.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/main.js"></script>
<script src="/js/search.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
(function($){
$('.fancybox').fancybox();
})(jQuery);
</script>
</body>
</html>