<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Unity 归档 - 初晴神社</title>
	<atom:link href="https://vki.cc/tag/unity/feed/" rel="self" type="application/rss+xml" />
	<link>https://vki.cc/tag/unity/</link>
	<description>白露的博客</description>
	<lastBuildDate>Fri, 30 Jul 2021 15:57:31 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>

<image>
	<url>https://cdn.vki.cc/wp-content/uploads/2018/03/cropped-icemaplen-1-32x32.png</url>
	<title>Unity 归档 - 初晴神社</title>
	<link>https://vki.cc/tag/unity/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Unity 3D 纹理压缩格式指南</title>
		<link>https://vki.cc/greattruth/experience/872/</link>
					<comments>https://vki.cc/greattruth/experience/872/#respond</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Fri, 30 Jul 2021 15:57:30 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[朝闻道]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[贴图]]></category>
		<guid isPermaLink="false">https://vki.cc/?p=872</guid>

					<description><![CDATA[<p>压缩纹理的主要目的是为了节省空间，缩短加载时间。针对不同的需求和平台需要不同的压缩格式，有的需要高性能，有的需要高质量，Unity本身提供了多种压缩格式供选择。</p>
<p><a href="https://vki.cc/greattruth/experience/872/">Unity 3D 纹理压缩格式指南</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p class="has-black-color has-text-color wp-block-paragraph">Unity本身支持多种贴图格式，比如jpg、png、psd等。但是当这些资源导入后，Unity会统一转化为自己的格式（非直接更改源文件），以供游戏运行时使用。</p>



<p class="has-black-color has-text-color wp-block-paragraph">压缩纹理的主要目的是为了节省空间，缩短加载时间。针对不同的需求和平台需要不同的压缩格式，有的需要高性能，有的需要高质量，Unity本身提供了多种压缩格式供选择。</p>



<h3 id="etc" class="wp-block-heading">ETC</h3>



<p class="wp-block-paragraph"><em>Ericsson Texture Compression，是由 Khronos 支持的开放标准，在移动平台中广泛采用。它是一种为感知质量设计的有损算法，其依据是人眼对亮度改变的反应要高于色度改变。类似于DXT，ETC也是把4&#215;4的像素块压缩成一个64或128位的数据块，也是有损压缩。</em></p>



<p class="has-black-color has-text-color wp-block-paragraph">ETC又分为ETC1和ETC2，通常用于Android平台。其中ETC2是较新的标准，也是Unity官方推荐的格式（虽然我还不太理解）。</p>



<p class="has-black-color has-text-color wp-block-paragraph">相对于ETC1，<strong>ETC2向前兼容，不强制要求贴图大小为2的整数次幂，且对RGB的压缩质量更好，支持透明通道。</strong>唯一的缺点是需要设备支持OpenGL ES 3.0标准。不过该标准诞生于2012年，目前不支持它的设备非常少，因此不用担心。</p>



<p class="wp-block-paragraph">注意：<em>可对具有 <a href="https://docs.unity3d.com/cn/current/Manual/HOWTO-alphamaps.html">Alpha 通道</a>的纹理使用 ETC1 格式，但仅当构建目标为 Android 且纹理放置在图集上（通过指定打包标签）时才适用。要启用此功能，请勾选纹理的 <strong>Compress using ETC1</strong> 复选框。Unity 会将生成的图集拆分为两个纹理，每个纹理都没有 Alpha 通道，然后将它们组合在渲染管线的最后部分中。</em></p>



<h3 id="pvrtc" class="wp-block-heading">PVRTC</h3>



<p class="wp-block-paragraph">PowerVR Texture Compression，PVRTC格式与基于块的压缩格式，比如S3TC、ETC的不同之处是，它使用2张双线性放大的<em>低分辨率图，根据精度和每个像素的权重，融合到一起来呈现纹理，并且2-bpp和4-bpp都支持ARGB数据。PVRTC格式压缩比高，也是有损压缩。</em></p>



<p class="has-black-color has-text-color wp-block-paragraph">PVRTC格式一般用于iOS平台，可以用在所有的iOS设备上。缺点是<strong>要求纹理的高、宽必须都是2的整数次幂（POT），最小为8，并且必须是正方形</strong>。</p>



<p class="has-vivid-red-color has-text-color wp-block-paragraph">注意：使用该格式，极端情况下会让内存占用变得更大。比如原先300*300的贴图，因为要求尺寸为2的整数次幂，所以变成512*512 . 这种情况下还不如使用RGBA16 .</p>



<h3 id="rgba16" class="wp-block-heading">RGBA16</h3>



<p class="has-black-color has-text-color wp-block-paragraph">RGBA16，即RGBA4444，每个像素2个字节，RGBA通道各占4位。</p>



<p class="has-black-color has-text-color wp-block-paragraph">相比以上压缩格式，贴图质量相对较好，缺点是内存占用大，且相对于RGBA32来说会有色彩断层问题。</p>



<h3 id="rgba32" class="wp-block-heading">RGBA32</h3>



<p class="has-black-color has-text-color wp-block-paragraph"> RGBA32，即RGBA8888，每个像素4个字节，RGBA通道各占8位。</p>



<p class="has-black-color has-text-color wp-block-paragraph">原图无压缩，质量最好 ，缺点是内存占用极大。除非美术要求极高才会使用。</p>



<p class="has-black-color has-text-color wp-block-paragraph">假如贴图没有透明通道则使用RGB24格式，少占用一个字节的空间。</p>



<h3 id="astc" class="wp-block-heading">ASTC</h3>



<p class="wp-block-paragraph"><em>ASTC 是在 OpenGL ES3.0 出现后在 2012 年中产生的一种业界领先的纹理压缩格式，它的压缩分块从 4&#215;4 到 12&#215;12 最终可以压缩到每个像素占用 1bit 以下，压缩比例有多种可选。ASTC 格式支持 RGBA，且适用于 2 的幂次方长宽等比尺寸和无尺寸要求的 NPOT（非 2 的幂次方）纹理。</em></p>



<p class="has-black-color has-text-color wp-block-paragraph">目前我最推荐使用的一种压缩格式，优点是压缩质量高，显示质量好，且Android和iOS平台都可以使用，比较省心。压缩质量从4&#215;4到12&#215;12，按需选择。</p>



<figure class="wp-block-image size-full"><img  decoding="async"  width="160"  height="261"  src="https://oss.vki.cc/wp-content/uploads/2021/07/1627659914-a905a96f-bb75-4bd8-a53a-adaaf02d9b80.png"  alt=""  class="wp-image-874"  srcset="https://cdn.vki.cc/wp-content/uploads/2021/07/1627659914-a905a96f-bb75-4bd8-a53a-adaaf02d9b80.png 160w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627659914-a905a96f-bb75-4bd8-a53a-adaaf02d9b80-120x196.png 120w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627659914-a905a96f-bb75-4bd8-a53a-adaaf02d9b80-90x147.png 90w"  sizes="(max-width: 160px) 100vw, 160px" ></figure>



<p class="has-black-color has-text-color wp-block-paragraph">缺点和ETC2差不多，老设备不支持。其中iOS设备从iPhone 5s才开始支持，Android主流压缩格式也正在从ETC2转向ASTC（这也是我不太理解Unity还在推荐ETC2的原因）。另一个小缺点是压缩时间稍长，不过也不是问题。</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>所以长期来看，ASTC将一统江湖！</strong></p>



<h2 id="%e7%bb%93%e8%ae%ba" class="wp-block-heading">结论</h2>



<p class="has-black-color has-text-color wp-block-paragraph">综上来看，新项目的贴图基本可以无脑使用ASTC，这里有张图，有个大佬总结出来的。</p>



<figure class="wp-block-image size-full"><img  fetchpriority="high"  decoding="async"  width="720"  height="337"  src="https://oss.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316.jpg"  alt=""  class="wp-image-876"  srcset="https://cdn.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316.jpg 720w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316-120x56.jpg 120w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316-90x42.jpg 90w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316-320x150.jpg 320w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660332-8650276a-f037-48d0-a24c-48714dc8e316-560x262.jpg 560w"  sizes="(max-width: 720px) 100vw, 720px" ></figure>



<figure class="wp-block-image size-full"><img  decoding="async"  width="618"  height="100"  src="https://oss.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11.png"  alt=""  class="wp-image-877"  srcset="https://cdn.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11.png 618w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11-120x19.png 120w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11-90x15.png 90w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11-320x52.png 320w, https://cdn.vki.cc/wp-content/uploads/2021/07/1627660356-adfe9ed4-3dd1-42a9-8d7d-b03aa74aab11-560x91.png 560w"  sizes="(max-width: 618px) 100vw, 618px" ></figure>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>不过尽管ASTC支持非二次幂纹理，但在时机开发中还是建议UI及美术尽量制作二次幂纹理。</strong></p>



<p class="wp-block-paragraph">具体可参考：<a href="https://www.zhihu.com/question/376921536/answer/1063272336" target="_blank" rel="noreferrer noopener">https://www.zhihu.com/question/376921536/answer/1063272336</a></p>
<p><a href="https://vki.cc/greattruth/experience/872/">Unity 3D 纹理压缩格式指南</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/experience/872/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Unity 内存管理</title>
		<link>https://vki.cc/greattruth/engine/731/</link>
					<comments>https://vki.cc/greattruth/engine/731/#respond</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Wed, 22 Jul 2020 12:10:38 +0000</pubDate>
				<category><![CDATA[引擎相关]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[内存]]></category>
		<category><![CDATA[原创]]></category>
		<guid isPermaLink="false">https://bye6.cc/?p=731</guid>

					<description><![CDATA[<p>我胡汉三又回来啦！~ 内存交换 标准交换在内存与备份存储之间移动进程，备份存储通常是快速磁盘，它应足够大，以容纳所有用户的所有内存映像的副本，并且它应提供对这些存储器映像的直接访问。 移动设备不支&#8230;</p>
<p><a href="https://vki.cc/greattruth/engine/731/">Unity 内存管理</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<pre class="wp-block-preformatted">我胡汉三又回来啦！~</pre>



<h4 class="wp-block-heading" id="o8CfU"><span id="%e5%86%85%e5%ad%98%e4%ba%a4%e6%8d%a2">内存交换</span></h4>



<p class="has-text-align-left has-black-color has-text-color wp-block-paragraph">标准交换在内存与备份存储之间移动进程，备份存储通常是快速磁盘，它应足够大，以容纳所有用户的所有内存映像的副本，并且它应提供对这些存储器映像的直接访问。</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>移动设备不支持任何形式的内存交换。</strong></p>



<ul class="wp-block-list"><li>移动设备通常采用闪存，而不是空间更大的硬盘作为它的永久存储。导致的空间约束是移动操作系统设计者避免交换的原因之一；</li><li>闪存写入次数的限制；</li><li>内存与闪存之间的吞吐量差；</li></ul>



<p class="has-black-color has-text-color wp-block-paragraph">当空闲内存降低到一定阈值以下时：</p>



<ul class="wp-block-list"><li>iOS：不釆用交换，而是要求应用程序自愿放弃分配的内存。只读数据（如代码）可从系统中删除，以后如有必要再从闪存重新加载。已修改的数据（如堆栈）不会被删除。然而，操作系统可以终止任何未能释放足够内存的应用程序。</li><li>Android：不支持交换，釆用类似 iOS 使用的策略。如果没有足够可用的空闲内存，则它可以终止进程。然而，在终止进程之前，Android 将其应用程序状态写到闪存，以便它能快速重新启动。</li></ul>



<p class="has-black-color has-text-color wp-block-paragraph">iOS支持内存压缩，Android不可以。</p>



<p class="has-black-color has-text-color wp-block-paragraph">Android 内存单位为Page，大小一般为4k，以分配单位回收，分为用户态和内核态，不可越界访问。</p>



<p class="has-black-color has-text-color wp-block-paragraph">Low Memory Killier：内存杀手。</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>Android服务优先级（从高到低），当内存不够时从优先级低的开始销毁</strong>：</p>



<ul class="wp-block-list"><li>Native</li><li>System 当杀到这一层级的时候手机重启</li><li>Persistent</li><li>Foreground 前台应用，具体表现为APP闪退</li><li>Perceptible</li><li>Service</li><li>Home 桌面</li><li>Previous 上一个使用的APP</li><li>Cached 后台APP</li></ul>



<h4 class="wp-block-heading" id="36R9c"><span id="unity%e5%86%85%e5%ad%98">Unity内存</span></h4>



<p class="has-black-color has-text-color wp-block-paragraph">按类型分为 <strong>Native Memory </strong>和<strong> Managed Memory</strong></p>



<p class="has-black-color has-text-color wp-block-paragraph">Editor与Runtime不同</p>



<ul class="has-cyan-bluish-gray-color has-text-color wp-block-list"><li data-lake-id="11ad0f3d261d1bdfaad1f6170d68b6da">Editor模式会尽可能的加载资源（启动较慢）</li><li data-lake-id="920753378d0cef5c0e9628ab6efaa826">Runtime按需加载</li></ul>



<p class="has-black-color has-text-color wp-block-paragraph">Unity封装了C++中与申请内存相关的函数，并添加了Label用于统计。</p>



<h4 class="wp-block-heading" id="FzmP4"><span id="audio">Audio</span></h4>



<p class="wp-block-paragraph"><strong>DSP Buffer</strong></p>



<ul class="wp-block-list"><li data-lake-id="b320a7254b16d587a6f73bceb02ab68b">过大会导致声音有延迟</li><li data-lake-id="988feb3af3915b96c8fd2c5133f0b1ab">过小会使CPU负担上升</li></ul>



<p class="wp-block-paragraph"><strong>Force to mono</strong></p>



<p class="wp-block-paragraph">双声道改单声道（尽量，绝大多数声音不需要双声道）</p>



<p class="wp-block-paragraph"><strong>Compress Format</strong></p>



<h4 class="wp-block-heading" id="e3S92"><span id="code-size">Code Size</span></h4>



<p class="wp-block-paragraph">慎用模板泛型，</p>



<h4 class="wp-block-heading" id="UfI9X"><span id="assetbundle">AssetBundle</span></h4>



<p class="wp-block-paragraph">Type Tree</p>



<p class="wp-block-paragraph">当Unity版本与APP版本一致时可以关掉</p>



<ul class="wp-block-list"><li style="list-style-type: none;">
<ul data-lake-id="3e53979f08d5f031e7fefefd919b79c4">
<li data-lake-id="6feee38208c0af4aca7e153e5c19465c">减小内存</li>
<li data-lake-id="2f7a8c2489975976f9ad934aa76d1b4b">减小包大小</li>
<li data-lake-id="47ac6b264aafb950d9d0f23e668ee5e0">Build和Runtime变快</li>
</ul>
</li></ul>



<p class="wp-block-paragraph"><strong>压缩方式</strong></p>



<p class="wp-block-paragraph">LZ4 推荐</p>



<p class="wp-block-paragraph">LZMA 弃用</p>



<p class="wp-block-paragraph"><strong>extra</strong></p>



<p class="wp-block-paragraph">不建议每个文件打一个AssetBundle包</p>



<p class="wp-block-paragraph">因为它们有相同的“头”，仅数据部分不同，容易浪费空间。</p>



<h4 class="wp-block-heading" id="dNP1Y"><span id="resources">Resources</span></h4>



<p class="wp-block-paragraph">通过红黑树进行索引，每次启动游戏都要分析加载红黑树，拖慢启动时间。其次整个游戏生命周期都会存在与内存中。</p>



<h4 class="wp-block-heading" id="KpCjw"><span id="texture">Texture</span></h4>



<p class="wp-block-paragraph"><strong>Upload Buffer</strong></p>



<p class="wp-block-paragraph"><strong>Read&amp;Write</strong></p>



<p class="wp-block-paragraph">没有特殊需求就关掉write</p>



<p class="wp-block-paragraph"><strong>Mipmap</strong></p>



<p class="wp-block-paragraph">同样没有特殊需求就关掉</p>



<h4 class="wp-block-heading" id="x73lJ"><span id="mesh">Mesh</span></h4>



<p class="wp-block-paragraph"><strong>Read&amp;Write</strong></p>



<p class="wp-block-paragraph"><strong>Compresssion</strong></p>



<h3 class="wp-block-heading" id="rbJ5r"><span id="managed%e5%86%85%e5%ad%98">Managed内存</span></h3>



<p class="has-black-color has-text-color wp-block-paragraph">VM内存池</p>



<p class="has-black-color has-text-color wp-block-paragraph">VM会返还内存给OS</p>



<p class="has-black-color has-text-color wp-block-paragraph">条件：一个block连续6次GC没被访问到</p>



<h4 class="wp-block-heading" id="epv2S"><span id="unity-gc-%e7%ae%97%e6%b3%95">Unity GC 算法</span></h4>



<pre class="wp-block-preformatted">貌似不采用CLR的GC机制_(:з」∠)_（参见另一篇文章，传送门）</pre>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>Boehm GC</strong></p>



<p class="has-black-color has-text-color wp-block-paragraph">旧版垃圾回收方式，新版Unity已弃用。</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>不分代</strong>（速度更快）</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>不压缩</strong>（因为一些历史原因。。跟mono有关）</p>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>Incremental GC（渐进式GC）</strong></p>



<p class="has-black-color has-text-color wp-block-paragraph">Unity2019.3之后使用，新一代垃圾回收算法。</p>



<p class="has-black-color has-text-color wp-block-paragraph">主要目的为了解决旧版GC导致主线程卡顿（旧版GC时会暂停主线程）的问题，<strong>分帧解决，且分代</strong></p>



<h4 class="wp-block-heading" id="4mYDq"><span id="gc%e6%9c%ba%e5%88%b6%e8%80%83%e9%87%8f">GC机制考量</span></h4>



<ul class="wp-block-list"><li data-lake-id="660957963fddbea01fd4ec0bcda75a61">回收能力</li><li data-lake-id="13580033e8e418799d5f260ba564a88d">暂停时长</li><li data-lake-id="522b2a4651dc451b9655e3c8fdf7d6cf">碎片化</li><li data-lake-id="2547a49c18f9244054ccb157d5bc822c">额外消耗</li><li data-lake-id="fdb31eab183fabe0398e946148dd5263">可扩展性</li><li data-lake-id="f3c2da301939823205f12211aedc759a">可移植性</li></ul>



<h4 class="wp-block-heading" id="J5Onq"><span id="%e5%86%85%e5%ad%98%e7%a2%8e%e7%89%87%e5%8c%96">内存碎片化</span></h4>



<p class="has-black-color has-text-color wp-block-paragraph">内存碎片通常分为内部碎片和外部碎片：</p>



<ol class="wp-block-list"><li>内部碎片是由于采用固定大小的内存分区，当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片，通常内部碎片难以完全避免；</li><li>外部碎片是由于某些未分配的连续内存区域太小，以至于不能满足任意进程的内存分配请求，从而不能被进程利用的内存区域。</li></ol>



<p class="has-black-color has-text-color wp-block-paragraph"><strong>先加载消耗大内存的资源，再加载小内存</strong></p>



<h4 class="wp-block-heading" id="FPdj0"><span id="%e5%83%b5%e5%b0%b8%e5%86%85%e5%ad%98">僵尸内存</span></h4>



<ul class="wp-block-list"><li data-lake-id="bc5462d9e5d49a7e6c32d79622a65214">无用内存</li><li data-lake-id="14915a15a5f640a5f8e01cbe11540cca">没有释放</li><li data-lake-id="796e8d72732ba18a118b944039f28f34">可通过代码管理和性能工具分析</li></ul>



<h4 class="wp-block-heading" id="7Bfhj"><span id="setactive">SetActive</span></h4>



<p class="wp-block-paragraph">TODO。。。</p>



<p class="wp-block-paragraph">都说要少用，但是不清楚机制，有机会看一下Unity源码 Orz</p>



<h3 class="wp-block-heading" id="QSWFN"><span id="%e4%bc%98%e5%8c%96%e5%bb%ba%e8%ae%ae">优化建议</span></h3>



<ul class="wp-block-list"><li data-lake-id="d69d8eee51298fd6887027e6e0e00d34"><strong>使用Destroy，别用null<br></strong></li><li data-lake-id="f2c16401a975b5ae82b4a625bbf6f445"><strong>Class/Struct</strong></li></ul>



<ul class="wp-block-list"><li data-lake-id="d566bb88ddc562cd4fa58dc8340331bf">少于8个字节的数据可用Struct代替Class（存疑）</li></ul>



<ul class="wp-block-list"><li data-lake-id="fdc6d72d868ae679fe6380d181f3b88d"><strong>池中池</strong></li><li data-lake-id="4334e0ca514037df778864799063153d"><strong>闭包和匿名函数</strong></li></ul>



<ul class="wp-block-list"><li data-lake-id="1250b809d7a3beea6d2bac105f387a0d">少用，在IL2CPP里这些都会new class</li><li data-lake-id="413a0dbfac105ff19edbffae41a3061e"><strong>协程</strong></li></ul>



<ul class="wp-block-list"><li data-lake-id="53c02b79234a6494d0ac6d3c4caf0935">用的时候再产生，不用的时候及时终止</li><li data-lake-id="c1e7ec9e3126fc936fc53cac7fa4b6bc">不要当线程使用</li><li data-lake-id="6d7ccc3bc281cf367da7a0f4e14430ad"><strong>配置表</strong></li></ul>



<ul class="wp-block-list"><li data-lake-id="f80c86b757dd40ebb7835f06cfb868b8">excel、json等，按需加载，不然会很占用内存空间</li><li data-lake-id="200224045513b88bcbc82c20699f1adb"><strong>单例模式 Singleton</strong></li></ul>



<ul class="wp-block-list"><li data-lake-id="82ebf0cbb49cdc3719ae3174695d3c4c">慎用，生命周期较长，占用内存</li></ul>
<p><a href="https://vki.cc/greattruth/engine/731/">Unity 内存管理</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/engine/731/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C#清除委托列表的正确用法</title>
		<link>https://vki.cc/greattruth/experience/709/</link>
					<comments>https://vki.cc/greattruth/experience/709/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Fri, 26 Jul 2019 06:15:32 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<guid isPermaLink="false">https://bye6.cc/?p=709</guid>

					<description><![CDATA[<p>近期将项目Unity版本从5.6升级到了2018.4.4，在解决完一系列可见语法错误后。遇到了个很神奇的错误，这在升级前是没有的，经过排查，最后锁定在下面的代码上（dramaEndBuildMapCallBack为Action类型）： 可&#8230;</p>
<p><a href="https://vki.cc/greattruth/experience/709/">C#清除委托列表的正确用法</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">近期将项目Unity版本从5.6升级到了2018.4.4，在解决完一系列可见语法错误后。遇到了个很神奇的错误，这在升级前是没有的，经过排查，最后锁定在下面的代码上（dramaEndBuildMapCallBack为<strong>Action</strong>类型）：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">if (this.dramaEndBuildMapCallback != null)
{
	this.dramaEndBuildMapCallback();
	this.dramaEndBuildMapCallback = null;
}</pre>



<p class="wp-block-paragraph">可以看出，该块代码想表达的意思是执行完委托就清空。事实上在Unity5.6的时候它确实可以正常工作，但是随着Unity升级，.Net版本也升级到4.x，这种方式失效了。</p>



<p class="wp-block-paragraph">经过查询，找到了一个可以正常清空委托列表的方法，首先通过<strong>GetInvocationList()</strong>方法获取委托列表，然后遍历，删掉。。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="csharp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">/// &lt;summary>
/// 清除委托列表。
/// &lt;/summary>
/// &lt;param name="action">&lt;/param>
public static void ClearDelegage(Action action)
{
	if (action != null)
	{
		Delegate[] delegates = action.GetInvocationList();
		for (int i = 0; i &lt; delegates.Length; i++)
		{
			action -= delegates[i] as Action;
		}
	}
}</pre>



<p class="wp-block-paragraph">好想吐槽一下，为什么C#没提供一个像链表Clear()那样的方法来清除委托列表呢_(:з」∠)_</p>
<p><a href="https://vki.cc/greattruth/experience/709/">C#清除委托列表的正确用法</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/experience/709/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Unity安卓项目踩坑日记</title>
		<link>https://vki.cc/greattruth/experience/692/</link>
					<comments>https://vki.cc/greattruth/experience/692/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Tue, 23 Apr 2019 09:38:57 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[安卓]]></category>
		<category><![CDATA[心得]]></category>
		<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">https://bye6.cc/?p=692</guid>

					<description><![CDATA[<p>失踪人口回归~ 最近在研究游戏在安卓平台的打包，遇到了不少坑，特此写个文章记录下~ 1.Unity与安卓的交互 虽然Unity可以直接导出apk安装包，但由于有些方法，比如读取手机相册图片，获取权限等，或者是添加&#8230;</p>
<p><a href="https://vki.cc/greattruth/experience/692/">Unity安卓项目踩坑日记</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="color: #808080;"><em>失踪人口回归~</em></span></p>
<blockquote><p>最近在研究游戏在安卓平台的打包，遇到了不少坑，特此写个文章记录下~</p></blockquote>
<h2 id="1-unity%e4%b8%8e%e5%ae%89%e5%8d%93%e7%9a%84%e4%ba%a4%e4%ba%92">1.Unity与安卓的交互</h2>
<p>虽然Unity可以直接导出apk安装包，但由于有些方法，比如读取手机相册图片，获取权限等，或者是添加SDK都不能直接通过Unity实现。我们一般用Unity导出安卓工程，再通过Android Studio修改之后打出apk包。</p>
<p>通常情况下每次打包都需要修改，为了偷懒~</p>
<p>这里提供个堪称一劳永逸的解决办法，请看文章~</p>
<p><span style="color: #ff6600;"><a style="color: #ff6600;" href="https://www.jianshu.com/p/86b275da600e" target="_blank" rel="noopener noreferrer">Unity与Android交互方案优化版</a></span></p>
<p><span style="text-decoration: underline;"><a href="https://www.jianshu.com/p/86b275da600e" target="_blank" rel="noopener noreferrer">https://www.jianshu.com/p/86b275da600e</a></span></p>
<h2 id="2-android-aar%e6%96%87%e4%bb%b6%e4%bf%ae%e6%94%b9">2.Android aar文件修改</h2>
<p><span style="color: #808080;"><em>今天刚踩得坑，麻蛋！</em></span></p>
<p>不同于jar包只能包含java代码，aar包还可以保存贴图等资源，相当于一个后缀是aar的压缩包。有时候第三方sdk提供的也是aar文件，当需要修改里面的东西时，比如删掉里面一个jar<strong>。切记不能采取先解压，删除完毕再压缩回去，后缀改成aar的操作。这样修改后Android Studio用不了！！！</strong></p>
<p>正确方法是以解压的形式打开（不是解压压缩包），一般Windows平台的压缩软件都可以，然后在压缩软件里增加或删除文件操作。</p>
<h2 id="3-android-aar%e6%96%87%e4%bb%b6%e8%af%bb%e5%8f%96">3.Android aar文件读取</h2>
<p><span style="color: #808080;"><em>同上，又是个巨坑，匪夷所思！</em></span></p>
<p>我目前的项目在安卓端是这样的，把用到的sdk和需要在安卓端才能调用的方法打成aar包，然后添加到Unity导出的安卓工程里，但是不知道为什么在运行的时候会报以下的错误;</p>
<p><img  loading="lazy"  decoding="async"  class="aligncenter size-full wp-image-694"  src="https://cdn.vki.cc/wp-content/uploads/2019/04/QQ20190423-0.jpg"  alt=""  width="661"  height="83"  srcset="https://cdn.vki.cc/wp-content/uploads/2019/04/QQ20190423-0.jpg 661w, https://cdn.vki.cc/wp-content/uploads/2019/04/QQ20190423-0-300x38.jpg 300w"  sizes="auto, (max-width: 661px) 100vw, 661px" ></p>
<p>说的是BGPlayerService类重复，可是我的找遍了真个项目和aar包也只有一个类，根本没有重复的地方。研究了很久都无解，就在准备放弃治疗的时候顺便改了下build.gradle的dependencies里的语句，从</p>
<pre class="pure-highlightjs"><code class="null">dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation project(':localizedappnamelib')
    implementation 'com.android.support:support-core-utils:24.2.0'
    implementation (name:'findingparadiselib-debug',ext:'aar')
}</code></pre>
<p>改成了</p>
<pre class="pure-highlightjs"><code class="null">dependencies {
    implementation (name:'findingparadiselib-debug',ext:'aar')
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation project(':localizedappnamelib')
    implementation 'com.android.support:support-core-utils:24.2.0'
}</code></pre>
<p>然后特么问题解决了！</p>
<p>？？？</p>
<p>我怀疑可能是implementation fileTree(include: [&#8216;*.jar&#8217;], dir: &#8216;libs&#8217;)把aar包里的jar也算进去了_(:з」∠)_</p>
<h2 id="4-%e7%94%9f%e6%88%90%e7%ad%be%e5%90%8d%e5%ae%89%e8%a3%85%e5%8c%85%e7%9a%84%e6%97%b6%e5%80%99%e6%8a%a5%e9%94%99">4.生成签名安装包的时候报错</h2>
<p>在第一次生成签名安装包的时候可能提示缺少xxx.pom（忘了是不是pom后缀了，反正差不多）和xxx.jar组件，这个报错在生成debug包的时候是不出现的。具体原因我不清楚，我猜是打包的时候需要这样依赖包，但是谷歌的官方站点没有（Android Studio提供的链接点进去404）。</p>
<p>两个解决办法，一是手动下载这些依赖包并放到指定的目录中去，不过不建议这样做，一个一个下载再放到指定目录太麻烦了。</p>
<p>第二中解决方法是使用阿里提供的站点，具体操作是将以下的代码方放到安卓工程的build.gradle文件的repositories代码块中去：</p>
<pre class="pure-highlightjs"><code class="null">maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' }
maven { url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }</code></pre>
<p>这样打包的时候Android Studio会自动去这些站点下载需要的依赖包，问题解决。</p>
<h2 id="5-execution-failed-for-task-appndkbuild">5.Execution failed for task &#8216;:app:ndkBuild&#8217;.</h2>
<p>该问题是在对一个老游戏升级的时候出现的，表现为无法打包，报错：</p>
<pre class="pure-highlightjs"><code class="null">Process 'command 'D:\SDK\***/ndk-build.cmd'' finished with non-zero exit value 2</code></pre>
<p>上网搜索，普遍的解决方式是使用低版本的NDK，又或者是删除src/main/obj文件夹里的内容，尝试无果。</p>
<p>最终发现是build.gradle版本较老，且使用ndkBuild的方式打包，不适用于新版的Android Studio，修改之后问题解决</p>
<p>修改前：</p>
<pre class="pure-highlightjs"><code class="null">android {
    signingConfigs {
    }
    compileSdkVersion 26
    buildToolsVersion '23.0.3'
    defaultConfig {
        applicationId "com.xd.swords.and"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 18
        versionName "1.1.7"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets.main.jni.srcDirs = []
    // disable automatic ndk-build call, which ignore our Android.mk
    sourceSets.main.jniLibs.srcDir 'src/main/libs'
    // call regular ndk-build(.cmd) script from app directory
    task ndkBuild(type: Exec) {
        workingDir file('src/main')
        commandLine getNdkBuildCmd()
    }
    tasks.withType(JavaCompile) {
        compileTask -&gt; compileTask.dependsOn ndkBuild
    }
    task cleanNative(type: Exec) {
        workingDir file('src/main')
        commandLine getNdkBuildCmd(), 'clean'
    }
    clean.dependsOn cleanNative
}</code></pre>
<p>修改后：</p>
<pre class="pure-highlightjs"><code class="null">android {
    signingConfigs {
    }
    compileSdkVersion 26
    buildToolsVersion '23.0.3'
    defaultConfig {
        applicationId "com.xd.swords.and"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 18
        versionName "1.1.7"
        ndk {
            abiFilters 'armeabi-v7a'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        ndkBuild {
            path "src/main/jni/Android.mk"
        }
    }

    // 下面部分代码应该也可以删掉。
    sourceSets.main.jni.srcDirs = []
    // disable automatic ndk-build call, which ignore our Android.mk
    sourceSets.main.jniLibs.srcDir 'src/main/libs'
    // call regular ndk-build(.cmd) script from app directory
}</code></pre>
<p>对比前后，主要是删除了旧的ndkBuild代码，然后设置abiFilters等。</p>
<p><a href="https://vki.cc/greattruth/experience/692/">Unity安卓项目踩坑日记</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/experience/692/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>《樱色伊始》开发日记</title>
		<link>https://vki.cc/greattruth/experience/499/</link>
					<comments>https://vki.cc/greattruth/experience/499/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Sun, 06 May 2018 05:58:03 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[心得]]></category>
		<category><![CDATA[游戏]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=499</guid>

					<description><![CDATA[<p>&#160; 2018.5.6之前 这段时间主要是搭建框架，并完成了注册，登录，创建角色功能。 大致流程如下： 构思框架-&#62;设计服务端框架-&#62;设计通信协议-&#62;设计客户端框架-&#62;验证通信协议 由于这之前我并未&#8230;</p>
<p><a href="https://vki.cc/greattruth/experience/499/">《樱色伊始》开发日记</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>&nbsp;</p>
<h2 id="2018-5-6%e4%b9%8b%e5%89%8d">2018.5.6之前</h2>
<p>这段时间主要是搭建框架，并完成了注册，登录，创建角色功能。</p>
<p>大致流程如下：</p>
<p><span style="color: #ff6600;">构思框架-&gt;设计服务端框架-&gt;设计通信协议-&gt;设计客户端框架-&gt;验证通信协议</span></p>
<p>由于这之前我并未有开发网络游戏的经验，所以这部分参考siki dalao的《丛林战争》和罗培羽dalao的《Unity 3D 网络游戏实战》，不过这两个项目跟《樱色伊始》需求有些出入，就综合了一下。</p>
<p>通信协议我分了四级，RequestCode &#8211;  ActionCode &#8211; ReturnCode &#8211; 内容</p>
<p><strong>服务端：</strong>首先通过RequestCode 在Dictionary中查找对应处理Class，然后通过反射机制查找ActionCode对应的method，ReturnCode就是简单的结果码，诸如Success，Fail之类。</p>
<p>最后跟的就是内容，比如如果是登录功能：</p>
<p>User &#8211; Login &#8211; None &#8211; Username + Password</p>
<p><strong>客户端：</strong>客户端维护了一个消息队列和委托Dictionary，在发送请求的同时处理返回结果的方法注册到Dictionary中。</p>
<p>客户端每帧处理若干条协议，通过Action匹配Dictionary中的委托。</p>
<p>服务端框架和客户端框架有些复杂，等之后我会再写篇文章进行详细解析。</p>
<p>// 设计协议的时候也有个坑，原型我是参考一本书的。刚开始使用没问题，后来在发送角色基本数据（协议数据比较长）的时候发现总会丢失4个字节的内容。</p>
<p>// 测来测去，最终发现是书上搞错了字符串的长度和字符串字节数组的长度。而这个bug在某些情况下又是不存在的。。</p>
<p>// 总之还是不要太相信“权威”</p>
<p><span style="color: #ff6600;">-&gt;实现创建，登录功能-&gt;实现选择，创建角色功能</span></p>
<p><span style="color: #ff6600;">-&gt;设计角色动作状态机</span></p>
<p>// 这个地方必须得吐槽下，没有合适的动作素材真难受，为了实现流畅的动作，我到处找素材，淘宝，论坛逛了一遍，始终没找到合适的。。</p>
<p>// 就现在用的动作还是从三套模型上抠出来的。。</p>
<p><span style="color: #ff6600;">-&gt;实现摄像机跟随角色的功能</span></p>
<p>// 这里有个细节，在实现摄像机自动拉近与被遮挡角色距离的时候，碰到射线无法检测部分物体的物品，后来发现是因为摄像机处于collider内部，而从内部发出的射线是无法检测collider边缘的。</p>
<p>// 换了下思路，改为从角色像摄像机方向发射射线，问题解决。</p>
<h2 id="2018-5-6">2018.5.6</h2>
<p>回头看了下前段时间写的代码，发现有部分已经快看不懂了。。（捂脸）</p>
<p>论注释的重要性</p>
<p>今天添加了删除角色功能，不过删除确认还没做，等开发到之后扔掉背包物品和退出游戏时一并做吧_(:з」∠)_</p>
<p>做了这么久，最让我头痛的还是模型动作的问题，除非我愿意去学习3dsmax或者有建模师帮我，不然我真的一点办法都没有。。</p>
<p>只能先将就着用了。。</p>
<p>希望到时候面试时dalao不要介意。。</p>
<h2 id="2018-5-7">2018.5.7</h2>
<p>今天是“沉重”的一天。。</p>
<p>让我担心的事最终还是发生了。。</p>
<p>设计客户端架构时经验不足，没有认真考虑到Unity执行脚本的生命周期而埋下的隐患，导致今天在改写功能的时候各种空指针引用。。</p>
<p>痛定思痛，花了点时间对核心脚本进行了重构，抛弃了先前的GameFacade脚本，并将其功能整合到了GameRoot脚本中。</p>
<p>暂时做如下设计</p>
<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/05/SZFlowChart.png"><img  loading="lazy"  decoding="async"  class="size-full wp-image-508 aligncenter"  src="https://cdn.vki.cc/wp-content/uploads/2018/05/SZFlowChart.png"  alt=""  width="709"  height="814"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/05/SZFlowChart.png 709w, https://cdn.vki.cc/wp-content/uploads/2018/05/SZFlowChart-261x300.png 261w"  sizes="auto, (max-width: 709px) 100vw, 709px" ></a></p>
<p>不知道效果咋样，等下课了回去试试_(:з」∠)_</p>
<p>*****************</p>
<p>改写之后，无bug一遍过</p>
<p>看来新结构行得通2333</p>
<h2 id="2018-5-8-scene%e5%8a%a0%e8%bd%bd%e4%b8%8e%e5%88%87%e6%8d%a2">2018.5.8 Scene加载与切换</h2>
<p>今天试着做了下异步加载Scene功能_(:з」∠)_</p>
<p>目前游戏有四个Scene，加载流程如下</p>
<p><span style="color: #ff6600;">欢迎Scene -&gt; 登录与注册相关Scene -&gt; Load Scene -&gt; 游戏Scene</span></p>
<p>其中Load Scene是专门用来显示加载进度条的，比如说从Scene 1 到 Scene 2，</p>
<p>Scene 1 中使用SceneManager.LoadScene() 直接加载LoadScene（因为很小，只有进度条，所以可以做到秒加载）</p>
<p>然后在LoadScene中使用SceneManager.LoadSceneAsyc()异步加载Scene2 ，加载过程通过其返回值AsyncOperation中的progress参数获取加载进度。</p>
<p>需要注意的是SceneManager.LoadSceneAsyc()加载完毕默认会直接切换到目标Scene，如果想手动控制切换时机的话设置AsyncOperation.allowSceneActivation为false，等到需要切换时再设为true。另外<span style="text-decoration: underline;"><strong><span style="color: #000000; text-decoration: underline;">把allowSceneActivation设置为false后，Unity就只会加载场景到90%，剩下的10%要等到allowSceneActivation设置为true后才加载。</span></strong></span></p>
<h2 id="5-9-5-13">5.9 &#8211; 5.13</h2>
<p>最近心态有点不好 T T</p>
<p>不过已经缓过来了，明天继续！</p>
<h2 id="5-14">5.14</h2>
<p>做了些UI，比如角色属性，状态栏啥的，</p>
<p>还有设计了下地图</p>
<p>好像没啥好说的。。</p>
<h2 id="5-15-%e8%a7%92%e8%89%b2%e5%b1%9e%e6%80%a7%e8%af%bb%e5%8f%96">5.15 角色属性读取</h2>
<p>目前设计的是将角色不同等级的基础属性，比如HP，暴击率什么的做成Json文件保存在客户端。在生成角色或角色升级时进行加载。</p>
<p>（数值设计暂且不考虑）</p>
<p>后期装备也准备这样做，角色总属性 = 基础属性 + 装备属性；</p>
<p>放在本地可以减轻服务器的压力，当然这样做有个很大的缺点，数据容易被篡改（作弊）。。</p>
<p>将其保存在服务器数据库实现起来应该不会太难，不过暂时先这样用着 _(:з」∠)_</p>
<h2 id="5-16">5.16</h2>
<p>增加了“删除角色”确认对话框，防止误删除；</p>
<p>完善了角色状态的UI显示，并能根据登录角色加载不同的角色到游戏中；</p>
<p>制作了角色暴击特效（暴击时在角色背后生成一个“假人”）；</p>
<p>开始制作包裹系统，由于以前有做过这个东西，所以大部分用的都是原来的代码，改动下就可以用了；</p>
<p>大致结构如下（不完整）：<a href="https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory.png" target="_blank" rel="noopener"><img  loading="lazy"  decoding="async"  class="aligncenter wp-image-512 size-full"  src="https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory.png"  alt=""  width="1392"  height="943"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory.png 1392w, https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory-300x203.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory-768x520.png 768w, https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory-1024x694.png 1024w, https://cdn.vki.cc/wp-content/uploads/2018/05/UML_Client_Inventory-750x508.png 750w"  sizes="auto, (max-width: 1392px) 100vw, 1392px" ></a></p>
<h2 id="5-17">5.17</h2>
<p>新增了穿上、脱下装备以及同步属性面板的显示；</p>
<p>新增了使用药品，恢复HP，MP以及同步面板的显示；</p>
<p>重构基础战斗属性：HP，MP，攻击，命中率，穿刺，防御，闪避率，暴击率，暴击伤害为PropertiesModel类，并重载了其“+”，“-”操作符，使得两个PropertiesModel可以进行加减运算；</p>
<p>（使用场景，当穿戴一个装备时，角色的PropertiesModel+=装备的PropertiesModel）</p>
<p>角色持有3个PropertiesModel，一个为<strong>固定角色属性</strong>，一个为<strong>“装备属性和”</strong>，一个为<strong>总可变属性</strong>；</p>
<p>1.<strong>固定角色属性</strong>是指角色本身基础属性，由职业和等级决定；</p>
<p>2.<strong>“装备属性和”</strong>由角色所佩戴的装备决定，等于角色身上每件装备的PropertiesModel相加；</p>
<p>3.<strong>总可变属性</strong>由固定属性和“装备属性和”组成，其中的HP，MP字段会随着收到伤害，使用技能，使用药品等发生变化，主要用于战斗计算；</p>
<p>另外角色属性<strong>上限由固定角色属性</strong>和“装备属性和”构成，例如HP上限 = 基础HP + 装备HP，这个部分只有在装备发生变化时才会改变，战斗中收到伤害等情况下不会改变；</p>
<p><span style="color: #808080;">（穿上，脱下装备对HP，MP来说只会影响上限，当前HP也不会超过上限。例如角色当前HP为80/100，卸下了一个可以增加50HP的装备，HP变为50/50）</span></p>
<p>装备类物品在数据库中有个额外的标志位，“1”表示穿戴中，“0”表示未穿戴；</p>
<p><span style="color: #ff0000;">已知bug：</span></p>
<p><span style="color: #ff0000;">在某些情况下表示拾取中的物品的ItemUI会被Destroy，暂时没发现规律，也不知道怎么回事。。。</span></p>
<h2 id="5-18">5.18</h2>
<p>新增天气-雨天效果；</p>
<p>用粒子系统做的</p>
<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211.png" target="_blank" rel="noopener"><img  loading="lazy"  decoding="async"  class="aligncenter wp-image-515 size-full"  src="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211.png"  alt=""  width="1078"  height="566"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211.png 1078w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211-300x158.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211-768x403.png 768w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211-1024x538.png 1024w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194211-750x394.png 750w"  sizes="auto, (max-width: 1078px) 100vw, 1078px" ></a><a href="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155.png" target="_blank" rel="noopener"><img  loading="lazy"  decoding="async"  class="aligncenter wp-image-514 size-full"  src="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155.png"  alt=""  width="1083"  height="597"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155.png 1083w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155-300x165.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155-768x423.png 768w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155-1024x564.png 1024w, https://cdn.vki.cc/wp-content/uploads/2018/05/20180518194155-750x413.png 750w"  sizes="auto, (max-width: 1083px) 100vw, 1083px" >emmm截图中雨滴看起来是矩形的，实际运行由于下落速度快还是挺好看的。。</a></p>
<p>顺便吐槽下剑灵的剧情。。</p>
<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/05/6ZW6JO22MYT9DJJLTIJ.jpg" target="_blank" rel="noopener"><img  loading="lazy"  decoding="async"  class="aligncenter wp-image-516 size-full"  src="https://cdn.vki.cc/wp-content/uploads/2018/05/6ZW6JO22MYT9DJJLTIJ.jpg"  alt=""  width="505"  height="119"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/05/6ZW6JO22MYT9DJJLTIJ.jpg 505w, https://cdn.vki.cc/wp-content/uploads/2018/05/6ZW6JO22MYT9DJJLTIJ-300x71.jpg 300w"  sizes="auto, (max-width: 505px) 100vw, 505px" ></a></p>
<p>来个Happy Ending就那么难吗。。。</p>
<h2 id="5-19">5.19</h2>
<p>新增雨天音效，环境音效的播放；</p>
<p>新增小地图功能（具体做法可以看我之前的文章：<span style="text-decoration: underline; color: #0000ff;"><a style="color: #0000ff; text-decoration: underline;" href="https://vki.cc/greattruth/engine/342/">在Unity中制作小地图</a></span>）</p>
<p>新增商店功能，包括购买，出售物品及金钱的同步；</p>
<h2 id="5-20">5.20</h2>
<p>修复了出售商品时商品数量实际上不会减少的bug；</p>
<p>新增客户端与服务端的位置同步；</p>
<p>重构 PlayerController.cs 和 PlayerBattle.cs 合为Player.cs （历史总是惊人的相似）</p>
<p>重新设计了角色生成机制，为多人游戏做准备（脑阔痛）</p>
<h2 id="5-21">5.21</h2>
<p><span style="color: #808080;">说些题外话，sz做了这么久了，感觉自己的心境也在慢慢变化。</span></p>
<p><span style="color: #808080;">一开始只是想着做个属于自己的游戏，一步一步，一砖一瓦构建自己想要的游戏世界</span></p>
<p><span style="color: #808080;">但是现在，不知不觉把找工作当成了首要任务</span></p>
<p><span style="color: #808080;">经常担心这做不好，那做不好，面试官问起这个怎么办，做的不完美怎么办。。</span></p>
<p><span style="color: #808080;">有些时候真的对sz有了略微的恐惧心理 _(:з」∠)_</span></p>
<p><span style="color: #808080;">惭愧，可能是我对那个公司太喜欢了吧，很担心自己水平不够_(:з」∠)_</span></p>
<h2 id="5-22"><strong>5.22 &#8211; ~~~</strong></h2>
<p>临近期末，各科都要做期末项目设计和实验报告，答辩啥的，比较忙。。</p>
<p>暂时挂起。。</p>
<p><a href="https://vki.cc/greattruth/experience/499/">《樱色伊始》开发日记</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/experience/499/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>基于Unity 3D引擎的可视化音乐播放器</title>
		<link>https://vki.cc/myworks/mygames/422/</link>
					<comments>https://vki.cc/myworks/mygames/422/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Thu, 22 Mar 2018 03:01:00 +0000</pubDate>
				<category><![CDATA[我的游戏]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[音乐]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=422</guid>

					<description><![CDATA[<p>前几天逛b站时偶然发现了个“煤气灶”播放器 av12408836 感觉挺好玩，就花点时间研究，并照着仿制了一个 感觉抄的还可以2333 使用说明 [kbd]Esc[/kbd]：显示/隐藏菜单 [kbd]空格[/kbd]：暂停/播放 [kbd]箭头上&#8230;</p>
<p><a href="https://vki.cc/myworks/mygames/422/">基于Unity 3D引擎的可视化音乐播放器</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<blockquote><p>前几天逛b站时偶然发现了个“煤气灶”播放器 <span style="color: #0000ff;"><a style="color: #0000ff;" href="https://www.bilibili.com/video/av12408836">av12408836</a></span></p>
<p>感觉挺好玩，就花点时间研究，并照着仿制了一个</p>
<p>感觉抄的还可以2333</p></blockquote>
<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629.png" target="_blank" rel="noopener noreferrer"><img  loading="lazy"  decoding="async"  class="aligncenter wp-image-425 size-full"  src="https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629.png"  alt=""  width="1372"  height="797"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629.png 1372w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629-300x174.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629-768x446.png 768w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629-1024x595.png 1024w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180321214629-750x436.png 750w"  sizes="auto, (max-width: 1372px) 100vw, 1372px" ></a></p>
<h2 id="%e4%bd%bf%e7%94%a8%e8%af%b4%e6%98%8e">使用说明</h2>
<p>[kbd]Esc[/kbd]：显示/隐藏菜单</p>
<p>[kbd]空格[/kbd]：暂停/播放</p>
<p>[kbd]箭头上/下[/kbd]：提高/降低音量</p>
<p>[kbd]箭头左/右[/kbd]：上一曲/下一曲</p>
<h2 id="%e6%b3%a8%e6%84%8f">注意</h2>
<p>第一次使用如果不指定播放目录或目录下没有MP3文件，会循环播放《世末歌者》；</p>
<p>目录有效且目录下有MP3文件，会显示绿色，反之红色；</p>
<p>在程序运行时请不要修改或删除播放目录内的mp3文件；</p>
<p>&nbsp;</p>
<p>由于unity引擎目前暂不支持读取外部MP3格式的文件，所以需要先转换格式才能播放（这也是<a href="https://www.bilibili.com/video/av12408836">av12408836</a>那个需要转格式的原因）</p>
<p>不过我已经集成了自动转换的功能，所以无需手动转换；</p>
<p>但是这也会导致一些问题，比如更换歌曲时会有略微的卡顿以及音质下降_(:з」∠)_</p>
<h2 id="%e4%b8%8b%e8%bd%bd">下载</h2>
<p>程序：</p>
<p>[ypbtn]https://pan.baidu.com/s/1Y6q6hg091jWlk3pbwHzBpg[/ypbtn]</p>
<p>源码：<span style="text-decoration: underline;"><span style="color: #3366ff;"><a style="color: #3366ff; text-decoration: underline;" href="https://github.com/icemaplen/AudioVisualization" target="_blank" rel="noopener noreferrer">https://github.com/icemaplen/AudioVisualization</a></span></span></p>
<p><a href="https://vki.cc/myworks/mygames/422/">基于Unity 3D引擎的可视化音乐播放器</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/myworks/mygames/422/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>在Unity中制作小地图</title>
		<link>https://vki.cc/greattruth/engine/342/</link>
					<comments>https://vki.cc/greattruth/engine/342/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Sat, 03 Feb 2018 14:36:54 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[引擎相关]]></category>
		<category><![CDATA[UGUI]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[心得]]></category>
		<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=342</guid>

					<description><![CDATA[<p>在很多游戏里，小地图都是不可或缺的存在，今天我们就来学习下如何在Unity中制作小地图 _(:з」∠)_ 据我目前所知（知识有限），小地图有两种制作方式： 一是新建一个小摄像机，放在场景上空朝下进行拍摄； 二&#8230;</p>
<p><a href="https://vki.cc/greattruth/engine/342/">在Unity中制作小地图</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>在很多游戏里，小地图都是不可或缺的存在，今天我们就来学习下如何在Unity中制作小地图</p>
<p>_(:з」∠)_</p>
<p>据我目前所知（知识有限），小地图有两种制作方式：</p>
<p>一是新建一个小摄像机，放在场景上空朝下进行拍摄；</p>
<p>二是计算场景中物体的相对位置，通过UI显示出来；</p>
<p>在本例中，我使用的是第一张方式，这种方式实现相对简单一点，所以很方便。</p>
<h2 id="%e9%a6%96%e5%85%88%e5%9c%a8project%e4%b8%ad%e6%96%b0%e5%bb%ba%e4%b8%80%e4%b8%aarender-texture%ef%bc%8c%e5%91%bd%e5%90%8d%e4%b8%baminimap">首先在Project中新建一个Render Texture，命名为“Minimap”</h2>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-351"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224324.jpg"  alt=""  width="505"  height="446"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224324.jpg 505w, https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224324-300x265.jpg 300w"  sizes="auto, (max-width: 505px) 100vw, 505px" ></p>
<p>然后在场景中新建一个Camera，将其设为Player（将会在小地图中处于中心位置的玩家）的子物体，并调整其位置和方向，令其处于Player上方且朝向正下方，再将其Target Texture指定为刚才创建的Render Texture，如图：</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-352"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224607.jpg"  alt=""  width="389"  height="406"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224607.jpg 389w, https://cdn.vki.cc/wp-content/uploads/2018/02/20180203224607-287x300.jpg 287w"  sizes="auto, (max-width: 389px) 100vw, 389px" ></p>
<p>然后在场景中创建UI-Raw Image，并设置Texture为刚才创建的Render Texture，你会发现image显示的是小地图Camera拍的内容 _(:з」∠)_</p>
<p>这样大体上就做出来了，不过还要调节下。</p>
<h2 id="%e8%ae%be%e7%bd%ae%e9%9c%80%e8%a6%81%e6%98%be%e7%a4%ba%e5%9c%a8%e5%b0%8f%e5%9c%b0%e5%9b%be%e4%b8%8a%e7%9a%84%e5%ad%90%e7%89%a9%e4%bd%93">设置需要显示在小地图上的子物体</h2>
<p>在需要显示在小地图上的的物体上添加一个Sphere子物体，改成绿色，同样改变高度使其位于上方（注意不要超过小地图Camera的高度）</p>
<p>新建一个Layer层，命名为Minimap，将Sphere置为Minimap层，</p>
<p>将地面模型也置为Minimap层，</p>
<p>更改小地图Camera的Culling Mask，只勾选刚才创建的Minimap层，注意勾选Occlusion Culling，这样小地图就只显示Minimap层的东西了。</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-354"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203230422.jpg"  alt=""  width="285"  height="350"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203230422.jpg 285w, https://cdn.vki.cc/wp-content/uploads/2018/02/20180203230422-244x300.jpg 244w"  sizes="auto, (max-width: 285px) 100vw, 285px" ></p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-355"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203230741.jpg"  alt=""  width="244"  height="234" ></p>
<h2 id="%e7%be%8e%e5%8c%96%e5%b0%8f%e5%9c%b0%e5%9b%be">美化小地图</h2>
<p>现在的小地图还是方形的，如何改成圆形呢？</p>
<p>打开ps，制作一个白色的圆，背景为透明，保存为png格式，导入到unity中，再设置属性为Sprite(2D and UI)，</p>
<p>[infobox title=&#8221;白色圆&#8221;]<a href="https://cdn.vki.cc/wp-content/uploads/2018/02/mask-1.png" target="_blank" rel="noopener noreferrer"><img  loading="lazy"  decoding="async"  class="alignnone wp-image-356 size-medium"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/mask-1-300x300.png"  alt=""  width="300"  height="300"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/mask-1-300x300.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/02/mask-1-150x150.png 150w, https://cdn.vki.cc/wp-content/uploads/2018/02/mask-1.png 512w"  sizes="auto, (max-width: 300px) 100vw, 300px" ></a> [/infobox]</p>
<p>在场景中新建UI-Image，image指定为白色的圆，添加上Mask组件，设置为Raw Image的父物体。这样小地图就变成圆形了：</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-358"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203231256.jpg"  alt=""  width="216"  height="214"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203231256.jpg 216w, https://cdn.vki.cc/wp-content/uploads/2018/02/20180203231256-150x150.jpg 150w"  sizes="auto, (max-width: 216px) 100vw, 216px" ></p>
<p>或者可以再加上一个圈：</p>
<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/02/mask3.png" target="_blank" rel="noopener noreferrer">[infobox title=&#8221;圆圈&#8221;]<img  loading="lazy"  decoding="async"  class="alignnone wp-image-357 size-medium"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/mask3-300x300.png"  alt=""  width="300"  height="300"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/02/mask3-300x300.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/02/mask3-150x150.png 150w, https://cdn.vki.cc/wp-content/uploads/2018/02/mask3.png 512w"  sizes="auto, (max-width: 300px) 100vw, 300px" >[/infobox]</a></p>
<p>最终效果：</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-359"  src="https://cdn.vki.cc/wp-content/uploads/2018/02/20180203231458.jpg"  alt=""  width="208"  height="213" ></p>
<hr />
<p>写完了，睡觉 _(:з」∠)_</p>
<p><a href="https://vki.cc/greattruth/engine/342/">在Unity中制作小地图</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/engine/342/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>UGUI 字体背景尺寸自适应</title>
		<link>https://vki.cc/greattruth/engine/321/</link>
					<comments>https://vki.cc/greattruth/engine/321/#respond</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Wed, 31 Jan 2018 09:06:22 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[引擎相关]]></category>
		<category><![CDATA[UGUI]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=321</guid>

					<description><![CDATA[<p>最近再做一个模仿QQ聊天界面的聊天功能，在开发过程中遇到了一个问题，就是需要将字体的背景气泡自动随着字体长度变化。 经过一番尝试，最终功能如下： 怎么实现的呢？一起来看看吧。 &#160; 首先将背景图片&#8230;</p>
<p><a href="https://vki.cc/greattruth/engine/321/">UGUI 字体背景尺寸自适应</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>最近再做一个模仿QQ聊天界面的聊天功能，在开发过程中遇到了一个问题，就是需要将字体的背景气泡自动随着字体长度变化。</p>
<p>经过一番尝试，最终功能如下：</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-324"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165407.jpg"  alt=""  width="610"  height="246"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165407.jpg 610w, https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165407-300x121.jpg 300w"  sizes="auto, (max-width: 610px) 100vw, 610px" ></p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-325"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165408.jpg"  alt=""  width="591"  height="257"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165408.jpg 591w, https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165408-300x130.jpg 300w"  sizes="auto, (max-width: 591px) 100vw, 591px" ></p>
<p>怎么实现的呢？一起来看看吧。</p>
<p>&nbsp;</p>
<p>首先将背景图片设为父物体，字体text为子物体；</p>
<p>给父物体添加[kbd]Horizontal Layout Group[/kbd]和[kbd]Content Size Fitter[/kbd]组件，</p>
<p>在[kbd]Horizontal Layout Group[/kbd]中设置Child Alignment为Middle Center，</p>
<p>勾选Child Controls Size里的Width和Height，该选项是令子物体控制其尺寸。</p>
<p>&nbsp;</p>
<p>在[kbd]Content Size Fitter[/kbd]中将两个选项都选为 PreferredSize；<br />
<span style="color: #808080;">Unconstrained：不执行任何调整 </span><br />
<span style="color: #808080;">MinSize：调整内容的最小大小 </span><br />
<span style="color: #808080;">PreferredSize：调整内容的首选大小，也就是会自动根据内容来调整大小</span></p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-326"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165826.jpg"  alt=""  width="766"  height="353"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165826.jpg 766w, https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165826-300x138.jpg 300w, https://cdn.vki.cc/wp-content/uploads/2018/01/20180131165826-750x346.jpg 750w"  sizes="auto, (max-width: 766px) 100vw, 766px" ></p>
<p>这样就可以了！做个测试吧</p>
<p>&nbsp;</p>
<p>为了美观，可以设置下背景的padding，这样文字和背景边框之间就会用一定的间隔啦</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-328"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131170736.jpg"  alt=""  width="402"  height="190"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/20180131170736.jpg 402w, https://cdn.vki.cc/wp-content/uploads/2018/01/20180131170736-300x142.jpg 300w"  sizes="auto, (max-width: 402px) 100vw, 402px" ></p>
<p>&nbsp;</p>
<p><a href="https://vki.cc/greattruth/engine/321/">UGUI 字体背景尺寸自适应</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/engine/321/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>分享一个摄像机跟随的代码模板</title>
		<link>https://vki.cc/greattruth/engine/315/</link>
					<comments>https://vki.cc/greattruth/engine/315/#comments</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Tue, 23 Jan 2018 23:53:11 +0000</pubDate>
				<category><![CDATA[咸鱼心得]]></category>
		<category><![CDATA[引擎相关]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[心得]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=315</guid>

					<description><![CDATA[<p>先上代码： using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraFollow : MonoBehaviour { public float Distance = 20; //摄像机与目标距离 public floa&#8230;</p>
<p><a href="https://vki.cc/greattruth/engine/315/">分享一个摄像机跟随的代码模板</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>先上代码：</p>
<pre class="pure-highlightjs"><code class="cs">using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraFollow : MonoBehaviour
{

    public float Distance = 20;                     //摄像机与目标距离
    public float RotSpeedInHorizontal = 0.05f;      //横向旋转速度
    public float RotSpeedInVertical = 0.05f;        //纵向旋转速度
    public float ZoomSpeed = 0.2f;                  //距离变化速度

    public float rot = 0;                           //横向角度
    private float roll = 30f * 2 * Mathf.PI / 360;  //纵向角度

    private float minRoll = -10f * 2 * Mathf.PI / 360;  //纵向角度范围
    private float maxRoll= 70f * 2 * Mathf.PI / 360;    //纵向角度范围

    private float minDistance = 10f;    //距离范围
    private float maxDisrance = 50f;

    private GameObject targetGO;        //目标物体  
    

    void Start()
    {
        SetTarget(GameObject.Find("Tank"));
    }
    
    void LateUpdate()
    {
        if (targetGO != null &amp;&amp; Camera.main != null)
        {
            RotateInHorizontal();
            RotateInVertical();
            Zoom();
            FollowTarget(targetGO.transform);
        }
    }

    private void SetTarget(GameObject target)
    {
        Transform cameraPoint = target.transform.Find("CameraPoint");
        targetGO = cameraPoint != null ? cameraPoint.gameObject : target;

        //if (cameraPoint != null)
        //{
        //    targetGO = cameraPoint.gameObject;
        //}
        //else
        //{
        //    targetGO = target;
        //}
    }

    private void FollowTarget(Transform targetTrans)
    {
        Vector3 targetPos = targetTrans.position;
        Vector3 cameraPos;
        float d = Distance * Mathf.Cos(roll);
        float height = Distance * Mathf.Sin(roll);
        cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
        cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
        cameraPos.y = targetPos.y + height;

        Camera.main.transform.position = cameraPos;
        Camera.main.transform.LookAt(targetTrans);
    }

    /// &lt;summary&gt;
    /// 水平旋转。
    /// &lt;/summary&gt;
    private void RotateInHorizontal()
    {
        float tmp = Input.GetAxis("Mouse X") * RotSpeedInHorizontal;
        rot -= tmp;
    }

    /// &lt;summary&gt;
    /// 竖直旋转。
    /// &lt;/summary&gt;
    private void RotateInVertical()
    {
        float tmp = Input.GetAxis("Mouse Y") * RotSpeedInVertical * 0.5f;
        roll -= tmp;

        roll = Mathf.Clamp(roll, minRoll, maxRoll);
    }

    /// &lt;summary&gt;
    /// 调节摄像机与目标之间的距离。
    /// &lt;/summary&gt;
    private void Zoom()
    {
        if (Input.GetAxis("Mouse ScrollWheel") &gt; 0)
        {
            if (Distance &gt; minDistance)
            {
                Distance -= ZoomSpeed;
            }
        }
        else if (Input.GetAxis("Mouse ScrollWheel") &lt; 0)
        {
            if (Distance &lt; maxDisrance)
            {
                Distance += ZoomSpeed;
            }
        }
    }
}
</code></pre>
<h2 id="%e8%ae%be%e7%bd%ae%e8%b7%9f%e9%9a%8f%e7%9b%ae%e6%a0%87-settargetgameobject-target">设置跟随目标 SetTarget(GameObject target)</h2>
<pre class="pure-highlightjs"><code class="cs">private void SetTarget(GameObject target)
    {
        Transform cameraPoint = target.transform.Find("CameraPoint");
        targetGO = cameraPoint != null ? cameraPoint.gameObject : target;

        //if (cameraPoint != null)
        //{
        //    targetGO = cameraPoint.gameObject;
        //}
        //else
        //{
        //    targetGO = target;
        //}
    }
</code></pre>
<p>因为目标物体的大小形状可能不同，有时候我们想让相机对准目标身上某个自定义的点，便可以在目标上添加一个子物体，命名为&#8221;CameraPoint&#8221;。</p>
<p>这个方法的作用就是查找目标是否存在&#8221;CameraPoint&#8221;，如果有就将&#8221;CameraPoint&#8221;设为目标点。如果没有，仍然使用默认目标点。</p>
<h2 id="%e7%9b%b8%e6%9c%ba%e8%b7%9f%e9%9a%8f%e7%9b%ae%e6%a0%87-followtargettransform-targettrans">相机跟随目标 FollowTarget(Transform targetTrans)</h2>
<pre class="pure-highlightjs"><code class="cs">    private void FollowTarget(Transform targetTrans)
    {
        Vector3 targetPos = targetTrans.position;
        Vector3 cameraPos;
        float d = Distance * Mathf.Cos(roll);
        float height = Distance * Mathf.Sin(roll);
        cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
        cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
        cameraPos.y = targetPos.y + height;

        Camera.main.transform.position = cameraPos;
        Camera.main.transform.LookAt(targetTrans);
    }</code></pre>
<p>这一部分较为复杂，使用了三角函数的知识。</p>
<p>要想让相机跟随目标移动，就要明白在一定角度下相机与目标的位置关系，如图所示</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-318"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow1.jpg"  alt=""  width="571"  height="429"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow1.jpg 571w, https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow1-300x225.jpg 300w"  sizes="auto, (max-width: 571px) 100vw, 571px" ></p>
<p>（灵魂画手。。）</p>
<p>设相机与目标距离为distance，相机与xz平面角度为roll。根据三角函数即可求得distance映射在xz平面上的距离为distance*cos(roll)，高度为distance*sin(roll)。</p>
<p>&nbsp;</p>
<p>再如下图，设相机与目标在水平面上的距离为d（即distance映射在水平面的长度），相机旋转角度为rot，由图可知相机与目标的连线与x轴角度为rot-180。</p>
<p>根据三角函数，求得x轴位移为d*sin(rot)，z轴位移为d*cos(rot)。所以，只要用目标坐标减去相对位移，便能求出相机坐标。</p>
<p><img  loading="lazy"  decoding="async"  class="alignnone size-full wp-image-319"  src="https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow2.jpg"  alt=""  width="464"  height="439"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow2.jpg 464w, https://cdn.vki.cc/wp-content/uploads/2018/01/CameraFollow2-300x284.jpg 300w"  sizes="auto, (max-width: 464px) 100vw, 464px" ></p>
<h2 id="%e5%85%b6%e4%bb%96">其他</h2>
<p>1.相机跟随代码最好放入LateUpdate()中；</p>
<p>2.Mathf.Sin()和Mathf.Cos()使用弧度做单位，使用时将度数乘以[kbd]2*Mathf.Pi/360[/kbd]转化为弧度；</p>
<p><a href="https://vki.cc/greattruth/engine/315/">分享一个摄像机跟随的代码模板</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/greattruth/engine/315/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>聊天机器人</title>
		<link>https://vki.cc/myworks/mygames/406/</link>
					<comments>https://vki.cc/myworks/mygames/406/#respond</comments>
		
		<dc:creator><![CDATA[白露]]></dc:creator>
		<pubDate>Fri, 19 Jan 2018 03:31:12 +0000</pubDate>
				<category><![CDATA[我的游戏]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[Unity 3D]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[游戏]]></category>
		<guid isPermaLink="false">http://www.icemaplen.com/?p=406</guid>

					<description><![CDATA[<p>如图，调用了图灵机器人的API 可实现简单聊天功能 _(:з」∠)_ &#160; 源码：https://github.com/icemaplen/Chatting-Robot</p>
<p><a href="https://vki.cc/myworks/mygames/406/">聊天机器人</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437.png"><img  loading="lazy"  decoding="async"  class="aligncenter size-large wp-image-408"  src="https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437-1024x595.png"  alt=""  width="1024"  height="595"  srcset="https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437-1024x595.png 1024w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437-300x174.png 300w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437-768x446.png 768w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437-750x436.png 750w, https://cdn.vki.cc/wp-content/uploads/2018/03/20180319112437.png 1372w"  sizes="auto, (max-width: 1024px) 100vw, 1024px" ></a></p>
<p>如图，调用了图灵机器人的API</p>
<p>可实现简单聊天功能</p>
<p>_(:з」∠)_</p>
<p>&nbsp;</p>
<p>源码：<a href="https://github.com/icemaplen/Chatting-Robot">https://github.com/icemaplen/Chatting-Robot</a></p>
<p><a href="https://vki.cc/myworks/mygames/406/">聊天机器人</a>最先出现在<a href="https://vki.cc">初晴神社</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://vki.cc/myworks/mygames/406/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
