-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
221 lines (105 loc) · 48.3 KB
/
search.xml
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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Behaviour行为树</title>
<link href="/2024/03/06/Unity/AI/Behaviour%E8%A1%8C%E4%B8%BA%E6%A0%91/"/>
<url>/2024/03/06/Unity/AI/Behaviour%E8%A1%8C%E4%B8%BA%E6%A0%91/</url>
<content type="html"><![CDATA[<p>之前做战斗的时候,都是用的状态机实现的,从逻辑上来看比较清晰,很容易把控流程,但不够直观。所以在空闲的时间,想研究一下Behaviour Designer,拓展一下技能。</p><h3 id="关于Behaviour-Designer-行为树"><a href="#关于Behaviour-Designer-行为树" class="headerlink" title="关于Behaviour Designer 行为树"></a>关于Behaviour Designer 行为树</h3><p>官方介绍:</p><p>Behavior Designer是一个为每个人-程序员,艺术家,设计师实现设计的行为树。Behavior Designer提供了一个强大的API,允许您轻松创建新任务。它提供了一个直观的可视化编辑器,具有广泛的第三方集成,使得无需编写一行代码就可以创建复杂的ai。</p><p>行为树有一些比较重要的概念,例如:如任务类型(动作、复合、条件和装饰)。</p><h3 id="行为树面板介绍"><a href="#行为树面板介绍" class="headerlink" title="行为树面板介绍"></a>行为树面板介绍</h3><p>初始界面是这样的:<br><img src="/postimg/Behaviour/1.png" alt="1" ></p><p>下面截图分为四部分:</p><ol><li>第1部分流程节点渲染绘制区域,在此面板创建行为树</li><li>第2部分是参数熟悉面板,可以编辑行为树的特定熟悉、添加新任务、创建新变量或者编辑任务的参数第2部分是一个属性面板。在属性面板中,您可以编辑行为树的特定属性、添加新任务、创建新变量或编辑任务的参数。</li><li>第3部分是工具栏,可以添加删除行为树等</li><li>第4部分是调试工具栏。可以运行、暂停、步近Unity。也有行为树错误数量的显示</li></ol><img src="/postimg/Behaviour/2.png" alt="2" ><h3 id="操作工具栏说明:"><a href="#操作工具栏说明:" class="headerlink" title="操作工具栏说明:"></a>操作工具栏说明:</h3><img src="/postimg/Behaviour/3.png" alt="3" ><ul><li>标签1:在你打开的行为树之间来回导航</li><li>标签2:列出场景或项目中的所有行为树(包括预制件)</li><li>标签3:列出场景中添加了行为树组件的任何游戏对象</li><li>标签4:列出从标签3中选择的附加到GameObject的任何行为树。</li><li>标签5:列出当前行为树引用的任何外部行为树</li><li>标签6:删除当前选择的行为树。</li><li>标签7:向GameObject添加一个新的行为树。</li><li>标签8:保持当前行为树活动,即使你在层次结构或项目窗口中选择了不同的游戏对象</li><li>标签9:将行为树导出到外部行为树资产。</li><li>标签10:打开查找对话框,可以搜索你的行为树。</li><li>标签11:获取当前行为树的截图。</li><li>标签12:显示行为设计者的偏好。</li></ul><h3 id="创建简单的自定义行为树"><a href="#创建简单的自定义行为树" class="headerlink" title="创建简单的自定义行为树"></a>创建简单的自定义行为树</h3><p>创建行为树需要选择一个GameObject,在行为树面板上会显示选择的GameObject</p><img src="/postimg/Behaviour/4.png" alt="4" ><p>可以根据在上述1部分,右键创建一个行为树,选择的GameObject会自动添加Behaviour Tree组件</p><img src="/postimg/Behaviour/5.png" alt="5"><p>自定义一个<code>Conditional</code>:</p><figure class="highlight csharp"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> BehaviorDesigner.Runtime.Tasks;</span><br><span class="line"><span class="keyword">using</span> BehaviorDesigner.Runtime;</span><br><span class="line"><span class="keyword">using</span> UnityEngine;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TestContional</span> : <span class="title">Conditional</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">public</span> SharedFloat randomNum;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> TaskStatus <span class="title">OnUpdate</span>()</span></span><br><span class="line"> {</span><br><span class="line"> randomNum = Random.Range(<span class="number">0</span>, <span class="number">10</span>);</span><br><span class="line"> <span class="keyword">if</span> (randomNum.Value > <span class="number">5</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> TaskStatus.Success;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> TaskStatus.Failure;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>自定义一个<code>Action</code>:</p><figure class="highlight csharp"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> BehaviorDesigner.Runtime;</span><br><span class="line"><span class="keyword">using</span> BehaviorDesigner.Runtime.Tasks;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TestAction</span> : <span class="title">Action</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">public</span> SharedTransform target;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> TaskStatus <span class="title">OnUpdate</span>()</span></span><br><span class="line"> {</span><br><span class="line"> target.Value.transform.Translate(<span class="number">1</span>, <span class="number">1</span>,<span class="number">1</span> );</span><br><span class="line"> <span class="keyword">return</span> TaskStatus.Success;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="/postimg/Behaviour/6.png" alt="6" ><p>将创建的BD挂到空节点,并重置坐标:</p><img src="/postimg/Behaviour/7.png" alt="7"><p>运行调试BD:</p><p>此时随机数是4,条件不满足:</p><img src="/postimg/Behaviour/8.png" alt="8" ><p>重新调试,此时随机数是7,满足条件,执行Action,节点坐标发生变化:</p><img src="/postimg/Behaviour/9.png" alt="9" >]]></content>
<categories>
<category> Unity </category>
<category> AI </category>
</categories>
</entry>
<entry>
<title>UGUI渲染顺序</title>
<link href="/2024/03/03/Unity/UI/UGUI%E6%B8%B2%E6%9F%93%E9%A1%BA%E5%BA%8F/"/>
<url>/2024/03/03/Unity/UI/UGUI%E6%B8%B2%E6%9F%93%E9%A1%BA%E5%BA%8F/</url>
<content type="html"><![CDATA[<h2 id="UGUI渲染顺序"><a href="#UGUI渲染顺序" class="headerlink" title="UGUI渲染顺序"></a>UGUI渲染顺序</h2><p><strong>1,当有多个canvas并且渲染模式都为Overlay。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这种情况下,渲染顺序是由canvas组件下的Sort Order决定的,值越大的越后渲染。</span><br></pre></td></tr></table></figure><p><strong>2,当有多个canvas并且渲染模式都为Overlay。</strong></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></pre></td><td class="code"><pre><span class="line">这种情况下,渲染顺序是由canvas组件下的Sort Order决定的,值越大的越后渲染。</span><br><span class="line">如果Depth值相同,那么由canvas组件下的Sortint Layer顺序决定,顺序越后则越后渲染。</span><br><span class="line">如果Depth值和Layer值都相同的情况下,渲染顺序由Order in Layer决定,值越大越后渲染。 (注意:若Rendener Camera都是同一个摄像机,则不考虑Depth情况)</span><br></pre></td></tr></table></figure><p><strong>3,当有多个canvas并且渲染模式都为World。</strong></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></pre></td><td class="code"><pre><span class="line">这种情况下,渲染顺序由canvas组件下的Sortint Layer顺序决定,顺序越后则越后渲染。</span><br><span class="line">如果Layer值都相同的情况下,渲染顺序由Order in Layer决定,值越大越后渲染。</span><br><span class="line">特别注意,当Layer和Order值都相同的情况下,此时渲染顺序由canvas距离Render Camera的距离决定,**距离越近越后渲染。**( 只有World模式有这种情况,因其他模式下canvas都是位置固定不可移动的。并且以上情况只考虑canvas都出现在Render Camera摄像范围的情况下。)</span><br></pre></td></tr></table></figure><p><strong>4,当有多个canvas并且渲染模式都存在的情况下</strong>。</p><figure class="highlight plaintext"><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">这种情况下,首先Overlay模式的canvas永远是最后渲染,并且同为Overlay模式的canvas在Sort Order的值越大时越后渲染。</span><br><span class="line">其次,Camera和Overlay同时存在的情况下有两种情况:若使用的不同的相机,则由摄像机的Depth决定,值越大越后渲染。若使用的是相同的相机,则是由canvas距离摄像机的距离决定的,距离越近的越后渲染。</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Unity </category>
<category> UI </category>
</categories>
</entry>
<entry>
<title>UGUI中Rebatch和Rebuild</title>
<link href="/2024/03/03/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/UGUI%E4%B8%ADRebatch%E5%92%8CRebuild/"/>
<url>/2024/03/03/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/UGUI%E4%B8%ADRebatch%E5%92%8CRebuild/</url>
<content type="html"><![CDATA[<h2 id="Unity-UGUI-Rebatch和Rebuild"><a href="#Unity-UGUI-Rebatch和Rebuild" class="headerlink" title="Unity UGUI Rebatch和Rebuild"></a>Unity UGUI Rebatch和Rebuild</h2><p>在Unity中,<code>UGUI(Unity GUI)</code>是一种用于创建用户界面的系统。当使用UGUI时,有两个重要的方法可以用于更新UI元素:<code>Rebatch</code>和<code>Rebuild</code>。</p><p><code>Rebatch:Rebatch</code>是<code>UGUI</code>的一个方法,它用于重新分配和重新创建UI元素的渲染批次,<code>Rebatch</code>发生在C++层面,是指Canvas分析UI节点生成最优批次的过程,节点数量过多会导致算法(贪心策略)耗时较长。对应<code>SetVerticesDirty</code>,当一个<code>canvas</code>中包含的<code>mesh</code>发生改变时就触发,例如<code>SetActive、transform</code>的改变、 颜色改变、文本内容改变等等,<code>canvas</code>独立处理,互相不影响。消耗在对meshes按照深度和重叠情况排序、共享材质的检测等。</p><p>当UI元素的属性(如颜色、位置等)发生变化时,可以使用<code>Rebatch</code>方法来通知系统重新组织和重绘UI元素,以优化渲染性能。使用<code>Rebatch</code>不会对布局进行重新计算,而只会重新创建和排序渲染批次。</p><p><code>Batch</code>以<code>Canvas</code>为单位,同一个<code>Canvas</code>下的UI元素最终都会被<code>Batch</code>到一个<code>Mesh</code>中。<code>Batch</code>前,UGUI根据UI材质以及渲染顺序重排,在不改变渲染结果的前提下,尽可能将相同材质的UI元素合并在同一个<code>SubMesh</code>中,以减少DC。<code>Batch</code>只在UI元素发生变化时进行,合成的Mesh越大,耗时越大。重建对<code>Canvas</code>下所有ui元素生效,不论是否修改过。</p><p>5.2之后底层是多线程的,考虑到现在手机上都是多核,这部分消耗可能会小很多。</p><p><code>Rebuild:Rebuild</code>是<code>UGUI</code>的另一个方法,它用于完全重新构建UI元素的布局和渲染。当UI元素的结构发生变化时,如添加、删除、调整子元素等,可以使用<code>Rebuild</code>方法来重建整个UI元素的布局和渲染。<code>Rebuild</code>方法会触发布局计算、重新分配网格、重新创建渲染批次等步骤,以确保UI元素按照新的结构正确渲染。</p><p><code>Rebuild</code>发生在C#层面,是指<code>UGUI</code>库中<code>layout组件</code>调整<code>RectTransform</code>尺寸、<code>Graphic组件</code>更新<code>Material</code>,以及<code>Mask</code>执行<code>Cull</code>的过程,耗时和发生变化的节点数量基本呈线性相关。</p><p>只有<code>LayoutGroup</code>的直接子节点,并且是 <code>Graphic</code>类型的(比如 <code>Image</code> 和 <code>Text</code>)会触发<code>SetLayoutDirty</code>。</p><p><code>Graphic</code>改变的原因包括,基本的大小、旋转以及文字的变化、图片的修改等等,对应<code>SetMaterialDirty</code>。</p><p>需要注意的是,虽然<code>Rebuild</code>方法在某些情况下很有用,但它的调用会较重量级,并且可能会导致性能下降,特别是在频繁调用的情况下。因此,在应用中应该谨慎使用<code>Rebuild</code>方法,并尽量避免不必要的调用。</p><p>综上所述,<code>Rebatch</code>用于重新分配和重绘UI元素的渲染批次,而<code>Rebuild</code>用于完全重建UI元素的布局和渲染。根据具体的需求和情况,选择适合的方法来更新和优化UI元素的渲染。</p>]]></content>
<categories>
<category> 性能优化 </category>
<category> Unity性能优化 </category>
</categories>
</entry>
<entry>
<title>第二章 标识符</title>
<link href="/2024/02/25/%E5%9B%BE%E8%A7%A3%E6%95%99%E7%A8%8B/%E7%AC%AC%E4%BA%8C%E7%AB%A0/"/>
<url>/2024/02/25/%E5%9B%BE%E8%A7%A3%E6%95%99%E7%A8%8B/%E7%AC%AC%E4%BA%8C%E7%AB%A0/</url>
<content type="html"><![CDATA[<h1 id="2-1-一个简单的C-程序"><a href="#2-1-一个简单的C-程序" class="headerlink" title="2.1 一个简单的C#程序"></a>2.1 一个简单的C#程序</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SimplaProgram.cs</span><br></pre></td></tr></table></figure><figure class="highlight csharp"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> Systme; <span class="comment">// 告诉编译器这个程序使用 Systme 命名空间的 类型 </span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">Simple</span> <span class="comment">// 声明一个新命名空间 Simple 大括号以内都是命名空间的成员</span></span><br><span class="line">{</span><br><span class="line"><span class="keyword">class</span> <span class="title">Program</span> <span class="comment">// 声明一个类</span></span><br><span class="line">{</span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>() <span class="comment">// 声明一个无返回类型的 Main 静态方法,是程序的起始点,仅限 Main 方法,其他命名无效</span></span></span><br><span class="line">{</span><br><span class="line">Console.WriteLine(<span class="string">"Hi there!"</span>);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>产生以下输出:<br><code>Hi there!</code></p><p>C#程序由一个或多个类型声明组成。程序的类型可以以任何顺序声明。以上,只声明了class类型。<br><code>命名空间</code>是与某个名称相关联的一组类型声明。SimpleProgram使用两个命名空间。创建了一个名称为<code>Simple</code>新命名空间,并在其中声明了其类<code>Program类</code>,还使用了Systme命名空间中定义的Console类。</p><h1 id="2-2-标识符"><a href="#2-2-标识符" class="headerlink" title="2.2 标识符"></a>2.2 标识符</h1><p>标识符是一种字符串,用来命名如变量、方法、参数和其他程序结构。可以使用大写和小写字母<code>CardDeck</code>、<code>PalyerHand</code>。规则如下</p><ul><li>字母和下划线(<code>a-z</code>、<code>A-Z</code>和<code>_</code>)可以用在任何位置</li><li>数字不能放在首位,可以放在其他任何地方</li><li><code>@</code>字符只能放在标识符首位。虽然允许使用,但不推荐将<code>@</code>作为常用字符<img src="/postimg/图解教程/第二章/1.png" alt="标识符允许使用的字符" width="752" height="175"></li></ul><h1 id="2-3-关键字"><a href="#2-3-关键字" class="headerlink" title="2.3 关键字"></a>2.3 关键字</h1><p>关键字是用来定义C#语言的字符串记号。如下图:<br> <img src="/postimg/图解教程/第二章/2.png" alt="关键字" width="855" height="293"><br><strong>注意:</strong></p><ul><li>关键字不能被用作变量名或任何其他形式的标识符,除非以<code>@</code>字符开始</li><li>所有C#关键字全部都由小写字母组成(但是.NET类型名使用Pascal大小写约定)</li></ul><p>上下文关键字是仅在特定的语言结构中充当关键字的标识符。有特别的含义。两者的区别是,关键字不能被用作标识符,而上下文关键字可以在代码的其他部分被用作标识符。上下文关键字如下:<br> <img src="/postimg/图解教程/第二章/3.png" alt="上下文关键" width="894" height="145"></p><h1 id="2-4-Main-程序的起始点"><a href="#2-4-Main-程序的起始点" class="headerlink" title="2.4 Main: 程序的起始点"></a>2.4 Main: 程序的起始点</h1><p>每个C#程序必须有一个类带有Main方法(函数)。在上个<code>SimpleProgram</code>程序中,被声明在Program类中。</p><ul><li>每个C#程序的可执行起始点在<code>Main</code>中的第一条指令</li><li><code>Main</code>必须首字母大写</li></ul><p><code>Main</code>的最简单形式如下:</p><figure class="highlight csharp"><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="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>()</span></span><br><span class="line">{</span><br><span class="line"><span class="comment">// 更多语句</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h1 id="2-5-空白"><a href="#2-5-空白" class="headerlink" title="2.5 空白"></a>2.5 空白</h1><p>程序中的空白指的是没有可视化输出的字符。包括:</p><ul><li>空格 <code>Space</code></li><li>制表符 <code>Tab</code></li><li>换行符</li><li>回车符</li></ul><p>例如,下面代码效果一致:</p><figure class="highlight csharp"><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="comment">// 很好的格式</span></span><br><span class="line">Main()</span><br><span class="line">{</span><br><span class="line">Console.writeLine(<span class="string">"Hi, there!"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight csharp"><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">// 连在一起</span></span><br><span class="line">Main(){Console.WriteLine(<span class="string">"Hi, there!"</span>);}</span><br></pre></td></tr></table></figure><h1 id="2-6-语句"><a href="#2-6-语句" class="headerlink" title="2.6 语句"></a>2.6 语句</h1><p>介绍语句的常用形式<br>语句是描述一个类型或者告诉程序去执行某个动作的一条源代码指令。</p><ul><li>简单语句以一个分号结束,例如:</li></ul><figure class="highlight csharp"><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="built_in">int</span> var1 = <span class="number">5</span>;</span><br><span class="line">System.Console.WriteLine(<span class="string">"The value of var1 is {0}"</span>, var1);</span><br></pre></td></tr></table></figure><h2 id="块"><a href="#块" class="headerlink" title="块"></a>块</h2><p>块是一个由成对大括号包围的0条或者多条语句序列,它在语法上相当于一条语句。例如</p><figure class="highlight csharp"><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><br><span class="line"><span class="built_in">int</span> var1 = <span class="number">5</span>;</span><br><span class="line">System.Console.WriteLine(<span class="string">"The value of var1 is {0}"</span>, var1);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>语法上只需要一条语句,而你需要执行的动作无法用一条简单的语句表达情况下,考虑使用块</li><li>有些特定的程序结构只能使用块。在这些结构中,不能使用简单语句提到块</li><li>虽然简单语句以分号结束,但块后面不跟分号。<img src="/postimg/图解教程/第二章/4.png" alt="" width="658" height="130"></li></ul><h1 id="2-7-从程序中输出文本"><a href="#2-7-从程序中输出文本" class="headerlink" title="2.7 从程序中输出文本"></a>2.7 从程序中输出文本</h1><p>控制台窗口是一种简单的命令提示窗口,允许程序显示文本并从键盘接收输入。BLC提供一个<code>Console</code>类,包含了输入和输出数据到控制台窗口的方法。</p><h2 id="2-7-1-Write"><a href="#2-7-1-Write" class="headerlink" title="2.7.1 Write"></a>2.7.1 Write</h2><p><code>Write</code>是Console类的成员,把文本字符串发送到程序的控制台窗口。</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Console.Write(<span class="string">"This is trivial text."</span>);</span><br></pre></td></tr></table></figure><h2 id="2-7-2-WriteLine"><a href="#2-7-2-WriteLine" class="headerlink" title="2.7.2 WriteLine"></a>2.7.2 WriteLine</h2><p><code>WriteLine</code>是Console类的成员,在<code>Write</code>基础上,末尾添加换行符。</p><h2 id="2-7-3-格式字符串"><a href="#2-7-3-格式字符串" class="headerlink" title="2.7.3 格式字符串"></a>2.7.3 格式字符串</h2><p><code>Write</code>语句和<code>WriteLine</code>语句常规形式中可以有一个以上的参数。</p><ul><li><p>如果不只是一个参数,参数间用逗号隔开</p></li><li><p>第一个参数必须总是字符串,称为格式字符串。格式字符串可以包含替代标记。 </p></li><li><p>替代标记在格式字符串中标出位置,在输出串中该位置将用一个值来替代。</p></li><li><p>替代标记由一个整数及括住它的一对大括号组成,其中整数就是替换值的数字位置。跟着格式字符串的参数称为替换值,这些替换值从0开始编号。</p><img src="/postimg/图解教程/第二章/4.png" alt="" width="781" height="210"></li></ul><h2 id="2-7-4-多重标记和值"><a href="#2-7-4-多重标记和值" class="headerlink" title="2.7.4 多重标记和值"></a>2.7.4 多重标记和值</h2><p>在c#中,可以使用任意数量的替代标记和任意数量的值。</p><ul><li>值可以以任何顺序使用</li><li>值可以在格式字符串中替换任意次<br>例如:<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Console.WriteLine(<span class="string">"Three integers are {1} {0} and {1}"</span>, <span class="number">3</span>, <span class="number">6</span>);</span><br></pre></td></tr></table></figure></li></ul>]]></content>
<categories>
<category> 编程语言 </category>
<category> CSharp </category>
<category> C#图解教程 </category>
</categories>
</entry>
<entry>
<title>第一章 C#和.NET框架</title>
<link href="/2024/02/25/%E5%9B%BE%E8%A7%A3%E6%95%99%E7%A8%8B/%E7%AC%AC%E4%B8%80%E7%AB%A0/"/>
<url>/2024/02/25/%E5%9B%BE%E8%A7%A3%E6%95%99%E7%A8%8B/%E7%AC%AC%E4%B8%80%E7%AB%A0/</url>
<content type="html"><![CDATA[<h1 id="第一章-C-和-NET框架"><a href="#第一章-C-和-NET框架" class="headerlink" title="第一章 C#和.NET框架"></a>第一章 C#和.NET框架</h1><h2 id="1-2-1-NET框架的组成"><a href="#1-2-1-NET框架的组成" class="headerlink" title="1.2.1 .NET框架的组成"></a>1.2.1 .NET框架的组成</h2><p>.NET框架由三部分组成。执行环境称为CLR(Common Language Runtime,公共语言运行库)。CLR在运行时管理程序的执行,包括以下内容。</p><ul><li>内存管理和垃圾回收</li><li>代码安全验证</li><li>代码执行、线程管理及异常处理<img src="/postimg/图解教程/第一章/NET框架组成.png" alt=".NET框架组成" width="359" height="232"></li></ul><h2 id="1-2-2-改进的编程环境"><a href="#1-2-2-改进的编程环境" class="headerlink" title="1.2.2 改进的编程环境"></a>1.2.2 改进的编程环境</h2><ol><li>面向对象的开发环境</li><li>自动垃圾收集</li><li>互操作性</li><li>不需要COM</li><li>简化的部署</li><li>类型的安全性</li><li>基类库</li></ol><h2 id="1-2-3-编译成CIL"><a href="#1-2-3-编译成CIL" class="headerlink" title="1.2.3 编译成CIL"></a>1.2.3 编译成CIL</h2><p>.NET语言的编译器接受源代码文件,并生成名为程序集的输出文件<br> <img src="/postimg/图解教程/第一章/编译过程.png" alt="编译过程" width="499" height="283"></p><ul><li>程序集要么是可执行的,要么是DLL</li><li>程序集里的代码并不是本机代码,而是一种名称为 CIL(Common Intermediate Language,公共中间语言)的中间语言</li><li>程序集包括下列项目:</li></ul><ol><li>程序的CIL</li><li>程序中使用的类型的元数据</li><li>对其他程序集引用的元数据</li></ol><h2 id="1-4-编译成本机代码并执行"><a href="#1-4-编译成本机代码并执行" class="headerlink" title="1.4 编译成本机代码并执行"></a>1.4 编译成本机代码并执行</h2><p>程序的CIL直到它被调用才会被编译成本机代码。在运行时,CLR执行下面的步骤:</p><ul><li>检查程序集的安全特效</li><li>在内存中分配空间</li><li>把程序集中的可执行代码发送给实时编译器<code>Just-in-time,JIT</code>,把其中的一部分编译成本机代码<img src="/postimg/图解教程/第一章/编译成本机代码并执行.png" alt="编译成本机代码并执行" width="533" height="338">程序集中的可执行代码只在需要的时候由JIT编译器编译,然后它被缓存起来以备在后来的程序中执行。使用这个方法意味着不被调用的代码不会被编译成本机代码,而且被调用到的代码只被编译一次。一旦CIL被编译成本机代码,CLR就在它运行时管理它,执行像释放无主内存、检查数组边界、检查参数类型和管理异常之类的任务。有两个重要的术语由此而生。</li><li>托管代码 为.NET框架编写的代码称为托管代码 managed code,需要CLR</li><li>非托管代码 不在CLR控制下运行的代码,比如 Win32 C/C++ DLL,称为非托管代码 unmanaged code.<img src="/postimg/图解教程/第一章/编译和运行时过程.png" alt="编译和运行时过程" width="685" height="441"></li></ul><h2 id="1-5-CLR"><a href="#1-5-CLR" class="headerlink" title="1.5 CLR"></a>1.5 CLR</h2><p>.NET框架的核心组件是CLR,他在操作系统的顶层,负责管理程序的运行,提供下列服务:</p><ul><li>自动垃圾回收</li><li>安全和认证</li><li>通过访问BCL得到广泛的编程功能,包括如Web服务和数据服务之类的功能<img src="/postimg/图解教程/第一章/CLR概览.png" alt="CLR概览" width="701" height="385"></li></ul><h2 id="1-7-各种缩写"><a href="#1-7-各种缩写" class="headerlink" title="1.7 各种缩写"></a>1.7 各种缩写</h2> <img src="/postimg/图解教程/第一章/各种缩写.png" alt="各种缩写" width="708" height="309">]]></content>
<categories>
<category> 编程语言 </category>
<category> CSharp </category>
<category> C#图解教程 </category>
</categories>
</entry>
<entry>
<title>网络基础概念</title>
<link href="/2024/02/25/Unity/%E7%BD%91%E7%BB%9C/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5/"/>
<url>/2024/02/25/Unity/%E7%BD%91%E7%BB%9C/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5/</url>
<content type="html"><![CDATA[<h3 id="网络是什么?"><a href="#网络是什么?" class="headerlink" title="网络是什么?"></a>网络是什么?</h3><p>利用通信线路和通信设备,将地理位置不同的、功能独立的多台计算机互连起来,以功能完善的网络软件来实现资源共享和信息传递,就构成了计算机网络系统。</p><h3 id="网络通信是指什么?"><a href="#网络通信是指什么?" class="headerlink" title="网络通信是指什么?"></a>网络通信是指什么?</h3><p> 计算设备之间通过网络交换数据,更通俗地说法就是:主机A上的某个程序(进程)与主机B上的某个程 序(进程)进行数据交换。 </p><h3 id="网络通信如何实现?"><a href="#网络通信如何实现?" class="headerlink" title="网络通信如何实现?"></a>网络通信如何实现?</h3><p> 计算设备之间通过共同遵守的 网络协议(network protocol) ,以约定好的规则来交换数据。 </p><h3 id="计算机网络体系结构:"><a href="#计算机网络体系结构:" class="headerlink" title="计算机网络体系结构:"></a>计算机网络体系结构:</h3><ul><li>OSI七层协议:概念清楚,理论完整,但它复杂不实用。 </li><li>TCP/IP四层协议:应用非常广泛。实质上,TCP/IP只有上面三层,最下层的网络接口层并没有什么 具体内容。</li><li>五层协议的体系结构<br>综合前面两者,我们一般采用五层协议的体系结构来学习理解计算机网络原理。</li></ul><h3 id="五层协议功能划分-主要功能概述-:"><a href="#五层协议功能划分-主要功能概述-:" class="headerlink" title="五层协议功能划分(主要功能概述):"></a>五层协议功能划分(主要功能概述):</h3><ul><li>应用层:直接为用户的应用进程提供服务。这一层的协议很多,比如HTTP协议(浏览器)、SMTP 协议(邮件)、FTP协议(文件传输)等。</li><li>运输层:运输应用层的数据,多个应用进程可同时使用运输层的服务,以及分发运输层的信息到应 用层中相应的进程上。运输层主要使用两种协议: <ul><li>传输控制协议TCP(Transmission Control Protocol): <ul><li>面向连接 ,以报文段(segment)为传输单位,保证传输的可靠性。</li></ul></li><li>用户数据报协议UDP(User Datagram Protocol): <ul><li>无连接 以用户数据报为传输单位,不保证传输的可靠性。</li></ul></li></ul></li><li>网络层:把运输层的报文段或用户数据报封装成 分组或包 进行传送。网络层使用IP协议,因此分组 也叫作 IP数据报 ,简称数据报。此外网络层还要选择合适的路由,使运输层里的数据通过网络中的 路由器找到目的主机。 </li><li>数据链路层:数据在网络上传输时总是在一段一段的链路上传送的(主机和路由器之间或者两个路 由器之间),这时需要链接层的协议将网络层交下来的IP数据报组装成 帧(framing) ,以便在相 邻的链路之间传送。数据帧里包含了必要的 传输控制信息 。 </li><li>物理层:在物体层上所传数据就是比特流。用不同的电压代表「0」或「1」,在硬件设备上实现数 据传输。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">注意:现在我们常提到的TCP/IP并不一定单指TCP和IP两个具体的协议,而是指组成因特网时所使 用的整个 TCP/IP协议族 (protocol suite),还包括了其它协议,比如:DNS协议(域名转换为IP 地址)、ARP协议(IP地址转换为mac地址)等等。 </span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Unity </category>
<category> 网络 </category>
</categories>
</entry>
<entry>
<title>关于Stream流</title>
<link href="/2024/02/25/Unity/%E5%BA%8F%E5%88%97%E5%8C%96/%E5%85%B3%E4%BA%8EStream%E6%B5%81/"/>
<url>/2024/02/25/Unity/%E5%BA%8F%E5%88%97%E5%8C%96/%E5%85%B3%E4%BA%8EStream%E6%B5%81/</url>
<content type="html"><![CDATA[<h1 id="关于Stream"><a href="#关于Stream" class="headerlink" title="关于Stream"></a>关于Stream</h1><p><code>Stream stream = response.GetResponseStream()</code>在Unity 2022版本中,<code>Stream</code>对象不再直接提供<code>Length</code>属性来获取流的长度。相反,您可以使用<code>Stream</code>对象的其他方法来获取流的长度。在Unity 2019版本中可以正常使用<code>Length</code>属性,这可能是由于Unity使用了不同的解析器或实现方式。您可以通过使用<code>stream.Read</code>方法来迭代流的内容,并计算读取的字节数来获得流的长度。另外,还可以使用<code>stream.Seek</code>方法将流的位置设置到流的末尾,然后使用<code>stream.Position</code>属性来获取流的长度。这两种方法都能在Unity 2022版本中获得流的长度。<br>在Unity 2022版本中,获取<code>Response Stream</code>的长度可以使用以下代码:</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">Stream stream = response.GetResponseStream();</span><br><span class="line"><span class="built_in">byte</span>[] buffer = <span class="keyword">new</span> <span class="built_in">byte</span>[<span class="number">4096</span>]; <span class="comment">// 缓冲区大小可以根据需要进行调整</span></span><br><span class="line"><span class="built_in">int</span> totalBytesRead = <span class="number">0</span>;</span><br><span class="line"><span class="built_in">int</span> bytesRead;</span><br><span class="line"><span class="keyword">while</span> ((bytesRead = stream.Read(buffer, <span class="number">0</span>, buffer.Length)) > <span class="number">0</span>)</span><br><span class="line">{</span><br><span class="line"> totalBytesRead += bytesRead;</span><br><span class="line">}</span><br><span class="line"><span class="built_in">int</span> streamLength = totalBytesRead;</span><br></pre></td></tr></table></figure><p>上述代码创建了一个缓冲区,并使用<code>stream.Read()</code>方法循环读取数据,不断累加已读取的字节数。最后,<code>streamLength</code>变量将保存<code>Response Stream</code>的长度。请注意,此方法适用于读取二进制数据流。如需获取文本数据流的长度,可根据具体情况将缓冲区设置为适当的文本编码。</p>]]></content>
<categories>
<category> Unity </category>
<category> 序列化 </category>
</categories>
</entry>
<entry>
<title>判断UI元素超出屏幕</title>
<link href="/2024/02/25/Unity/UI/%E5%88%A4%E6%96%ADUI%E5%85%83%E7%B4%A0%E8%B6%85%E5%87%BA%E5%B1%8F%E5%B9%95/"/>
<url>/2024/02/25/Unity/UI/%E5%88%A4%E6%96%ADUI%E5%85%83%E7%B4%A0%E8%B6%85%E5%87%BA%E5%B1%8F%E5%B9%95/</url>
<content type="html"><![CDATA[<h1 id="判断UI元素超出屏幕"><a href="#判断UI元素超出屏幕" class="headerlink" title="判断UI元素超出屏幕"></a>判断UI元素超出屏幕</h1><p>这里只判断UI元素的RectTransform,不判断实际UI元素实际绘制区域,代码如下</p><figure class="highlight lua"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">local</span> halfW = <span class="number">121</span></span><br><span class="line"><span class="keyword">local</span> halfH = <span class="number">50</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">GuideDesPosView:CalcUiBound</span><span class="params">()</span></span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> <span class="built_in">self</span>.m_desPos <span class="keyword">then</span></span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> value = Camera.main:WorldToScreenPoint(<span class="built_in">self</span>.m_desPos)</span><br><span class="line"> <span class="keyword">local</span> x = value.x</span><br><span class="line"> <span class="keyword">local</span> y = value.y</span><br><span class="line"> <span class="keyword">local</span> z = value.z</span><br><span class="line"> <span class="keyword">if</span> x == <span class="built_in">self</span>.m_lastX <span class="keyword">and</span> y == <span class="built_in">self</span>.m_lastY <span class="keyword">and</span> z == <span class="built_in">self</span>.m_lastZ <span class="keyword">then</span></span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> z < <span class="number">0</span> <span class="keyword">then</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">self</span>.contentTrans.gameObject.activeSelf <span class="keyword">then</span></span><br><span class="line"> <span class="built_in">self</span>.contentTrans.gameObject:SetActive(<span class="literal">false</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> <span class="keyword">elseif</span> z >= <span class="number">0</span> <span class="keyword">then</span></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">self</span>.m_lastZ >= <span class="number">0</span> <span class="keyword">then</span></span><br><span class="line"> <span class="built_in">self</span>.contentTrans.gameObject:SetActive(<span class="literal">true</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> scaleX = <span class="number">1920</span> / Screen.width</span><br><span class="line"> <span class="keyword">local</span> scaleY = <span class="number">1080</span> / Screen.height</span><br><span class="line"></span><br><span class="line"> <span class="built_in">self</span>.m_lastX = x</span><br><span class="line"> <span class="built_in">self</span>.m_lastY = y</span><br><span class="line"> <span class="built_in">self</span>.m_lastZ = z</span><br><span class="line"> <span class="keyword">if</span> (value.x + halfW > Screen.width) <span class="keyword">then</span></span><br><span class="line"> x = Screen.width - halfW</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (value.x - halfW < <span class="number">0</span>) <span class="keyword">then</span></span><br><span class="line"> x = halfW</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (value.y - halfH < <span class="number">0</span>) <span class="keyword">then</span></span><br><span class="line"> y = halfH</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (value.y + halfH > Screen.height) <span class="keyword">then</span></span><br><span class="line"> y = Screen.height - halfH</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">self</span>.contentRectTrans.localPosition = Vector3((x - Screen.width / <span class="number">2</span>) * scaleX, (y - Screen.height / <span class="number">2</span>) * scaleY, <span class="number">0</span>)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Unity </category>
<category> UI </category>
</categories>
</entry>
<entry>
<title>Untiy性能优化小结</title>
<link href="/2024/02/25/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/Untiy%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E5%B0%8F%E7%BB%93/"/>
<url>/2024/02/25/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/Untiy%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E5%B0%8F%E7%BB%93/</url>
<content type="html"><![CDATA[<h1 id="MemeoryProfiler-dddd"><a href="#MemeoryProfiler-dddd" class="headerlink" title="MemeoryProfiler dddd"></a>MemeoryProfiler dddd</h1><p>在Unity中,Memory Profiler(内存分析器)提供了Compare Snapshots(比较快照)功能,用于比较两个不同时间点的内存快照数据。通过比较内存快照,可以了解对象在不同时间点的内存使用情况,帮助进行内存优化和泄漏调试。</p><p>在使用Memory Profiler的Compare Snapshots功能时,可以设置是否启用Managed选项。Managed选项用于指定是否包含托管堆(managed heap)中的数据。默认情况下,Managed选项是启用的,这表示内存快照会包括托管堆中的对象信息。</p><p>如果禁用了Managed选项,比较快照时将不会包含托管堆中的对象信息,只会分析非托管资源的内存使用情况。这在一些特定的情况下可能会更有用,例如只关注引起内存泄漏的非托管资源时。</p><p>通过在Memory Profiler中使用Compare Snapshots功能,并根据需求选择启用或禁用Managed选项,能更好地识别和解决游戏中的内存问题,提升Unity项目的性能和效率。</p><img src="/postimg/Unity性能优化/MemeoryProfiler.png" alt="Memory Profiler" width="500" height="400">]]></content>
<categories>
<category> 性能优化 </category>
<category> Unity性能优化 </category>
</categories>
</entry>
<entry>
<title>OpenGL资料</title>
<link href="/2024/02/25/%E5%9B%BE%E5%BD%A2%E6%B8%B2%E6%9F%93/OpenGL%E8%B5%84%E6%96%99/"/>
<url>/2024/02/25/%E5%9B%BE%E5%BD%A2%E6%B8%B2%E6%9F%93/OpenGL%E8%B5%84%E6%96%99/</url>
<content type="html"><![CDATA[<h1 id="资料"><a href="#资料" class="headerlink" title="资料"></a>资料</h1><p><a href="https://learnopengl-cn.github.io/">https://learnopengl-cn.github.io/</a></p>]]></content>
<categories>
<category> 图形渲染 </category>
<category> 资料推荐 </category>
</categories>
</entry>
</search>