Jekyll2017-06-11T01:13:33+02:00http://btlcruiser.com/blog/The Battlecruiser Dev logA website about developing game in Unity3d.Pixeyepixeye@hbrew.storeFade groups of objects in Unity3d.2017-06-10T09:08:13+02:002017-06-10T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Fade%20groups%20of%20objects%20%20in%20Unity3d<p>I would like to share a small library I made for fading any kind of objects. It works similar to unity3d canvas group but can be used not only for UI. It also allows defining global groups with shared string ID so you will be able to fade several groups simultaneously.
<!--more-->
Please note that your materials/shaders must support transparency in order to get it work.</p>
<p><a href="https://i.gyazo.com/23d97b106b51be96f2812786179ca3e3.png" title="alpha dudes"><img src="https://i.gyazo.com/23d97b106b51be96f2812786179ca3e3.png" alt="alpha dudes" title="alpha dudes" /></a></p>
<p>Inspector params:</p>
<p><strong>Global Render Group</strong>
String id for global group. You can easily fade groups simultaneously if they share the same ID.</p>
<p><strong>Ignore parent group</strong>
If this group is a child of another ignores alpha changes of the parent.</p>
<p><strong>Child Renders Only</strong>
If this is toggled you won’t be able manually to add/remove nodes to a group. The group works automatically and nodes are cleaned up when the object no longer a child of the render group.</p>
<p><strong>Deactivate On Fade</strong>
Deactivates all nodes of the group when their alpha equals to zero. Activates them when alpha is bigger than zero.</p>
<p><strong>Nodes</strong>
It’s a list of all nodes that are used in a group. It can contain render or graphic nodes ( UI ) depending on what you put inside the group. Nodes are utility components that contain cached values. They are scriptable objects.</p>
<p><strong>Child Groups</strong>
All groups that are children of selected render group.</p>
<p><strong>Materials Props</strong> -
Id of shader color to look for alpha. You can define several ID. For example, if you are going to fade particles they use _TintColor.</p>
<p>Methods to use in RenderGroup.cs :</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="c1">// Value to fade to and the time of transition
</span><span class="k">public</span> <span class="k">void</span> <span class="nf">Fade</span><span class="p">(</span><span class="kt">float</span> <span class="k">value</span><span class="p">,</span><span class="kt">float</span> <span class="n">time</span><span class="p">)</span>
</code></pre>
</div>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="c1">// Fade global group. Use globalgroup ID, value to fade and transition time
</span><span class="n">RenderGroupGlobal</span><span class="p">.</span><span class="nf">FadeGlobalGroup</span> <span class="p">(</span><span class="s">"Group"</span><span class="p">,</span><span class="m">0.0f</span><span class="p">,</span><span class="m">0.5f</span><span class="p">);</span>
</code></pre>
</div>
<p><a href="https://i.gyazo.com/bcd5773b7838c23dd44abccb54ffb7c7.png" title="Editor"><img src="https://i.gyazo.com/bcd5773b7838c23dd44abccb54ffb7c7.png" alt="Editor" title="Editor" /></a></p>
<p>Get the unity package from my <a href="https://www.dropbox.com/s/7hj1vyjygt7hwwu/RenderGroupPackage.unitypackage?dl=0" title="dropbox">Dropbox</a></p>
<p>Follow me on my <a href="https://www.twitch.tv/pixeye" title="Twitch">Twitch</a> channel where I’m showing creation process of the Battlecruiser.</p>Pixeyepixeye@hbrew.storeI would like to share a small library I made for fading any kind of objects. It works similar to unity3d canvas group but can be used not only for UI. It also allows defining global groups with shared string ID so you will be able to fade several groups simultaneously.Coloring Specific Parts of a Model in Unity3d.2017-05-25T09:08:13+02:002017-05-25T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Coloring%20Specific%20Parts%20of%20a%20Model%20in%20Unity3d<p>One of the features I’ve implemented is objects coloring. I’ve written a simple shader for that. I’ve used the alpha value to fill the desired spots on the model with the custom color. Also, I’ve done it for emission color as well ( We use it on our models a lot )
<!--more-->
<a href="https://gyazo.com/421523ac33f1c4e0cb8ea7e0cf4cf3d4"><img src="https://i.gyazo.com/421523ac33f1c4e0cb8ea7e0cf4cf3d4.gif" alt="https://gyazo.com/421523ac33f1c4e0cb8ea7e0cf4cf3d4" /></a></p>
<p>To use this shader erase desired parts from your texture map.</p>
<p>This is the texture I use on the ship above:</p>
<p><a href="https://i.gyazo.com/cb47c17e64c9693661f63bd0b399ed25.png"><img src="https://i.gyazo.com/cb47c17e64c9693661f63bd0b399ed25.png" alt="" /></a></p>
<p>In addition you can use one more extra color for emission if needed. To use emission coloring add
the emission map: erase everything on your diffuse map except spots you want for emission color. Make them black color save and attach to Emission Map inside the material. Thats it.</p>
<p><a href="https://gyazo.com/62b74bf1ca147f66db31a3e995a87d9c"><img src="https://i.gyazo.com/62b74bf1ca147f66db31a3e995a87d9c.png" alt="https://gyazo.com/62b74bf1ca147f66db31a3e995a87d9c" /></a></p>
<p>It may be not the best approach but it works.</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="n">Shader</span> <span class="s">"Custom/CustomColorPainter"</span> <span class="p">{</span>
<span class="n">Properties</span> <span class="p">{</span>
<span class="nf">_Color</span> <span class="p">(</span><span class="s">"Color"</span><span class="p">,</span> <span class="n">Color</span><span class="p">)</span> <span class="p">=</span> <span class="p">(</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">)</span>
<span class="nf">_ColorEmission</span><span class="p">(</span><span class="s">"ColorEmission"</span><span class="p">,</span> <span class="n">Color</span><span class="p">)=(</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">)</span>
<span class="nf">_MainTex</span> <span class="p">(</span><span class="s">"Albedo (RGB)"</span><span class="p">,</span> <span class="m">2D</span><span class="p">)</span> <span class="p">=</span> <span class="s">"white"</span> <span class="p">{}</span>
<span class="nf">_EmissionMap</span> <span class="p">(</span><span class="s">"EmissionMap"</span><span class="p">,</span><span class="m">2D</span><span class="p">)</span> <span class="p">=</span> <span class="s">"gray"</span> <span class="p">{}</span>
<span class="nf">_Glossiness</span> <span class="p">(</span><span class="s">"Smoothness"</span><span class="p">,</span> <span class="nf">Range</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">1</span><span class="p">))</span> <span class="p">=</span> <span class="m">0.5</span>
<span class="nf">_Metallic</span> <span class="p">(</span><span class="s">"Metallic"</span><span class="p">,</span> <span class="nf">Range</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">1</span><span class="p">))</span> <span class="p">=</span> <span class="m">0.0</span>
<span class="p">}</span>
<span class="n">SubShader</span> <span class="p">{</span>
<span class="n">Tags</span> <span class="p">{</span> <span class="s">"RenderType"</span><span class="p">=</span><span class="s">"Opaque"</span> <span class="p">}</span>
<span class="n">LOD</span> <span class="m">200</span>
<span class="n">CGPROGRAM</span>
<span class="c1">// Physically based Standard lighting model, and enable shadows on all light types
</span> <span class="err">#</span><span class="n">pragma</span> <span class="n">surface</span> <span class="n">surf</span> <span class="n">Standard</span> <span class="n">fullforwardshadows</span>
<span class="c1">// Use shader model 3.0 target, to get nicer looking lighting
</span> <span class="err">#</span><span class="n">pragma</span> <span class="n">target</span> <span class="m">3.0</span>
<span class="n">sampler2D</span> <span class="n">_MainTex</span><span class="p">;</span>
<span class="n">sampler2D</span> <span class="n">_EmissionMap</span><span class="p">;</span>
<span class="k">struct</span> <span class="nc">Input</span> <span class="p">{</span>
<span class="n">float2</span> <span class="n">uv_MainTex</span><span class="p">;</span>
<span class="n">float2</span> <span class="n">uv_EmissionMap</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">half</span> <span class="n">_Glossiness</span><span class="p">;</span>
<span class="n">half</span> <span class="n">_Metallic</span><span class="p">;</span>
<span class="k">fixed</span> <span class="n">_AlphaChecker</span><span class="p">;</span>
<span class="n">fixed4</span> <span class="n">_Color</span><span class="p">;</span>
<span class="n">fixed4</span> <span class="n">_ColorEmission</span><span class="p">;</span>
<span class="c1">// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
</span> <span class="c1">// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
</span> <span class="c1">// #pragma instancing_options assumeuniformscaling
</span> <span class="nf">UNITY_INSTANCING_CBUFFER_START</span><span class="p">(</span><span class="n">Props</span><span class="p">)</span>
<span class="c1">// put more per-instance properties here
</span> <span class="n">UNITY_INSTANCING_CBUFFER_END</span>
<span class="k">void</span> <span class="nf">surf</span> <span class="p">(</span><span class="n">Input</span> <span class="n">IN</span><span class="p">,</span> <span class="n">inout</span> <span class="n">SurfaceOutputStandard</span> <span class="n">o</span><span class="p">)</span> <span class="p">{</span>
<span class="n">_AlphaChecker</span> <span class="p">=</span> <span class="m">0.6</span><span class="p">;</span>
<span class="n">fixed3</span> <span class="n">endColor</span> <span class="p">=</span> <span class="nf">fixed3</span><span class="p">(</span><span class="m">0.0</span><span class="p">,</span><span class="m">0.0</span><span class="p">,</span><span class="m">0.0</span><span class="p">);</span>
<span class="n">fixed4</span> <span class="n">ca</span> <span class="p">=</span> <span class="nf">tex2D</span><span class="p">(</span><span class="n">_EmissionMap</span><span class="p">,</span> <span class="n">IN</span><span class="p">.</span><span class="n">uv_EmissionMap</span><span class="p">);</span>
<span class="c1">// normalColor stuff
</span> <span class="n">fixed4</span> <span class="n">c</span> <span class="p">=</span> <span class="nf">tex2D</span> <span class="p">(</span><span class="n">_MainTex</span><span class="p">,</span> <span class="n">IN</span><span class="p">.</span><span class="n">uv_MainTex</span><span class="p">);</span>
<span class="c1">// emission stuff
</span> <span class="k">if</span> <span class="p">(</span><span class="n">ca</span><span class="p">.</span><span class="n">a</span><span class="p"><=</span><span class="n">_AlphaChecker</span><span class="p">){</span>
<span class="n">o</span><span class="p">.</span><span class="n">Emission</span> <span class="p">=</span> <span class="nf">half3</span><span class="p">(</span><span class="m">0.0</span><span class="p">,</span><span class="m">0.0</span><span class="p">,</span><span class="m">0.0</span><span class="p">);</span>
<span class="n">endColor</span> <span class="p">=</span> <span class="n">c</span><span class="p">.</span><span class="n">rgb</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="n">o</span><span class="p">.</span><span class="n">Emission</span> <span class="p">=</span> <span class="n">_ColorEmission</span><span class="p">;</span>
<span class="n">endColor</span> <span class="p">=</span> <span class="n">_ColorEmission</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span><span class="p">.</span><span class="n">a</span><span class="p"><</span><span class="n">_AlphaChecker</span><span class="p">)</span>
<span class="n">endColor</span> <span class="p">=</span> <span class="n">_Color</span><span class="p">;</span>
<span class="c1">// Metallic and smoothness come from slider variables
</span> <span class="n">o</span><span class="p">.</span><span class="n">Metallic</span> <span class="p">=</span> <span class="n">_Metallic</span><span class="p">;</span>
<span class="n">o</span><span class="p">.</span><span class="n">Smoothness</span> <span class="p">=</span> <span class="n">_Glossiness</span><span class="p">;</span>
<span class="n">o</span><span class="p">.</span><span class="n">Albedo</span> <span class="p">=</span> <span class="n">endColor</span><span class="p">.</span><span class="n">rgb</span><span class="p">;</span>
<span class="n">o</span><span class="p">.</span><span class="n">Alpha</span> <span class="p">=</span> <span class="n">c</span><span class="p">.</span><span class="n">a</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">ENDCG</span>
<span class="p">}</span>
<span class="n">FallBack</span> <span class="s">"Diffuse"</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Or take it from my <a href="https://github.com/dimmpixeye/Shaders" title="github">github</a></p>
<p>Follow me at my <a href="https://www.twitch.tv/pixeye" title="Twitch">Twitch</a> channel where I’m showing creation process of the Battlecruiser.</p>Pixeyepixeye@hbrew.storeOne of the features I’ve implemented is objects coloring. I’ve written a simple shader for that. I’ve used the alpha value to fill the desired spots on the model with the custom color. Also, I’ve done it for emission color as well ( We use it on our models a lot )Buying stuff like in Kingdom: New Lands.2017-04-20T09:08:13+02:002017-04-20T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Buying%20stuff%20like%20in%20Kingdom%20New%20Lands<p>I implemented this technique in my game. Feel free to use it.
The idea of it is that you see the “price” nodes above the building you want to buy.
<!--more-->
<a href="https://gyazo.com/ee0e997617ccb1cc413fc85a5e5281d8"><img src="https://i.gyazo.com/ee0e997617ccb1cc413fc85a5e5281d8.gif" alt="https://gyazo.com/ee0e997617ccb1cc413fc85a5e5281d8" /></a></p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code>
<span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="kt">int</span> <span class="n">currentPrice</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="c1">// how many nodes should be used in price. I made up to 12.
</span> <span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="kt">float</span> <span class="n">size</span> <span class="p">=</span> <span class="m">1.0f</span><span class="p">;</span>
<span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="n">Transform</span><span class="p">[]</span> <span class="n">nodeObjs</span><span class="p">;</span> <span class="c1">// predefined price nodes
</span> <span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="kt">float</span> <span class="n">arcSize</span> <span class="p">=</span> <span class="m">0.1f</span><span class="p">;</span> <span class="c1">// the height of the arc. ( showing row like parabola )
</span> <span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="kt">float</span> <span class="n">fadeSpeed</span> <span class="p">=</span> <span class="m">0.2f</span><span class="p">;</span>
<span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="n">Vector3</span> <span class="n">offset</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Vector3</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">36</span><span class="p">,</span><span class="m">0</span><span class="p">);</span>
<span class="p">[</span><span class="n">SerializeField</span><span class="p">]</span>
<span class="k">private</span> <span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">></span> <span class="n">positions</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">>();</span> <span class="c1">// position array of used nodes
</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Bad in math. Good in bed.
</span> <span class="c1">/// </summary>
</span> <span class="k">void</span> <span class="nf">CalculateNodes</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">positions</span><span class="p">.</span><span class="nf">Clear</span><span class="p">();</span>
<span class="c1">// Add nodes to array with we will work
</span> <span class="n">Transform</span><span class="p">[]</span> <span class="n">nodes</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Transform</span><span class="p">[</span><span class="n">currentPrice</span><span class="p">];</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span><span class="n">i</span><span class="p"><</span><span class="n">nodeObjs</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span><span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
<span class="n">nodeObjs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">gameObject</span><span class="p">.</span><span class="nf">SetActive</span><span class="p">((</span><span class="n">i</span><span class="p"><</span><span class="n">currentPrice</span><span class="p">)?</span><span class="k">true</span><span class="p">:</span><span class="k">false</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentPrice</span><span class="p">></span><span class="n">i</span><span class="p">)</span>
<span class="n">nodes</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="p">=</span> <span class="n">nodeObjs</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="c1">// we will calculate single row length based on amount of price nodes.
</span>
<span class="kt">int</span> <span class="n">rowLength</span> <span class="p">=</span> <span class="n">currentPrice</span> <span class="p">/</span> <span class="m">2</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentPrice</span> <span class="p"><</span> <span class="m">7</span><span class="p">)</span>
<span class="n">rowLength</span> <span class="p">=</span> <span class="n">currentPrice</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">zPos</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">extraOffset</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="c1">//dirty hacks to be sure we can get nodes from the upper left corner.
</span> <span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">></span> <span class="n">row1</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">>();</span>
<span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">></span> <span class="n">row2</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">Vector3</span><span class="p">>();</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="p"><</span> <span class="n">currentPrice</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
<span class="kt">float</span> <span class="n">offset</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">arcRatio</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">yHeight</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="p"><</span> <span class="n">rowLength</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">zPos</span> <span class="p">=</span> <span class="n">size</span> <span class="p">*</span> <span class="m">1.25f</span><span class="p">;</span>
<span class="n">extraOffset</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">((</span><span class="n">rowLength</span> <span class="p">%</span> <span class="m">2</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
<span class="n">extraOffset</span> <span class="p">=</span> <span class="n">size</span> <span class="p">*</span> <span class="m">0.5f</span><span class="p">;</span>
<span class="n">offset</span> <span class="p">=</span> <span class="p">(</span><span class="n">rowLength</span> <span class="p">/</span> <span class="m">2</span> <span class="p">*</span> <span class="n">size</span> <span class="p">-</span> <span class="n">extraOffset</span><span class="p">)</span> <span class="p">*</span> <span class="p">-</span><span class="m">1</span><span class="p">;</span>
<span class="n">arcRatio</span> <span class="p">=</span> <span class="n">Mathf</span><span class="p">.</span><span class="nf">PingPong</span><span class="p">((</span><span class="kt">float</span><span class="p">)</span><span class="n">i</span> <span class="p">/</span> <span class="p">(</span><span class="kt">float</span><span class="p">)(</span><span class="n">rowLength</span><span class="p">-</span><span class="m">1</span><span class="p">),</span> <span class="m">0.5f</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">zPos</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="n">extraOffset</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(((</span><span class="n">currentPrice</span> <span class="p">-</span> <span class="n">rowLength</span><span class="p">)</span> <span class="p">%</span> <span class="m">2</span><span class="p">)</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
<span class="n">extraOffset</span> <span class="p">=</span> <span class="n">size</span> <span class="p">*</span> <span class="m">0.5f</span><span class="p">;</span>
<span class="n">arcRatio</span> <span class="p">=</span> <span class="n">Mathf</span><span class="p">.</span><span class="nf">PingPong</span><span class="p">((</span><span class="kt">float</span><span class="p">)(</span><span class="n">i</span><span class="p">-</span><span class="n">rowLength</span><span class="p">)</span> <span class="p">/</span> <span class="p">(</span><span class="kt">float</span><span class="p">)(</span><span class="n">currentPrice</span><span class="p">-</span><span class="n">rowLength</span><span class="p">-</span><span class="m">1</span><span class="p">),</span> <span class="m">0.5f</span><span class="p">);</span>
<span class="n">offset</span> <span class="p">=</span> <span class="p">((</span><span class="n">rowLength</span><span class="p">*</span><span class="n">size</span><span class="p">)</span> <span class="p">+</span> <span class="p">((</span><span class="n">currentPrice</span><span class="p">-</span><span class="n">rowLength</span><span class="p">)</span> <span class="p">/</span> <span class="m">2</span> <span class="p">*</span> <span class="n">size</span> <span class="p">-</span> <span class="n">extraOffset</span><span class="p">))</span> <span class="p">*</span> <span class="p">-</span><span class="m">1</span> <span class="p">;</span>
<span class="p">}</span>
<span class="n">yHeight</span> <span class="p">=</span> <span class="n">Mathf</span><span class="p">.</span><span class="nf">Sin</span><span class="p">(</span><span class="n">arcRatio</span> <span class="p">*</span> <span class="n">Mathf</span><span class="p">.</span><span class="n">PI</span><span class="p">)*</span><span class="n">arcSize</span><span class="p">;</span>
<span class="n">nodes</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">localPosition</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Vector3</span><span class="p">(</span><span class="n">offset</span> <span class="p">+</span> <span class="n">i</span> <span class="p">*</span> <span class="n">size</span><span class="p">,</span> <span class="n">yHeight</span><span class="p">,</span> <span class="p">-</span><span class="n">zPos</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="p"><</span> <span class="n">rowLength</span><span class="p">)</span>
<span class="n">row1</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">nodes</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">position</span><span class="p">);</span>
<span class="k">else</span>
<span class="n">row2</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">nodes</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">position</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Adding rows to positions array. You will need it to get price point index.
</span> <span class="n">positions</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="n">row2</span><span class="p">);</span>
<span class="n">positions</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="n">row1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Follow me at my <a href="https://www.twitch.tv/pixeye" title="Twitch">Twitch</a> channel where I’m showing creation process of the Battlecruiser.</p>Pixeyepixeye@hbrew.storeI implemented this technique in my game. Feel free to use it. The idea of it is that you see the “price” nodes above the building you want to buy.Making simple AI states in Unity3d2017-04-15T09:08:13+02:002017-04-15T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Simple-AI-State-Machine<p>My implementation of AI state machine. It relies on nested inherited classes.
<!--more--></p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="cm">/*===============================================================
Product: Utilities
Developer: Dimitry Pixeye - pixeye@hbrew.store
Company: Homebrew - http://hbrew.store
Date: 26/04/2017 10:55
================================================================*/</span>
<span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">Homebrew</span><span class="p">{</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="k">class</span> <span class="nc">BasicAI</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="p">:</span> <span class="n">MonoBehaviour</span> <span class="p">{</span>
<span class="p">[</span><span class="n">System</span><span class="p">.</span><span class="n">Serializable</span><span class="p">]</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="k">class</span> <span class="nc">AIState</span>
<span class="p">{</span>
<span class="k">protected</span> <span class="n">T</span> <span class="n">AI</span><span class="p">;</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">ID</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">AIState</span><span class="p">(</span><span class="n">T</span> <span class="n">AI</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">AI</span> <span class="p">=</span> <span class="n">AI</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Logic loop. The action itself goes here
</span> <span class="c1">/// </summary>
</span> <span class="k">public</span> <span class="k">abstract</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">();</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Checks if we need to kill the current state
</span> <span class="c1">/// </summary>
</span> <span class="c1">/// <returns></returns>
</span> <span class="k">public</span> <span class="k">abstract</span> <span class="kt">bool</span> <span class="nf">EndStateCondition</span><span class="p">();</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Use to reset some variables / set next state or set state to null
</span> <span class="c1">/// </summary>
</span> <span class="k">public</span> <span class="k">abstract</span> <span class="k">void</span> <span class="nf">End</span><span class="p">();</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Some initial setups or actions that happen ONCE when the state becomes active.
</span> <span class="c1">/// </summary>
</span> <span class="k">public</span> <span class="k">virtual</span> <span class="k">void</span> <span class="nf">Start</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="n">AIState</span><span class="p">></span> <span class="n">states</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">AIState</span><span class="p">>();</span>
<span class="k">public</span> <span class="n">AIState</span> <span class="n">currentState</span><span class="p">;</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">SwitchToState</span><span class="p">(</span><span class="kt">string</span> <span class="n">ID</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">state</span> <span class="p">=</span> <span class="n">states</span><span class="p">.</span><span class="nf">Find</span><span class="p">(</span><span class="n">s</span> <span class="p">=></span> <span class="n">s</span><span class="p">.</span><span class="n">ID</span> <span class="p">==</span> <span class="n">ID</span><span class="p">);</span>
<span class="n">currentState</span> <span class="p">=</span> <span class="n">state</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentState</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span>
<span class="n">currentState</span><span class="p">.</span><span class="nf">Start</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">protected</span> <span class="k">virtual</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentState</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentState</span><span class="p">.</span><span class="nf">EndStateCondition</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">currentState</span><span class="p">.</span><span class="nf">End</span><span class="p">();</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">currentState</span><span class="p">.</span><span class="nf">Update</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>It’s a initial AI script you inherit from. It contains nested class AIState that we will use to create our custom states.</p>
<p><strong>AIState</strong></p>
<p>Members:</p>
<ul>
<li>ID - a string name of the state. Is used to get other states from list.</li>
</ul>
<p>Methods:</p>
<ul>
<li>Update - Logic loop. The action of the state itself goes here.</li>
<li>EndStateCondition - The way to know if we don’t need state anymore.</li>
<li>End - The end method of state. Triggers after positive EndStateCondition</li>
<li>It’s important to note that you have to define ether you want to switch to the next state or set it to null.</li>
<li>Start - Triggers once after new state set.</li>
</ul>
<p>**BasicAI<T>**</T></p>
<p>Members:</p>
<ul>
<li>states - A list of all states to look. Add new states to the list.</li>
<li>currentState - a current state in action.</li>
</ul>
<p>Methods:</p>
<ul>
<li>SwitchToState(string ID) - will try to switch to a state with provided ID. If not null triggers state start method.</li>
</ul>
<p>An example from Battlecruiser:</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="cm">/*===============================================================
Product: Battlecruiser
Developer: Dimitry Pixeye - pixeye@hbrew.store
Company: Homebrew - http://hbrew.store
Date: 26/04/2017 11:02
================================================================*/</span>
<span class="cm">/*===============================================================
Example realisation
Create special netested classes of your states and inherit them from AIState
================================================================*/</span>
<span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">DG.Tweening</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">Homebrew</span><span class="p">{</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">SalvageDroneAI</span> <span class="p">:</span> <span class="n">BasicAI</span><span class="p"><</span><span class="n">SalvageDroneAI</span><span class="p">></span> <span class="p">{</span>
<span class="k">public</span> <span class="n">Transform</span> <span class="n">model</span><span class="p">;</span>
<span class="k">public</span> <span class="n">Transform</span> <span class="n">targetRef</span><span class="p">;</span>
<span class="err">#</span><span class="n">region</span> <span class="n">STATES</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">LeaveBase</span> <span class="p">:</span> <span class="n">AIState</span>
<span class="p">{</span>
<span class="kt">bool</span> <span class="n">leftTheBase</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="k">public</span> <span class="nf">LeaveBase</span><span class="p">(</span><span class="n">SalvageDroneAI</span> <span class="n">ai</span><span class="p">):</span> <span class="k">base</span><span class="p">(</span><span class="n">ai</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">ID</span> <span class="p">=</span> <span class="s">"LeaveBase"</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">/// <summary>
</span> <span class="c1">/// Reseting values
</span> <span class="c1">/// </summary>
</span> <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">End</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">leftTheBase</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="n">AI</span><span class="p">.</span><span class="nf">SwitchToState</span><span class="p">(</span><span class="s">"FlyToTarget"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">EndStateCondition</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">leftTheBase</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Start</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">Log</span><span class="p">(</span><span class="s">"Leaving my parent ship. Goodbye!"</span><span class="p">);</span>
<span class="n">leftTheBase</span><span class="p">=</span><span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">FlyToTarget</span> <span class="p">:</span> <span class="n">AIState</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">FlyToTarget</span><span class="p">(</span><span class="n">SalvageDroneAI</span> <span class="n">ai</span><span class="p">):</span> <span class="k">base</span><span class="p">(</span><span class="n">ai</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">ID</span> <span class="p">=</span> <span class="s">"FlyToTarget"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">End</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotImplementedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">bool</span> <span class="nf">EndStateCondition</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Start</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//AI.TargetRef
</span> <span class="k">if</span> <span class="p">(</span><span class="n">AI</span><span class="p">.</span><span class="n">targetRef</span><span class="p">==</span><span class="k">null</span><span class="p">)</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">Log</span><span class="p">(</span><span class="s">"I'm on my way! To...err where am I going?!"</span><span class="p">);</span>
<span class="k">else</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">Log</span><span class="p">(</span><span class="s">"I'm on my way to the "</span> <span class="p">+</span> <span class="n">AI</span><span class="p">.</span><span class="n">targetRef</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="err">#</span><span class="n">endregion</span>
<span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Create</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">base</span><span class="p">.</span><span class="nf">Create</span><span class="p">();</span>
<span class="n">states</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">LeaveBase</span><span class="p">(</span><span class="k">this</span><span class="p">));</span>
<span class="n">states</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">FlyToTarget</span><span class="p">(</span><span class="k">this</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">OnEnable</span><span class="p">()</span>
<span class="p">{</span>
<span class="nf">SwitchToState</span><span class="p">(</span><span class="s">"LeaveBase"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">OnDisable</span><span class="p">()</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>You can take the script from <a href="https://github.com/dimmpixeye/SimpleAIStateMachine" title="Github">Github</a></p>
<p>Follow me at my <a href="https://www.twitch.tv/pixeye" title="Twitch">Twitch</a> channel where I’m showing creation process of the Battlecruiser.</p>Pixeyepixeye@hbrew.storeMy implementation of AI state machine. It relies on nested inherited classes.Convenient Syntax Highlighting for Visual Studio2017-04-15T09:08:13+02:002017-04-15T09:08:13+02:00http://btlcruiser.com/blog/visualstudio/Visual-Studio-Syntax-Highlighting%20-%20Copy<p>I love to customize my visual studio color theme from time to time, but it’s a frustrating experience. I’ve found a great solution. It’s called Codinion, and you can get it free.</p>
<p><a href="http://www.codinion.com" title="##Codinion">Codinion</a></p>
<p><a href="https://i.gyazo.com/03a33a4263a3259ffc1f7cbdce5c68fc.png" title="Showcase"><img src="https://i.gyazo.com/03a33a4263a3259ffc1f7cbdce5c68fc.png" alt="Showcase" title="Showcase" /></a></p>
<p>Besides Syntax Highlighting it also customizes navigation, jumplist and banner ( a more clear live preview of the Windows taskbar)</p>Pixeyepixeye@hbrew.storeI love to customize my visual studio color theme from time to time, but it’s a frustrating experience. I’ve found a great solution. It’s called Codinion, and you can get it free. Codinion Besides Syntax Highlighting it also customizes navigation, jumplist and banner ( a more clear live preview of the Windows taskbar)Organizing game logic scripts2017-04-15T09:08:13+02:002017-04-15T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Game-Objects<p><a href="https://i.gyazo.com/59a9d88e9403086ec42b3dc19b27cc88.gif" title="Showcase"><img src="https://i.gyazo.com/59a9d88e9403086ec42b3dc19b27cc88.gif" alt="Showcase" title="Showcase" /></a></p>
<p>Today I will share the way I build up game objects in unity3d. As an example, I will take spaceship controlled by a player.
I’ve spent a good amount of time figuring how to organize my game logic code and game object tree. It’s essential to build clear rules that you follow during the whole developing process. Though you also need a way to break the rule if needed. While I looked at different patterns implemented to Unity3d, I thought they are way overpowered or too complicated.</p>
<p>My attempt in making easy to follow pattern is dead simple and flexible : )
<!--more-->
First, we generate a game object in a special way dividing model view, game logic scripts and data.
Inside the desired game object, I attach three empty objects:</p>
<ul>
<li><strong>bindings</strong></li>
</ul>
<p>You put here all game logic scripts. You even can customize this part more by dividing scripts into states.
For example STATE:ACTIVE, STATE:DESTROYED and so on. Also, it will be a good idea to add separate folders for different types of scripts. In my case, I’ve added DECORATOR child that holds all my ship decoration scripts. This child attached to STATE:ACTIVE so if I decide to switch state to something like STATE:PAUSE the scripts there will be deactivated automatically.</p>
<p><a href="https://i.gyazo.com/4902e0b5dfb629c60b47c79cf7560c82.png" title="decorators"><img src="https://i.gyazo.com/4902e0b5dfb629c60b47c79cf7560c82.png" alt="decorators" title="decorators" /></a></p>
<ul>
<li><strong>model</strong></li>
</ul>
<p>Represents your sprites or 3d models, effects, flares, generally everything that must be shown to the player.
You can also attach some scripts here if they make small particular view related job. In my case, I’ve added flares, thrusters special effects and some empty transform attachments to control local rotations, scales, offsets.</p>
<ul>
<li><strong>settings</strong></li>
</ul>
<p>I use this for initial setup file and in-game data container related to the object. During the game, all scripts from the game object turn here to fetch specific variables.</p>
<p>The script that generates game object tree in this way described in <a href="http://btlcruiser.com/blog/unity3d/Project-Setup/" title="previous post">previous post</a></p>
<p><a href="https://i.gyazo.com/9aec8cff3ee6d6dde2fc3667e5d1c024.gif" title="Showcase_01"><img src="https://i.gyazo.com/9aec8cff3ee6d6dde2fc3667e5d1c024.gif" alt="Showcase_01" title="Showcase_01" /></a></p>
<p>But how our scripts will communicate? We can’t just use GetComponentInParent/Children as we have a lot of siblings in our object that can contain the script we are looking.</p>
<p>We will solve that problem with using extended method and some initial object setups.</p>
<p>First, we need a script attached to the top of the game object tree, <strong>RootComponent.cs</strong></p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">RootComponent</span> <span class="p">:</span> <span class="n">MonoBehaviour</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre>
</div>
<p>My version of the RootComponent is a little bit different, but for example it does the job.
Next, we make an extension to our transforms. To do that I’ve made a script, <strong>TransfromExtensions.cs</strong></p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">TransformExtensions</span> <span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">T</span> <span class="n">Bind</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="k">this</span> <span class="n">Transform</span> <span class="n">transform</span><span class="p">,</span><span class="kt">int</span> <span class="n">cycles</span> <span class="p">=</span> <span class="m">1</span><span class="p">,</span><span class="kt">bool</span> <span class="n">searchInactive</span> <span class="p">=</span> <span class="k">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">T</span> <span class="n">desiredComponent</span> <span class="p">=</span> <span class="k">default</span> <span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">root</span><span class="p">=</span><span class="n">transform</span><span class="p">.</span><span class="n">GetComponentInParent</span><span class="p"><</span><span class="n">RootComponent</span><span class="p">></span> <span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cycles</span><span class="p">></span><span class="m">1</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">parent</span><span class="p">=</span><span class="n">root</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">parent</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span><span class="p"><</span><span class="n">cycles</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
<span class="n">parent</span><span class="p">=</span><span class="n">root</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">parent</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">parent</span><span class="p">==</span><span class="k">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">LogError</span> <span class="p">(</span><span class="s">"Index out of range!"</span><span class="p">);</span>
<span class="k">return</span> <span class="k">default</span> <span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">root</span><span class="p">=</span><span class="n">parent</span><span class="p">.</span><span class="n">GetComponentInParent</span><span class="p"><</span><span class="n">RootComponent</span><span class="p">></span> <span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">root</span><span class="p">==</span><span class="k">null</span><span class="p">)</span>
<span class="k">return</span> <span class="k">default</span> <span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="n">MonoBehaviour</span><span class="p">[]</span> <span class="n">behaviours</span> <span class="p">=</span> <span class="n">root</span><span class="p">.</span><span class="n">GetComponentsInChildren</span><span class="p"><</span><span class="n">MonoBehaviour</span><span class="p">></span> <span class="p">(</span><span class="n">searchInactive</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span><span class="p"><</span><span class="n">behaviours</span><span class="p">.</span><span class="n">Length</span><span class="p">;</span> <span class="n">i</span><span class="p">++)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">behaviours</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">is</span> <span class="n">T</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">desiredComponent</span><span class="p">=</span><span class="n">behaviours</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">GetComponent</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">desiredComponent</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The idea is simple. Find main “index” named RootComponent in your object. Search for desired component in children of RootComponent.</p>
<p>And now we can do something like this :</p>
<p>I have a script, let’s assume shipmovement.cs, and it needs to be linked to setup asset and data script.
They are placed in settings/data.</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="kt">var</span> <span class="n">setupRef</span> <span class="p">=</span> <span class="n">transform</span><span class="p">.</span><span class="n">Bind</span><span class="p"><</span><span class="n">ShipSetup</span><span class="p">></span> <span class="p">().</span><span class="n">Asset</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">dataRef</span> <span class="p">=</span> <span class="n">transform</span><span class="p">.</span><span class="n">Bind</span><span class="p"><</span><span class="n">ShipData</span><span class="p">></span> <span class="p">();</span>
</code></pre>
</div>
<p><a href="https://i.gyazo.com/29c199abaa1a993945392d34fbf3833d.png" title="showcase_03"><img src="https://i.gyazo.com/29c199abaa1a993945392d34fbf3833d.png" alt="showcase_03" title="showcase_03" /></a></p>
<p>There are some options for .Bind you can use as well:
For example, you have a gun structure object that is placed on the top of the platform object. You put the gun structure as a child of the platform object and want to get a platform-specific script from the gun.</p>
<p>To do that you need deeper bind to get platform’s root component. You can do that by setting search cycles.</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="kt">var</span> <span class="n">script</span> <span class="p">=</span> <span class="n">transform</span><span class="p">.</span><span class="n">Bind</span><span class="p"><</span><span class="n">MyCoolPlatfromScript</span><span class="p">>(</span><span class="m">2</span><span class="p">);</span>
</code></pre>
</div>
<p>.Bind will ignore RootParent of the gun structure and will look further for the next RootParent that is attached to the platform object. Also, you can toggle active/inactive components search filter. By the default .Bind looks up for the inactive components.</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="c1">// won't add deactivated EntitySetup component.
</span><span class="kt">var</span> <span class="n">t</span> <span class="p">=</span> <span class="n">transform</span><span class="p">.</span><span class="n">Bind</span><span class="p"><</span><span class="n">EntitySetup</span><span class="p">></span> <span class="p">(</span><span class="m">1</span><span class="p">,</span><span class="k">false</span><span class="p">);</span>
</code></pre>
</div>
<p>I’m still working on making this system better and definitely will write more about it later.
If you like what I’m doing you can support me by signing up to <a href="http://tinyletter.com/Battlecruiser" title="newsletter">newsletter</a> : )</p>Pixeyepixeye@hbrew.storeToday I will share the way I build up game objects in unity3d. As an example, I will take spaceship controlled by a player. I’ve spent a good amount of time figuring how to organize my game logic code and game object tree. It’s essential to build clear rules that you follow during the whole developing process. Though you also need a way to break the rule if needed. While I looked at different patterns implemented to Unity3d, I thought they are way overpowered or too complicated. My attempt in making easy to follow pattern is dead simple and flexible : )Setting up the project in Unity3d2017-04-15T09:08:13+02:002017-04-15T09:08:13+02:00http://btlcruiser.com/blog/unity3d/Project-Setup<p>The bundle of useful scripts that helps to organize your project from scratch. Includes adding project, scene and object tree and coding templates generator.
<!--more-->
I’m not the author of all those scripts, please contact me if I forget to mention someone.</p>
<h3 id="projecttreegeneratorcs">ProjectTreeGenerator.cs</h3>
<p>A script that will generate a project tree for you.
Find GenerateFolderStructure method in the script and feel free to change structure to what you want. Also special .keep files will be included in folders to prevent ignoring empty folders with any processors.</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code> <span class="k">private</span> <span class="k">static</span> <span class="n">Folder</span> <span class="nf">GenerateFolderStructure</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">Folder</span> <span class="n">rootFolder</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Folder</span> <span class="p">(</span><span class="s">"Assets"</span><span class="p">,</span><span class="s">""</span><span class="p">);</span>
<span class="n">rootFolder</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Extensions"</span><span class="p">);</span>
<span class="n">rootFolder</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Plugins"</span><span class="p">);</span>
<span class="n">rootFolder</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"3rdParty"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">GameAssets</span> <span class="p">=</span> <span class="n">rootFolder</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"GAME_ASSETS"</span><span class="p">);</span>
<span class="n">GameAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Data"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">ScriptAssets</span> <span class="p">=</span> <span class="n">GameAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Scripts"</span><span class="p">);</span>
<span class="n">ScriptAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Attributes"</span><span class="p">);</span>
<span class="n">ScriptAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"GameLogic"</span><span class="p">);</span>
<span class="n">ScriptAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Enums"</span><span class="p">);</span>
<span class="n">ScriptAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"ScriptableObjects"</span><span class="p">);</span>
<span class="n">ScriptAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Utility"</span><span class="p">);</span>
<span class="n">GameAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Scenes"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">Prefabs</span> <span class="p">=</span> <span class="n">GameAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Prefabs"</span><span class="p">);</span>
<span class="n">Prefabs</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Resources"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">staticAssets</span> <span class="p">=</span> <span class="n">GameAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"STATIC_ASSETS"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Models"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Animations"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Animators"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Effects"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Fonts"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Materials"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Shaders"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Audio"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Sprites"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Textures"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Videos"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="n">SubFolders</span><span class="p">.</span><span class="nf">Find</span> <span class="p">(</span><span class="n">f</span> <span class="p">=></span> <span class="n">f</span><span class="p">.</span><span class="n">Name</span><span class="p">==</span><span class="s">"Audio"</span><span class="p">).</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Sounds"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="n">SubFolders</span><span class="p">.</span><span class="nf">Find</span> <span class="p">(</span><span class="n">f</span> <span class="p">=></span> <span class="n">f</span><span class="p">.</span><span class="n">Name</span><span class="p">==</span><span class="s">"Audio"</span><span class="p">).</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Music"</span><span class="p">);</span>
<span class="n">staticAssets</span><span class="p">.</span><span class="n">SubFolders</span><span class="p">.</span><span class="nf">Find</span> <span class="p">(</span><span class="n">f</span> <span class="p">=></span> <span class="n">f</span><span class="p">.</span><span class="n">Name</span><span class="p">==</span><span class="s">"Audio"</span><span class="p">).</span><span class="nf">Add</span> <span class="p">(</span><span class="s">"Ambients"</span><span class="p">);</span>
<span class="k">return</span> <span class="n">rootFolder</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The script can be executed from Tools->Project->Generate Project Tree</p>
<p><a href="https://i.gyazo.com/8f24c7b42b51364f2de9cb5a86b4f175.gif" title="Example"><img src="https://i.gyazo.com/8f24c7b42b51364f2de9cb5a86b4f175.gif" alt="Example" title="Example" /></a></p>
<h3 id="scenegeneratorcs">SceneGenerator.cs</h3>
<p>Setups scene in desired way. Feel free to customize tree from the script.
The script executes from Tools->Project->Generate Scene.</p>
<h3 id="objectgeneratorcs">ObjectGenerator.cs</h3>
<p>Create custom object tree. Useful for making advanced game object with different children nodes. I usually do that to divide game logic from model view.</p>
<p><a href="https://i.gyazo.com/a820e0297e1cb00cd5636877166662c5.png" title="Example"><img src="https://i.gyazo.com/a820e0297e1cb00cd5636877166662c5.png" alt="Example" title="Example" /></a></p>
<h3 id="codetemplatescs">CodeTemplates.cs</h3>
<p>A useful pack of scripts to generate code files in unity3d. Also with enhanced ScriptKeywordProcessor from Sarper Soher.</p>
<p><a href="https://i.gyazo.com/411120b4433f9be438c6e1cb28c96e4f.gif" title="Example"><img src="https://i.gyazo.com/411120b4433f9be438c6e1cb28c96e4f.gif" alt="Example" title="Example" /></a></p>
<p>In my case I’ve got this script :</p>
<div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="cm">/*===============================================================
Product: Battlecruiser
Developer: Dimitry Pixeye - pixeye@hbrew.store
Company: Homebrew - http://www.hbrew.store
Date: 16/04/2017 12:58
================================================================*/</span>
<span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">Homebrew</span><span class="p">{</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">BasicScript</span> <span class="p">:</span> <span class="n">MonoBehaviour</span> <span class="p">{</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>The easy steps to generate your own scripts.</p>
<ul>
<li>Open <strong>templates</strong> folder.
You can find it In your assets folder ProjectPref->Editor->CodeTemplates->Templates</li>
<li>Add a simple .txt file.<br />
For example BasicScript</li>
<li>Add some meat to your script!</li>
</ul>
<p>Customization rules :
The first line in your must be a path from where you will take the script template.
For example “BasicScripts/C# Scripts”</p>
<p><a href="https://i.gyazo.com/193ada0dad30c91e34d05e3a01644c82.png" title="Example"><img src="https://i.gyazo.com/193ada0dad30c91e34d05e3a01644c82.png" alt="Example" title="Example" /></a></p>
<p>You always should Add ##NAME## after class or interface. By default the name will be taken from the name of the template. Use prebuild tags for more advanced customization.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>#PROJECTNAME#
#DEVELOPERNAME#
#COMPANY#
#CREATIONDATE#
#NAMESPACE#
</code></pre>
</div>
<p>You can add more special tags if you want but in this case you should add them to postprocessor.
To do that open <strong>TemplateKeys.txt</strong> in ProjectPref->Editor->CodeTemplates->Settings</p>
<p>The structure of <strong>Templatekeys.txt</strong> must be similar to this template:</p>
<div class="highlighter-rouge"><pre class="highlight"><code> #CREATIONDATE#
[Time]
#PROJECTNAME#
[PlayerSettings.productName]
#DEVELOPERNAME#
Dimitry Pixeye - pixeye@hbrew.store
#COMPANY#
[PlayerSettings.companyName] - http://www.hbrew.store
#NAMESPACE#
Homebrew
</code></pre>
</div>
<ul>
<li>Odd line - the tag id braced in ‘#’</li>
<li>Even line - the description of the tag.</li>
<li>Use [Time] in description to add Current machine time</li>
<li>Use [PlayerSettings.productName] in description to get product name from unity3d project settings</li>
<li>Use [PlayerSettings.companyName] in description to get company name from unity3d project settings</li>
</ul>
<h3 id="summary">Summary</h3>
<p>I hope you will find this library helpful. You can download it as .unitypackage from <a href="https://www.dropbox.com/s/ciznv6od105ch89/ProjectSetup.unitypackage?dl=0" title="here">dropbox</a> or take it from <a href="https://github.com/dimmpixeye/Unity3d-Project-Setup" title="github">github</a></p>Pixeyepixeye@hbrew.storeThe bundle of useful scripts that helps to organize your project from scratch. Includes adding project, scene and object tree and coding templates generator.