tag:blogger.com,1999:blog-8649372264484395922024-03-05T11:19:16.097-08:00StrangewireGame Development and Game DesignStrangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-864937226448439592.post-9703933590134301322020-04-11T15:57:00.000-07:002020-04-11T15:57:11.363-07:00Property Drawers<h2>
<br />Explanation</h2>
So you implemented the <span style="color: #8e7cc3;"><b>FrameChecker</b></span> from the <a href="https://strangewire.blogspot.com/2019/09/frame-specific-attacks-in-unity.html" target="_blank">last post</a> but your editor is looking pretty bad. If you managed to make the <span style="color: #8e7cc3;"><b>FrameChecker </b></span>appear in the inspector, you are seeing 3 integer boxes. Besides not looking great, it's probably making it hard for you to quickly modify things and have an idea of what you are actually doing.<br />
<br />
Let's refresh what that class does. We created the <span style="color: #8e7cc3;"><b>FrameChecker</b></span> to give it an animation clip and a range of frames in which we want to do something. For example, an attack. The animation for a punch may have <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>12 frames</b></span></span></span>, but we only want to do damage in frames <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>4 to 8</b></span></span></span>.<br />
<h3>
</h3>
<h3>
Problems</h3>
With the standard inspector you can input any frame number. You could even input negative frame numbers, or one greater than the total number of frames. Also you could make the start of the range bigger than the end, like hitting in frames <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>9 to 2. </b></span></span></span>All of those are <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>invalid states</b></span></span></span></span></span> for our class, they break the <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>implicit contract</b></span></span></span></span></span> we were thinking of when we made it.<br />
<h3>
</h3>
<h3>
What do we want?</h3>
We want to enforce the contract, so you (or whoever uses this class) can only use valid inputs and therefore get valid outputs. Also we want a clear input interface and a way to provide visual feedback for valid and invalid values.<br />
<h3>
</h3>
<h3>
The Contract</h3>
<ul>
<li>The minimum possible frame number is <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>1</b></span>.</span></span></li>
<li>The maximum possible frame number is the <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>total frame number</b></span></span></span> that the animation has.</li>
<li><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>hitFrameEnd</b></span> </span></span>should be bigger than<span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>hitFrameStart</b></span></span></span> (they can't be equal).</li>
<li>I want a clear indicator of how many frames every<span style="color: #8e7cc3;"><span style="color: black;"> <a href="https://strangewire.blogspot.com/2019/09/frame-specific-attacks-in-unity.html" target="_blank">move stage</a> </span></span>has (Startup, Active and Recovery)</li>
</ul>
The first 3 we can enforce via code. You would have to use C# setters or a custom method because in this case<span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>FrameChecker is not a MonoBehaviour,</b></span> </span></span>so we can't use<span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>OnValidate().</b></span></span></span> I won't go into this because there's already a lot of<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <a href="https://stackoverflow.com/questions/6127290/c-sharp-add-validation-on-a-setter-method" target="_blank">answers all over the internet.</a></span></span></span></span><br />
Let's focus on the inspector.<br />
<h3>
</h3>
<h3>
Custom Inspectors and Property Drawers</h3>
<a href="https://docs.unity3d.com/Manual/editor-CustomEditors.html" target="_blank">Custom Inspectors</a> and <a href="https://docs.unity3d.com/Manual/editor-PropertyDrawers.html" target="_blank">Property Drawers</a> are types of scripts that allow us to customize the Unity Editor. The differences is that Custom Editors are used for MonoBehaviours and PropertyDrawers for any <span style="color: #8e7cc3;"><b>Serializable</b></span> class.<br />
<br />
If you create a standard C# class (as opposed to a Unity script that inherits from MonoBehaviour) you won't be able to see it in the inspector unless you make it <span style="color: #8e7cc3;"><b>Serializable.</b></span><br />
That's easy, you just need to add a line just before your class definition:<br />
<br />
<span style="color: #8e7cc3;"><span style="color: black;"><span id="docs-internal-guid-36914c7c-7fff-903a-1fdf-aaef120177a0" style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">[System.Serializable]</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">FrameChecker</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">...</span></span></span><br />
<br />
<span style="color: #8e7cc3;"><span style="color: black;"><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span></span><b> </b></span><br />
Note that as this class is not a <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>MonoBehaviour</b></span> </span></span></span></span>you can't add it directly to a<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>GameObject</b></span>, </span></span></span></span>you'll need to add it as a property in a script that inherits from<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>MonoBehaviour.</b></span></span></span></span></span><br />
If you made the class<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>Serializable</b></span></span></span></span></span><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> </span></span></span></span>you can now see it in the inspector as a list of it's public properties. Making a<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>Property Drawer</b></span> </span></span></span></span>will allow us to customize that.<br />
You can make all sort of <a href="https://www.reddit.com/r/Unity3D/comments/6tsnhe/how_not_to_create_a_pong_game_in_unity_xpost_from/" target="_blank">crazy things</a> with Custom Editors and Property Drawers, but what we want today is this:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicTBjxdRsDeVTqjzXBSYxQiCSxQoXWGU3l9_anJDU5ZJSAfixY8gzpwQ-VKlPs4lyfC8uyZL72TVrBzxtZdlNoNeZpZ0w2b7zf6J_B4M1T8PgaoOfmTje5QLkll9WGQNJC15B6m5ZmupU/s1600/screenshot.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="85" data-original-width="373" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicTBjxdRsDeVTqjzXBSYxQiCSxQoXWGU3l9_anJDU5ZJSAfixY8gzpwQ-VKlPs4lyfC8uyZL72TVrBzxtZdlNoNeZpZ0w2b7zf6J_B4M1T8PgaoOfmTje5QLkll9WGQNJC15B6m5ZmupU/s320/screenshot.16.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
To create a basic Property Drawer we need to do the following:<br />
<ul>
<li>Make a new class (I'll call it <span style="color: #8e7cc3;"><b>FrameCheckerDrawer</b></span>)</li>
<li>Make that class inherit from <span style="color: #8e7cc3;"><b>PropertyDrawer</b></span> </li>
<li>Declare an <a href="https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z0w1kczw(v=vs.100)?redirectedfrom=MSDN" target="_blank">Attribute </a>to let Unity know which class this <span style="color: #8e7cc3;"><b>PropertyDrawer</b></span> is for.</li>
<ul>
<li>Attributes are the things we declare inside square brackets, in this case it would be <br /><span style="color: #8e7cc3;"><b>[CustomPropertyDrawer(typeof(FrameChecker))]</b></span></li>
</ul>
<li>Override two methods: <span style="color: #8e7cc3;"><b>OnGUI</b></span> and <span style="color: #8e7cc3;"><b>GetPropertyHeight</b></span>. The first one is where we draw the inspector, in the second one we let Unity know how much space it will occupy.</li>
</ul>
So let´s see how that would look before we start actually coding the thing: <br />
<ul>
</ul>
<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> </span></span></span></span><br />
<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span id="docs-internal-guid-3bfc361b-7fff-e580-fa72-ab478d272ab0" style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">using</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> UnityEngine;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">using</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> UnityEditor;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">[CustomPropertyDrawer(typeof(FrameChecker))]</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">FrameCheckerDrawer</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> : PropertyDrawer {</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public override void </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">OnGUI</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(Rect position, SerializedProperty property, GUIContent label)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> ... </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public override float </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">GetPropertyHeight</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(SerializedProperty property, GUIContent label)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{ ...</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> }</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span> </span></span></span></span><br />
<br />
<br />
Let's determine the height first. If you check the image above you'll see that we have basically<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>4 rows</b></span></span></span></span></span>:<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> </span></span></span></span><br />
<ul>
<li>The name of the property (<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>Frame Checker</b></span></span></span></span></span>)<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> </span></span></span></span></li>
</ul>
<ul>
<li>The frame count and its distribution in every move stage</li>
</ul>
<ul>
<li>The active range in text, for easier reading.</li>
</ul>
<ul>
<li>The active range as a slidable range selector, for easier handling.</li>
</ul>
<br />
Each of these has the same height:<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>16px</b></span></span></span></span></span>, and the distance between them is<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>4px</b></span></span></span></span></span>. so the total height of our property drawer would be<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> <span style="color: #8e7cc3;"><b>80px</b></span> </span></span></span></span>(but you can use whatever height works for you).<br />
As we also need the particular height of every row to draw it, I'll create two constants for that and fill our <span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b>GetPropertyHeight</b></span></span></span></span></span> method.<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><br /></span></span></span></span><br />
<br />
<div dir="ltr" id="docs-internal-guid-f3ac37d5-7fff-c2e5-d9e4-d1cb2f0c5076" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">FrameCheckerDrawer</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> : PropertyDrawer {</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">const</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">int</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> yDistance = </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">20</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">const</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">int</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> fieldHeight = </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">16</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public override void </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">OnGUI</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(Rect position, SerializedProperty property, GUIContent label)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> ... </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public override float </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">GetPropertyHeight</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(SerializedProperty property, GUIContent label)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">return</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> yDistance * </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">4</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> }</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span></div>
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"></span><br />
<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><br /></span></span></span></span>
Now let's look at the actual drawing. We'll need a couple of things so, as I seem to really like dots, here's a list:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9sYKwbfO8-efcmeel-nBxhxrMj_B1PvTk6k-eiD5Z9g65yAPzqeoMJrDQf5goGrZu6jpfoJki-geBz466Ngh4zOqK0HYST22ZVBc09Qd2fTxogXlv40-wPsNXcIopNGqFAmyKyFYzr90/s1600/index.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="177" data-original-width="284" height="124" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9sYKwbfO8-efcmeel-nBxhxrMj_B1PvTk6k-eiD5Z9g65yAPzqeoMJrDQf5goGrZu6jpfoJki-geBz466Ngh4zOqK0HYST22ZVBc09Qd2fTxogXlv40-wPsNXcIopNGqFAmyKyFYzr90/s200/index.jpg" width="200" /></a></div>
<ul>
<li>Get the<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"> </span></span></span></span><a href="https://docs.unity3d.com/ScriptReference/SerializedProperty.html" target="_blank">serialized properties</a><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b> </b></span></span></span></span></span>for<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b> hitFrameStart, hitFrameEnd </b></span></span></span></span></span>and<span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><span style="color: black;"><span style="color: #8e7cc3;"><b> totalFrames</b></span></span></span></span></span></li>
<li>Make <a href="https://docs.unity3d.com/ScriptReference/Rect.html" target="_blank">Rects</a> for our 4 things to render (name, frames, active frames and the slider)</li>
<li>Use <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.html" target="_blank">EditorGUI</a> to render <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.LabelField.html" target="_blank">Labels </a>for our texts and <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.MinMaxSlider.html" target="_blank">MinMaxSlider </a>for our slider.</li>
</ul>
<br />
First let get the <span style="color: #8e7cc3;"><b>serialized properties</b></span>. If you are not familiar with serialization and why we need it, check <a href="https://docs.unity3d.com/Manual/script-Serialization.html" target="_blank">this</a>. To do this, we'll use the <span style="color: #8e7cc3;"><b>property</b></span> parameter that comes in the <span style="color: #8e7cc3;"><b>OnGUI</b></span> method, that's the actual serialized property we are drawing, so in this case it would be the <span style="color: #8e7cc3;"><b>FrameChecker. </b></span><br />
To get the properties, you just use their name:<br />
<br />
<span id="docs-internal-guid-e4b6e646-7fff-8c91-e918-f010af332411" style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">SerializedProperty hitFrameStart = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"hitFrameStart"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">SerializedProperty hitFrameEnd = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"hitFrameEnd"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">SerializedProperty totalFrames = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"totalFrames"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span> <br />
<span style="color: #8e7cc3;"></span><span style="color: #8e7cc3;"></span><br />
<br />
Using those we will be able to get the current value and make our inspector modify them.<br />
Now let's make the <span style="color: #8e7cc3;"><b>Rects,</b></span> we will need them to specify where every one of our rows is inside the inspector. For that we will use the <span style="color: #8e7cc3;"><b>position </b></span>parameter (that's the position that the Editor will start rendering the property) and add to its <span style="color: #8e7cc3;"><b>y component</b></span> the distance that precedes the row in question. For the height we just use <b><span style="color: #8e7cc3;">fieldHeight</span>.</b><br />
<br />
<span id="docs-internal-guid-beb05995-7fff-75f1-92ac-28187db5c44b" style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Rect nameRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Rect framesRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Rect hitFramesRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance * </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">2</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Rect sliderRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance * </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">3</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, position.width, fieldHeight);</span><br />
<br />
<br />
Now we'll use all of that to render. First we need to wrap all we do with <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.BeginProperty.html" target="_blank">BeginProperty and EndProperty</a> as we are gonna use <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.MinMaxSlider.html" target="_blank">MinMaxSlider</a> and it needs it to work properly. As we are on it, let's create a label to show the title of the property and then modify the <a href="https://docs.unity3d.com/ScriptReference/EditorGUI-indentLevel.html" target="_blank">indentLevel</a>, so the rest of our property will render nicely. Also, we should remember to decrease the indent level when we finish with this.<br />
<br />
<span id="docs-internal-guid-c9aa92c7-7fff-71f7-ae61-4406044048dd" style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">label = EditorGUI.BeginProperty(position, label, property);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">EditorGUI.LabelField(nameRect, property.displayName);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">EditorGUI.indentLevel++;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">frameRangeSlider(ref hitFrameStart, ref hitFrameEnd, totalFrames.intValue, framesRect, hitFramesRect, sliderRect);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">EditorGUI.indentLevel--;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">EditorGUI.EndProperty();</span><br />
<br />
<br />
As you can see, we also added a new method for our slider so the code is cleaner. If you are wondering what <span style="color: #8e7cc3;"><b>ref </b></span>means, check <a href="https://www.geeksforgeeks.org/ref-in-c-sharp/" target="_blank">this</a>.<br />
At this point, our OnGUI method should look like this:<br />
<br />
<span id="docs-internal-guid-59fdea43-7fff-0c2d-ecfe-b52c53136321" style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public override void </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">OnGUI</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(Rect position, SerializedProperty property, GUIContent label)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> SerializedProperty hitFrameStart = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"hitFrameStart"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> SerializedProperty hitFrameEnd = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"hitFrameEnd"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> SerializedProperty totalFrames = property.FindPropertyRelative(</span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"totalFrames"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect nameRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect framesRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect hitFramesRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance * </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">2</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect sliderRect = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Rect(position.x, position.y + yDistance * </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">3</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, position.width, fieldHeight);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> label = EditorGUI.BeginProperty(position, label, property);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.LabelField(nameRect, property.displayName);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.indentLevel++;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> frameRangeSlider(ref hitFrameStart, ref hitFrameEnd, totalFrames.intValue, framesRect, hitFramesRect, sliderRect);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.indentLevel--;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.EndProperty();</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><br />
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><br />
<br />
In that new method, first we'll be using <span style="color: #8e7cc3;"><b>hitFrameStart, hitFrameEnd and totalFrames</b></span> to build our texts. We will be using <a href="https://docs.unity3d.com/560/Documentation/Manual/StyledText.html" target="_blank">rich text</a> so we can use colors and formatting, create the LabelFields and give some basic style to them with <a href="https://docs.unity3d.com/ScriptReference/GUIStyle.html" target="_blank">GUIStyle</a>.<br />
Then we'll add the MinMaxSlider, using <span style="color: #8e7cc3;"><b>BeginChangeCheck() and EndChangeCheck()</b></span> as the documentation from <a href="https://docs.unity3d.com/ScriptReference/EditorGUI.BeginProperty.html" target="_blank">BeginProperty </a>says. <br />
<br />
<div align="left" dir="ltr" style="margin-left: 0pt;">
<table style="border-collapse: collapse; border: none;"><colgroup></colgroup><tbody>
<tr style="height: 0pt;"><td style="overflow-wrap: break-word; overflow: hidden; padding: 5pt 5pt 5pt 5pt; vertical-align: top;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public void </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">frameRangeSlider</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(ref SerializedProperty hitFrameStart, ref SerializedProperty hitFrameEnd, </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><br />
<span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> int</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> totalFrames, Rect framesRect, Rect hitRect, Rect sliderRect)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d6baad; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">// Must be a float to use the MinMaxSlider</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">float</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> start = hitFrameStart.intValue;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">float</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> end = hitFrameEnd.intValue;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> GUIStyle style = </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> GUIStyle(EditorStyles.helpBox);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> style.richText = </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">true</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">string</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> frames = </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"<b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + totalFrames + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b> frames"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">string</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> startUp = </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"<color=green><b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + (start - </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">1</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">) + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b> startup</color>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">string</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> active = </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"<color=red><b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + (end - start + </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">1</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">) + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b> active</color>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span> <span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">string</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> recovery = </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"<color=blue><b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + (totalFrames - end) + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b> recovery</color>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.LabelField(framesRect, frames + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">": "</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + startUp + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"| "</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + active + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"| "</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + recovery, style);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.LabelField(hitRect, </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"Hits in: <b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + start + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b> to <b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> + end + </span><span style="background-color: transparent; color: #889b4a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">"</b>"</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, style);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> // and here we add the MinMaxSlider with our values</span><br />
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span id="docs-internal-guid-f48b1537-7fff-9a75-232b-dcf818c01850" style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.BeginChangeCheck();</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> EditorGUI.MinMaxSlider(sliderRect, ref start, ref end, </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">1</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">, totalFrames);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">if</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> (EditorGUI.EndChangeCheck()) {</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> hitFrameStart.intValue = Mathf.RoundToInt(start);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> hitFrameEnd.intValue = Mathf.RoundToInt(end);</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> }</span></span><br />
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 10.5pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span></div>
</td></tr>
</tbody></table>
</div>
<br />
<br />
And we are done! Whenever you add a <span style="color: #8e7cc3;"><b>FrameChecker </b></span>to a script, you should see it with our new inspector. Remember that you need to put Editor scripts inside a <span style="color: #8e7cc3;"><b>folder called Editor in your Assets folder</b></span> for them to work.<br />
<br />
<br />
<div>
<h2>
So now what?</h2>
<div>
<br />
Any feedback or questions? Let me know in the comments!<br />
If you enjoyed the post, remember to check the <a href="https://www.patreon.com/strangewire">Patreon</a>!<br />
<br />
You can also follow Strangewire on <a href="https://twitter.com/strangewire" target="_blank">Twitter</a></div>
</div>
<div>
<br /></div>
Strangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.com0tag:blogger.com,1999:blog-864937226448439592.post-52305702608695810292019-09-02T14:19:00.000-07:002019-09-02T14:19:22.349-07:00Frame-specific attacks in Unity<h2>
Explanation</h2>
Why would I want to check specific frames? There's several situations where checking if an animation is in a specific frame comes in handy:<br />
<br />
<ul>
<li>If you remember my previous post about <a href="https://strangewire.blogspot.com/2018/05/hitboxes-and-hurtboxes-in-unity.html" target="_blank">Hitboxes and Hurtboxes</a>, one of the qualities we needed our hitboxes to have was that <span style="color: #8e7cc3;"><b>It should be able to check if it’s overlapping a Hurtbox in arbitrary frames. </b></span></li>
<li>Suppose you are making an action game and you want to have combos. You'll probably need a way to tell if an attack animation is in a frame that can be interrupted to chain the next move. Yo wouldn't want to chain the next punch if the first one didn't reached a certain point in the animation.</li>
<li>Maybe you want to have a certain range of frames marked as <i>parryable, </i>probably a few frames before the attack connects.</li>
<li>You could have a window of oportunity after a character misses an attack where getting hit makes more damage.</li>
</ul>
<div>
Examples are endless, but you can see where this is going: More control over our animations gives us more possibilities.</div>
<br />
The underlying logic (and code) for all the situations I mentioned will be the same, but in this post I'll center in one of those cases: I want to be able to tell an attack how many frames of <span style="color: #8e7cc3;"><b>startup, hit and recovery</b></span> it has. Or in other words, <b><span style="color: #8e7cc3;">Move Stages</span></b>.<br />
<br />
<h2>
Animation, Frames and Move Stages</h2>
<div>
So what do we see when we watch a fighting or action game? <i>Characters fighting each other, is it not obvious? </i>You may say, and you would be correct. But if we look deeper, what we are actually seeing are animation frames. Sprites being rendered one after the other at a fixed rate (Or polygons being moved and deformed at a fixed rate if you are in a 3D enviroment). </div>
<div>
This "fixed rate" is usually 60 or 30 frames per second for 3D games. In 2D games it depends on what the developer or artist wants: More frames per second will give you a smoother and more detailed animation, but it means more sprites need to be created for every action. Note that we are talking about <b><span style="color: #8e7cc3;">animation frames and not the speed the game runs at.</span></b> For a fighting game to be responsive enough to be good it should at least detect the player input at a high framerate, indepentendly of the type of animation used.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://media.giphy.com/media/5hqxHleQShKNi/giphy.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="176" data-original-width="245" src="https://media.giphy.com/media/5hqxHleQShKNi/giphy.gif" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i><span style="font-size: x-small;">SF3 runs at 60fps but it's animated at a much lower framerate (And it looks awesome).</span></i></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
As your probably know, an animation is composed of frames and has a duration that we can also measure in frames. Why would we want to measure an animation in frames? because as we stated previously we want to check if our animation is playing a specific frame. </div>
When you trigger an attack in a game it doesn't automatically hit the enemy. The character starts the animation by preparing the attack, it hits for some amount of time and then recovers from the movement. Playing with the duration of those phases is how you get "heavier" or "lighter" characters, moves or weapons.<br />
Here's an example from <span style="color: #8e7cc3;"><b>Dark Souls</b></span>, a quick Rapier that does small amounts of damage vs. a slower Great Club that does enourmos damage.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://i.makeagif.com/media/11-26-2015/MWLle1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="225" data-original-width="400" height="179" src="https://i.makeagif.com/media/11-26-2015/MWLle1.gif" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://thumbs.gfycat.com/DaringLinearHarlequinbug-size_restricted.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="304" data-original-width="540" height="179" src="https://thumbs.gfycat.com/DaringLinearHarlequinbug-size_restricted.gif" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i><span style="font-size: x-small;">Pay attention to the really long startup of the club</span></i></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both;">
Those stages of an attack animation are called <b><span style="color: #8e7cc3;">Move Stages.</span></b> Or Attack Phases, or any combination of those 4 words. As always, it depends on who you ask. I'll call them Move Stages just to be consistent.</div>
<div class="separator" style="clear: both;">
<br /></div>
<h3 style="clear: both;">
Move Stages</h3>
<div>
As we mentioned, an attack has 3 stages:</div>
<div>
<ul>
<li><b>Startup: </b>The frames before the attack hits, where the character is setting up the move.</li>
<li><b>Active frames: </b>The frames where the attack is hitting and hitboxes are checking collisions.</li>
<li><b>Recovery: </b>The frames after the attack hits or misses, where the character recovers.</li>
</ul>
<div>
Here's a nice graphic from <a href="http://shoryuken.com/">Shoryuken.com</a>:<br />
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0IIpaNeSiyery4p1IjrCmML2uxkEYvjA2bUmS5uRhbEJqnvv0o6C2wCbSCUJ2tlW8x7a8GtpXZTNYFSe68bst_lFKGVn0J0yi9U6tipjE9y7zFnLNG0IW8xgnpCTLx2IX91a7J0WQnC8/s1600/Cycle_de_vie.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="1335" height="95" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0IIpaNeSiyery4p1IjrCmML2uxkEYvjA2bUmS5uRhbEJqnvv0o6C2wCbSCUJ2tlW8x7a8GtpXZTNYFSe68bst_lFKGVn0J0yi9U6tipjE9y7zFnLNG0IW8xgnpCTLx2IX91a7J0WQnC8/s640/Cycle_de_vie.jpg" width="640" /></a></div>
<br /></div>
So when do we want our Hitboxes to check for collisions? You guessed right, in the <b><span style="color: #8e7cc3;">Active Frames Stage.</span></b><br />
Now that we know what we want, let's get to work! (This may seem obvious but never underestimate the power of actually knowing what problem you are trying to solve)<br />
<br />
<h2>
Quick solutions</h2>
<div>
As with every problem, there's the quick way and there's the more complicated way. Note that I didn't say one is <i>right</i> and one is <i>wrong</i>. <b><span style="color: #8e7cc3;">Which solution you choose should respond to what problem you have, the scope of the problem and how much time you are willing to invest to solve it.</span></b> Don't let yourself be distracted of your objective because some coding guru told you that the <i>right </i>way to iterate an array is an incredibly performant-functional-disruptive way that would take you 2 months to implement when you had it solved and working perfectly in 5 minutes with a for loop.</div>
<br />
Okay, rant over.<br />
There's 2 standard ways to change script values in specific frames of an animation:<br />
<ul>
<li><span style="color: #8e7cc3;"><b>Animating the parameters: </b></span>You can simply turn hitboxes on and off or change public script values while animating your character.</li>
<li><b><span style="color: #8e7cc3;">Animation Events:</span></b> You can add Animation Events to any frame you like of an animation and trigger a method from a class that is in the same GameObject. Check <a href="https://docs.unity3d.com/Manual/script-AnimationWindowEvent.html" target="_blank">here </a>if you don't know what I'm talking about.</li>
</ul>
<div>
These two methods could work perfectly depending on the needs of your game, and you can implement any of them in 5 minutes, so really evaluate what you need.<br />
<br /></div>
<h3>
The problems</h3>
<div>
<ul>
<li><b><span style="color: #8e7cc3;">No reusability:</span></b> You will have to go animation by animation modifying the values in the frames you want. </li>
<li><b><span style="color: #8e7cc3;">Mixing animation and events: </span></b>If you are doing everything by yourself this may not be a problem, but if you work with an artist having animation events or setting values in them could lead to mistakes when changing animations.</li>
<li>If using animation events you will need to have all the code in a monolitic class that the animations can access.</li>
</ul>
<div>
<br /></div>
<h2>
The long way</h2>
</div>
<div>
To solve the problems that we mentioned, we first need to understand how animations in Unity work.</div>
<br />
<h3>
Getting to know the components</h3>
<div>
In Unity, an animation is represented by an <b><span style="color: #8e7cc3;">AnimationClip. </span></b>It holds the keyframe data of an animation and you can reutilize it for different characters (if the animated objects respect the same hierarchy and have the same names).</div>
<div>
Unless you are rolling your own animation system, to actually play a clip you need an <b><span style="color: #8e7cc3;">Animator Controller. </span></b>An animator controller provides you with a node-based interface to handle animation states, layers, transitions, playback speed and animation blending. Here's where things can get a little complicated, but don't worry too much right now.<br />
<br /></div>
<div>
Let's enumerate some definitions:</div>
<div>
<ul>
<li>An Animation controller plays one State per layer.</li>
<li>A State has an AnimationClip</li>
<li>Layers are identified by a number stating at 0</li>
<li>You can query the controller for an <a href="https://docs.unity3d.com/ScriptReference/AnimatorStateInfo.html" target="_blank">AnimatorStateInfo </a>for a specific layer. </li>
<li>An AnimatorStateInfo gives us a number between 0 and 1 that represents the progress of the current state.</li>
<li>AnimatorStateInfo identifies states by a <a href="https://en.wikipedia.org/wiki/Hash_function" target="_blank">hash</a>.</li>
<li>We need to know if the animator is playing a certain state in a certain layer, and in which frame is the animation in the state.</li>
</ul>
<div>
<br /></div>
</div>
<div>
<h3>
Working</h3>
Lets get the hash fo the state. We need to make a string composed of the <b><span style="color: #8e7cc3;">name of the layer and the name of the state separated by a dot</span></b>, and then ask the Animator class what's the hash:<br />
<br />
<span id="docs-internal-guid-f8a97818-7fff-ae20-edfd-0159a254afc7"><span style="color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">string</span><span style="color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> name = animator.GetLayerName(layerNumber) + </span><span style="color: #889b4a; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">"."</span><span style="color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> + animatorStateName;</span><span style="color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">string</span><span style="color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> animationFullNameHash = Animator.StringToHash(name);</span></span><br />
<br />
If you have <a href="https://docs.unity3d.com/Manual/NestedStateMachines.html" target="_blank">Sub-state machines</a> the "name of the state" is composed the same way: <b><span style="color: #8e7cc3;">sub-state machine name and state separated by a dot.</span></b><br />
<b><span style="color: #8e7cc3;"><br /></span></b>
Note that <b><span style="color: #8e7cc3;">you get the layer name from an Animator instance, but the hash from the Animator class using a static method.</span></b><br />
<br />
As you can see there's some level of indirection to get the progress of a state. In cases like this I like to use <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods" target="_blank">Extension Methods</a>. Check the link if you don't know what extensions are. Be warned that some developers don't like extension methods because in some ways you are "hiding" your own methods in other classes. I'm not going to discuss that in this article but I recommend you do some googling and decide for yourself.</div>
<div>
Lets make an extension to check if the animator is playing a certain animation and another to check the progress of the current animation.</div>
<div>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">static</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">AnimatorExtension</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> {</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> public static bool </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">isPlayingOnLayer</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">this</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Animator animator, </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">int</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> fullPathHash, </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">int</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> layer)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> return</span><span style="color: #d3af86; font-family: consolas, sans-serif; font-size: 9pt; white-space: pre;"> animator.GetCurrentAnimatorStateInfo(layer).fullPathHash == fullPathHash;</span><br />
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> }</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> public static double </span><span style="background-color: transparent; color: #f06431; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">normalizedTime</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">(</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">this</span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> Animator animator, System.Int32 layer)</span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">{</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">double</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> time = animator.GetCurrentAnimatorStateInfo(layer).normalizedTime;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: #98676a; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">return</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> time > </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">1</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> ? </span><span style="background-color: transparent; color: #f79a32; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">1</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> : time;</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> }</span><span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></div>
<span id="docs-internal-guid-9c462b31-7fff-869c-b0ee-f46698c7dff3"></span><br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: #d3af86; font-family: "consolas" , sans-serif; font-size: 9pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">}</span><br />
<br />
Some notes about <span style="color: #f06431; font-family: consolas, sans-serif; font-size: 12px; white-space: pre;">normalizedTime</span>: </div>
</div>
<div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br />
<ul>
<li>We are not getting a frame number, we are getting a percentage.</li>
<li>From the API: <i>The integer part is the number of time a state has been looped. The fractional part is the % (0-1) of progress in the current loop.</i></li>
<li>Beware of transitions, depending on how do you use them you may skip frames and never get the value you expected in normalizedTime.</li>
<li>I'm clamping the value to 1 because, <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it" target="_blank">at least for now</a>, I don't need to use these methods in looping animations. If you need it you'll need to check if the loop changed when checking for a frame.</li>
<li>If you are not familiar with <a href="https://en.wikipedia.org/wiki/Extreme_programming" target="_blank">Extreme Programming</a>, the link it's worth a read. While I don't like to adhere any methodology as a dogma, XP certainly has several great principles.</li>
</ul>
<br />
With the code above we have a way of querying an animator for the progress of a certain state, but if want to work with animation frames <b><span style="color: #8e7cc3;">we need to convert that percentage to frames, or our frames to percentage.</span></b><br />
An AnimationClip has a <b><span style="color: #8e7cc3;">length </span></b>and a <span style="color: #8e7cc3;"><b>frameRate</b></span>. With those two values we can get the amount of frames of a clip:<br />
<br />
<span id="docs-internal-guid-1698d2a4-7fff-7a74-cd04-166742c9551e"><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int totalFrames = Mathf.RoundToInt(clip.length * clip.frameRate);</span></span><br />
<br />
With the number of frames and the extensions we made we can now convert frames to percentage (I stored <span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;">_totalFrames</span> as a property):<br />
<br />
<span id="docs-internal-guid-41be4876-7fff-daaa-5dfc-3a8ec8db218d"><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">percentageOnFrame</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> frameNumber)</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)frameNumber / (</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)_totalFrames;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span><br />
<br />
Now we can get the progress of a state and also what that number should be in every frame. One problem you probably guessed is that normalized time is not precise, at least not in my experience. If you do something like this you'll get mixed results:<br />
<br />
<span id="docs-internal-guid-52abac88-7fff-393b-68d2-507d2fd90cd4"><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// WARNING, read above</span></span></div>
public bool </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">itsOnFrame</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> frameNumber)</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> percentage = animator.normalizedTime(layerNumber);</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (percentage >= percentageOnFrame(frameNumber) && (percentage < percentageOnFrame(frameNumber + </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">1</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)));</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span><br />
<br />
Take this with a grain of salt but from what I tried the precision will vary based on the framerate of your animations. For what is worth, I'm using 16 samples per animation.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaoFAB9A186OUQz2HpK1i2WgWaWAzWvdxhOK3pR3m7VqLt7_TliQJNLLR-JkcOjhzdHN4gmBi1EG-N97NM4EJzgdGY-cUe5K2lP-qju4GO3f5BHkkyjdA_4R369yb33zt9Ikl-pRtD3U/s1600/AnimationEditorNewAnimationAdded.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="144" data-original-width="423" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaoFAB9A186OUQz2HpK1i2WgWaWAzWvdxhOK3pR3m7VqLt7_TliQJNLLR-JkcOjhzdHN4gmBi1EG-N97NM4EJzgdGY-cUe5K2lP-qju4GO3f5BHkkyjdA_4R369yb33zt9Ikl-pRtD3U/s320/AnimationEditorNewAnimationAdded.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: start;"><i><span style="font-size: x-small;">In the Animation tab it's called Samples, 60 by default.</span></i></span></div>
</div>
</div>
<div>
<br />
So how do we solve this? It will depend on the precision you need and your project.<br />
<br />
<ul>
<li>If you are always checking for several frames (for example if all your active frames are longer than 2 frames), you could probably get away with using the code above by checking the full range instead of every single frame.</li>
<li>You could start debbuging and determine, based on your animations, a buffer value to use when checking frames. Maybe when normalizedTime is really close to the next frame value you return true.</li>
<li>You could check for bigger or equal rather than just equal.</li>
</ul>
<div>
I went with the third option because it worked pretty well for my needs:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-b6e78467-7fff-a663-6296-843f293abe8a"><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public bool </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">biggerOrEqualThanFrame</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> frameNumber)</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> percentage = animator.normalizedTime(layerNumber);</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (percentage >= percentageOnFrame(frameNumber));</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<br />
<div>
<br /></div>
<div>
Obviously this method will return true in the frame we want and in all subsequent ones, so we need a flag to avoid repeating functionality we just wanted to run on that specific frame.</div>
<div>
While we are at it we could add a special case for the last frame, to avoid the aforementioned problem with transitions:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-1696b2f4-7fff-8459-2ff2-04a7d45068b7"><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public bool </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">itsOnLastFrame</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">double</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> percentage = animator.normalizedTime(layerNumber);</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (percentage > percentageOnFrame(_totalFrames - </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">1</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">));</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<div>
<br /></div>
<div>
Now that we have the methods we need, lets put them in a class that makes sense. We need a class that represents an Animation from our point of view, that you can ask in what frame it is, if it's active in an animator and how many frames does it have.</div>
<div>
I chose to call this class AnimationClipExtended. <a href="https://dzone.com/articles/naming-conventions-from-uncle-bobs-clean-code-phil" target="_blank">It's an awful name</a> and you are right in hating me right now. Feel free to suggest a better name! I'll be happy to change it.</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-720bb4d2-7fff-d319-d012-8c6142b318b6"><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">[System.Serializable]</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">AnimationClipExtended</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> {</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Animator animator;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> AnimationClip clip;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">string</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> animatorStateName;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> layerNumber;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _totalFrames = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _animationFullNameHash;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">initialize</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _totalFrames = Mathf.RoundToInt(clip.length * clip.frameRate);</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (animator.isActiveAndEnabled) {</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">string</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> name = animator.GetLayerName(layerNumber) + </span><span style="color: #889b4a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">"."</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> + animatorStateName;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_animationFullNameHash = Animator.StringToHash(name);</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public bool </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">isActive</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> animator.isPlayingOnLayer(_animationFullNameHash, </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> // ... And add the methods we worked on before.</span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://i.redd.it/sl7rauedzmgy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="535" height="320" src="https://i.redd.it/sl7rauedzmgy.png" width="213" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<i><span style="font-size: x-small;">In my defense, I intended to change the name later...</span></i></div>
<div style="text-align: center;">
<br /></div>
Using this class you should be able to add it to you Attack script and do whatever you want with the hitboxes, but if you want to check frame ranges in different classes you would be repeating a lot of code and <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank">we don't want that</a>. We can take one more step and make it more reusable by <b><span style="color: #8e7cc3;">encapsulating the frame range checking.</span></b> I would like to be able to:</div>
<div>
<ul>
<li>Give it a range to check</li>
<li>Handle the flags we talked about internally</li>
<li>Have some sort of callback when important events happen</li>
<li>Be reusable in any class we want</li>
</ul>
</div>
<div>
<br /></div>
<div>
For the callbacks lets take the same approach we did with Hitboxes and make an interface. If you want to know the rationale behind it check<a href="https://strangewire.blogspot.com/2018/05/hitboxes-and-hurtboxes-in-unity.html" target="_blank"> the post</a>.</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-3d3a03d1-7fff-7eb5-77e2-494de8bbddb1"><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> interface IFrameCheckHandler {</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">onHitFrameStart</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">onHitFrameEnd</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">onLastFrameStart</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">onLastFrameEnd</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<div>
<br /></div>
<div>
Now we have everything we need to make our class:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-bd04006e-7fff-2d9b-5376-bf2f11a7716d"><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">[System.Serializable]</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">FrameChecker</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> {</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> hitFrameStart;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> hitFrameEnd;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> totalFrames;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> IFrameCheckHandler _frameCheckHandler;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> AnimationClipExtended _extendedClip;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _checkedHitFrameStart;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _checkedHitFrameEnd;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> _lastFrame;</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>public void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">initialize</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(IFrameCheckHandler frameCheckHandler, AnimationClipExtended extendedClip)</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">frameCheckHandler = frameCheckHandler;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_extendedClip = extendedClip;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">totalFrames = extendedClip.totalFrames();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">initCheck();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">initCheck</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_checkedHitFrameStart = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_checkedHitFrameEnd = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_lastFrame = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">checkFrames</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (_lastFrame) {</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_lastFrame = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_frameCheckHandler.onLastFrameEnd();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (!_extendedClip.isActive()) { </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">; }</span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (!_checkedHitFrameStart && _extendedClip.biggerOrEqualThanFrame(hitFrameStart)) {</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_frameCheckHandler.onHitFrameStart();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_checkedHitFrameStart = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">} </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">else</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (!_checkedHitFrameEnd && _extendedClip.biggerOrEqualThanFrame(hitFrameEnd)) {</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_frameCheckHandler.onHitFrameEnd();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_checkedHitFrameEnd = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> (!_lastFrame && _extendedClip.itsOnLastFrame()) {</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">_frameCheckHandler.onLastFrameStart();</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">_lastFrame = </span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">; </span><span style="color: #d6baad; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// This is here so we don't skip the last frame</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 12px; white-space: pre-wrap;"> </span><span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<div>
<span><span style="color: #d3af86; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></span><br /></div>
<div>
We could use an enum to handle state changes instead of booleans, but then the last frame and the last active frame can't be equal. As always, it depends of your use case.</div>
<div>
<br /></div>
<div>
How do we use this class? </div>
<div>
<ul>
<li>Have an instance of it in the class we want to react to frame changes.</li>
<li>Declare that class as implementing <span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">IFrameCheckHandler.</span></li>
<li>Do whatever you need in the callback methods.</li>
<li>Call <span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">initCheck</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() </span>when the attack starts, or when the animation ends.</li>
<li>Call <span style="color: #f06431; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">checkFrames</span><span style="color: #f79a32; font-family: Consolas, sans-serif; font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() </span>in an update method (Remember that <a href="https://blogs.unity3d.com/es/2015/12/23/1k-update-calls/" target="_blank">we don't want to depend too much on Unity's API</a>, so it could be your own update method)</li>
</ul>
<div>
<br /></div>
<div>
And that's it! Here's a look at all of this in action in the game I'm working on:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAzEZKFq95cny6-Knc1zpl-RGY5hpjEYfuvvJUMSyeB9urr_2R5A_WJv_a5YWIdT_fyoEjE7vlWPGKBXmZsNAFdZBj3pE5oB785xsXzWdO2TqRuMZl6989aLdQq662ilkIFDr7bparFZY/s1600/blocks.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="480" data-original-width="640" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAzEZKFq95cny6-Knc1zpl-RGY5hpjEYfuvvJUMSyeB9urr_2R5A_WJv_a5YWIdT_fyoEjE7vlWPGKBXmZsNAFdZBj3pE5oB785xsXzWdO2TqRuMZl6989aLdQq662ilkIFDr7bparFZY/s400/blocks.gif" width="400" /></a></div>
<div>
<br /></div>
<h2>
So now what?</h2>
<div>
In my next post I'll probably delve a little in how I handle attacks and combos as the one you saw in the gif, with animation interruption and such.<br />
Also, with a really simple Editor script you can make the FrameChecker look like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHHZwDl9aOT8XXEmJcujNThFW3L0VsvAp5F2QDbVTUlwfRvdchyyD6cb-r_w1u5ZsNBqmbV4k0_-heXXobXqh18k5JlvZJ3UqCsXu3-KfkgQuY-RWxkXw2Klc5TwPoEtrI7Gut-6y4Wtk/s1600/screenshot.21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="64" data-original-width="384" height="65" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHHZwDl9aOT8XXEmJcujNThFW3L0VsvAp5F2QDbVTUlwfRvdchyyD6cb-r_w1u5ZsNBqmbV4k0_-heXXobXqh18k5JlvZJ3UqCsXu3-KfkgQuY-RWxkXw2Klc5TwPoEtrI7Gut-6y4Wtk/s400/screenshot.21.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />
Any feedback or questions? Let me know in the comments!<br />
If you enjoyed the post, remember to check the <a href="https://www.patreon.com/strangewire">Patreon</a>!<br />
<br />
You can also follow Strangewire on <a href="https://twitter.com/strangewire" target="_blank">Twitter</a>.</div>
</div>
<div>
<br /></div>
Strangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.com8tag:blogger.com,1999:blog-864937226448439592.post-17612869508685931742018-08-31T11:07:00.002-07:002018-08-31T12:09:48.128-07:00Unity Quick Tip: Snap to grid with arrow keys<br />
<h2>
Explanation</h2>
<div>
If you're working with pixel art in Unity, you know how difficult it can be to have a workflow that's fast and comfortable. First off, if you're not sure about the relationship between<span style="color: #8e7cc3;"><b> pixel art, PPU and Orthographic camera size</b></span>, you should read <a href="https://blogs.unity3d.com/es/2015/06/19/pixel-perfect-2d/">thist post</a> and <a href="https://gamedev.stackexchange.com/questions/141609/understanding-pixel-art-in-unity-2d">this thread.</a></div>
<div>
<br /></div>
<h2>
GameObjects Positions</h2>
<div>
As you know, <b><span style="color: #8e7cc3;">GameObjects </span></b>have a <span style="color: #8e7cc3;"><b>Transform </b></span>component that determines its position in the game world, measured in <span style="color: #8e7cc3;"><b>Units</b></span>. </div>
<div>
The problem when you're working with pixel art is that a GameObject position cannot be any number we want, it should be a multiple of our "pixel size". This means that if one pixel occupies 0.0625 units, we want every position to be a multiple of 0.0625. </div>
<div>
<span style="color: #8e7cc3;"><b>PPU </b></span>stands for <span style="color: #8e7cc3;"><b>Pixel Per Unit</b></span>, so as you probably guessed, our pixel size will be <span style="color: #8e7cc3;"><b>1/PPU</b></span>.</div>
<div>
<br /></div>
<h2>
Unity Built-in snapping</h2>
<div>
You should know that Unity has a built-in function to move objects a fixed amount. It's called <a href="https://docs.unity3d.com/Manual/PositioningGameObjects.html">Unit snapping</a>, you can customize the amount in <span style="color: #8e7cc3;"><b>Edit/Snap Settings</b></span> and move an object by that amount by <span style="color: #8e7cc3;"><b>dragging it while holding Ctrl.</b></span></div>
<div>
This helps, partially, because you can set your Snap amount to your pixel size in every axis and always move objects holding Ctrl. The problem is that if the starting position of the object is not a multiple of your pixel size, you will end up with a position thats outside the grid anyway, because snapping only moves the object by a fixed amount, it doesn't really snaps to a grid. Also, dragging objects is not precise, and it's uncomfortable.</div>
<div>
What we want is to be able to move an object using the arrow keys, and to make its position only take values that are multiples of our pixel size.</div>
<div>
<br /></div>
<h2>
Our own snapping</h2>
<div>
First off, calculate your pixel size. Remember that it is <span style="color: #8e7cc3; font-weight: bold;">1/PPU. </span>Personally I like to set it in Snap Settings in every axis, and I'll asume that you're doing it that way too, but you could store this value anywhere you like, just have in mind that we will need to be able to access it from an Editor script.</div>
<div>
The script itself is pretty simple so I'll make a broad explanation of what we are doing and you can check the details in the script itself. What we are doing is based on <a href="https://gist.github.com/dvddarias/dd4206dec54a3f48aa536126de2594b0">this script</a> to use the arrow keys, so be sure to check it out!.</div>
<div>
<ul>
<li>We will: </li>
<ul>
<li>Subscribe to <b><span style="color: #8e7cc3;">OnSceneGUIDelegate</span></b>, to be able to get the key events.</li>
<li>Check if the <span style="color: #8e7cc3;"><b>Move tool</b></span> is currently selected (You can ignore this if you want)</li>
<li>Check the current event to see if an arrow key is pressed</li>
<li>Get our pixel size from the <span style="color: #8e7cc3;"><b>Snap Settings</b></span> (or from anywhere you store it)</li>
<li>Check which direction we are moving</li>
<li>Get every selected object, add one pixel size to its position</li>
<li>Clamp the new position to our grid so every component is a multiple of our pixel size</li>
</ul>
</ul>
<div>
<br /></div>
</div>
<div>
<i>Note that we are only setting X and Y, that's because as we are working with pixel art I don't need to change the Z axis, but you could do it the same way.</i></div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-f949c73e-5dba-c2cc-72d4-f1954dec05c7"><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">using</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> System;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">using</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> System.Collections;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">using</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> UnityEditor;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">using</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> UnityEngine;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">[InitializeOnLoad]</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">ArrowEditorMove</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">static </span><span style="color: #f06431; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">ArrowEditorMove</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">//avoid registering twice to the SceneGUI delegate</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> SceneView.onSceneGUIDelegate -= OnSceneView;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> SceneView.onSceneGUIDelegate += OnSceneView;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">static void </span><span style="color: #f06431; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">OnSceneView</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">(SceneView sceneView)</span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> (Tools.current != Tool.Move) { </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">; }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Event currentEvent = Event.current;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> keyDown = currentEvent.isKey && currentEvent.type == EventType.KeyDown;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> arrowKeys = (currentEvent.modifiers == EventModifiers.None </span></span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> || currentEvent.modifiers == EventModifiers.FunctionKey); </span><span style="color: #d6baad; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">//arrow keys are function keys</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">//if the event is a keyDown on an orthographic camera</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> (keyDown && arrowKeys && sceneView.camera.orthographic) {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Vector3 movement = Vector3.zero;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> xStep = EditorPrefs.GetFloat(</span><span style="color: #889b4a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">"MoveSnapX"</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> yStep = EditorPrefs.GetFloat(</span><span style="color: #889b4a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">"MoveSnapY"</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">switch</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> (currentEvent.keyCode) {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> KeyCode.RightArrow:</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> movement.x = xStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> KeyCode.LeftArrow:</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> movement.x = -xStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> KeyCode.UpArrow:</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> movement.y = yStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> KeyCode.DownArrow:</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> movement.y = -yStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> moveSelectedObjects(movement, xStep, yStep);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">static void </span><span style="color: #f06431; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">clampPosition</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">(ref Vector3 position, </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> xStep, </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> yStep)</span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> position.x = Mathf.Round(position.x / xStep) * xStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> position.y = Mathf.Round(position.y / yStep) * yStep;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">static void </span><span style="color: #f06431; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">moveSelectedObjects</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">(Vector3 movement, </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> xStep, </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> yStep)</span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> UnityEngine.Object[] selectedObjects = Selection.GetFiltered(typeof(GameObject),</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> SelectionMode.Editable | SelectionMode.ExcludePrefab);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">for</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> (</span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> i = </span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">; i < selectedObjects.Length; i++) {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Transform objectTransform = (selectedObjects[i] as GameObject).transform;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Undo.RecordObject(objectTransform, </span><span style="color: #889b4a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">"Move Step"</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">); </span><span style="color: #d6baad; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">//allow undo of the movements</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Vector3 newPosition = objectTransform.position + movement;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> clampPosition(ref newPosition, xStep, yStep);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> objectTransform.position = newPosition;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">// only consume the event if there was at least one gameObject selected, otherwise the camera will move as usual</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> (selectedObjects.Length > </span><span style="color: #f79a32; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">) {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> Event.current.Use();</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"> }</span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 10pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<br />
Now just put this script in a folder named <b><span style="color: #8e7cc3;">Editor</span></b> inside your <span style="color: #8e7cc3;"><b>Assets</b></span> folder, if you don't have an Editor folder just create it.<br />
<br />
Any feedback or questions? Let me know in the comments!<br />
If you enjoyed the post, remember to check the <a href="https://www.patreon.com/strangewire">Patreon</a>!<br />
<br />
You can also follow Strangewire on <a href="https://www.facebook.com/Strangewire-199540187464125/">Facebook</a>, <a href="https://twitter.com/strangewire" target="_blank">Twitter</a>, <a href="https://strangewire.tumblr.com/">Tumblr</a>Strangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.com0tag:blogger.com,1999:blog-864937226448439592.post-39527282501985570392018-07-01T11:04:00.000-07:002018-07-08T21:27:47.770-07:00Unity Quick Tip: Editing .anim files<b><span style="color: #8e7cc3;"><br /></span></b>
<br />
<h2>
What's an .anim file?</h2>
<div>
An .anim file is created when we create a new animation clip in Unity. It contains all the data that the Animator needs to play a clip, be it object positions, names, rotations or anything else.</div>
<div>
<br /></div>
<div>
Actually these files are <a href="https://en.wikipedia.org/wiki/YAML">YAML</a>, you can simply open them with any text editor and change them.</div>
<div>
<br /></div>
<div>
<br /></div>
<h2>
Why would I want to manually edit these files?</h2>
<div>
That's a great question! You normally wouldn't want to edit them as text, you would use the Unity Animator. But the Animator, as you probably know, has some flaws.</div>
<div>
<ul>
<li>Changed an object name? The animation clip will lose the reference to it.</li>
<li>Want to change every position of every keyframe by a fixed amount? you'll need to edit them one by one.</li>
<li>You made some animations and then realized that the root bone had a different scale than 1 or you changed your sprites PPU? Changing those things would break all your animations.</li>
</ul>
<div>
<br /></div>
<h2>
Oh no! What can we do?</h2>
</div>
<div>
Do not worry! As we said we can open and edit these files manually, which means we can edit them with a script to change the values we need.</div>
<div>
<br /></div>
<div>
If you changed an object name, that's easy enough. Just search and replace as with any text.</div>
<div>
Object names are stored like this: <span style="color: #8e7cc3; font-weight: bold;">path: Bones/Hip</span>, so you just need to change that with your new object path.</div>
<div>
<br /></div>
<div>
If you changed your root bone scale, position o sprites PPU, you'll need to get the positional values of every object and make some operation with them.</div>
<div>
Positions are stored like this: <span style="color: #8e7cc3; font-weight: bold;">value: {x: 0.43749998, y: -0.31250006, z: 0}</span>.</div>
<div>
We need to parse the file, get every string that matches that format, get every number inside it and replace it with our new values. As an example let's say we want to multiply them by 2.</div>
<div>
<br /></div>
<div>
<br /></div>
<h2>
Dirty work</h2>
<div>
<i>Disclaimer: I know this code is awful and can be improved, but I know very little Python and just wanted to get the job done. Feel free to suggest a cleaner way to do it!</i></div>
<div>
<i><br /></i></div>
<div>
We will solve this using <a href="https://en.wikipedia.org/wiki/Python_(programming_language)">Python </a>and <a href="https://notepad-plus-plus.org/">Notepad++</a> (you could just as easily do it without Notepad++).</div>
<div>
First we'll need to download <a href="https://notepad-plus-plus.org/">Notepad++</a> (the 32-bit version) and <a href="https://sourceforge.net/projects/npppythonscript/">this plugin</a> that allows us to run Python scripts.</div>
<div>
Once you have everything set up, open Notepad++ and go to <b><span style="color: #8e7cc3;">Plugins/Python Script/New Script</span></b> to create a new script and call it whatever you want and paste this code:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-790e2140-5703-192a-e546-7ded46c5c968"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">def </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">multiply</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(match)</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">:</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> return "value: </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{x: </span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">" + "</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">".format(str(float(match.group(1))*2)) + "</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">, y: </span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">" + "</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">".format(str(float(match.group(3))*2))</span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">editor.rereplace(r'value: {x: ([+-]?([0-9]*[.])?[0-9]+), y: ([+-]?([0-9]*[.])?[0-9]+)', multiply)</span></span></div>
<div>
<span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div>
<div>
This code is defining a method that gets matches from a regular expresion and replaces them with what we tell it to. In this case, with the same string but with every number multiplied by 2. <br />
Note that I only included X and Y coordinates, because I'm working in 2D, but you can easily extend this to cover the Z axis.<br />
<br />
Now we just need to open the .anim file we want to edit and go to <b><span style="color: #8e7cc3;">Plugins/Python Script/Scripts/yourScript</span></b>, and it will change the file! Save it and go to Unity, once it's reimported you should see the changes in your animation right away.</div>
<div>
<br />
<h3>
Warning</h3>
<div>
While the code above will work and will change your animations, if you try to edit them in Unity the animator will go back to the previous state. That's because we didn't actually edited the local position of the objects. The problem is that a simple regular expression won't work for that and we'll need a YAML editor or something more powerful to do it but that escapes the scope of this post.</div>
<br /></div>
<div>
Any feedback or questions? Let me know in the comments!<br />
If you enjoyed the post, remember to check the <a href="https://www.patreon.com/strangewire">Patreon</a>!<br />
<br />
You can also follow Strangewire on <a href="https://www.facebook.com/Strangewire-199540187464125/">Facebook</a>, <a href="https://strangewire.tumblr.com/">Tumblr</a></div>
<div>
<br /></div>
Strangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.com1tag:blogger.com,1999:blog-864937226448439592.post-66660662523186220232018-05-13T10:16:00.000-07:002019-08-28T18:35:51.233-07:00Hitboxes and Hurtboxes in Unity<h2>
<br /> Explanation</h2>
So what are hitboxes and hurtboxes anyway? Aren’t they the same thing?<br />
<div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
Well... The answer can differ depending on who you ask, but here we will abide to the notion that hitboxes and hurtboxes are two different things and have different uses, as any fighting game worth mentioning does.<br />
A <b><span style="color: #8e7cc3;">Hitbox </span></b>is an invisible box (or sphere) that determines where an attack hits.</div>
A <b><span style="color: #8e7cc3;">Hurtbox </span></b>on the other side is also an invisible box (or sphere), but it determines where a player or object can be hit by a Hitbox.<br />
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="213" src="https://lh6.googleusercontent.com/0SqF0TGJaUhXutnE94Q1jwmz1mqiLO6Scu2Za6Rt_sU27Fg3xzblKrUDJjmzST9pLqDoM6FeS8jifdAsgfPgYsS4o7KPhNwahMQCk8MxfPMnOZWBDdH8Kd-boWB0MXQEz3aKudmG" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="380" /></span></div>
<div style="text-align: center;">
<i>In this image from <b><span style="color: #8e7cc3;">SFIV</span></b>, the red box is the hitbox and the green one the hurtbox</i></div>
<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="text-decoration-color: initial; text-decoration-style: initial;">It’s worth mentioning that the size and position of both hitboxes and hurtboxes change depending on </span>the frame of animation that is playing:</div>
<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="221" src="https://lh6.googleusercontent.com/Rta-LfgiH1cD0_l5ibBQwpgMHkIOLyf6kscVipnBBspuZRQ0cVCwmzXkxVzZReLdw-e9eSwzUzOjgSiwzKV3SlcYJLx95FzGcDczXbn9gaRap94uETAeHy3fxI1Im5NK6wy3Q7jU" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="402" /></span></div>
<div style="text-align: center;">
<i>Gif from <b><span style="color: #8e7cc3;">Killer Instinct</span></b>. Look how the hitboxes only appear on hitting frames and move with the sword</i></div>
<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
In the Killer Instinct example we can also see a third type of box, the <span style="color: #8e7cc3;"><b>Pushbox</b> </span>(the yellow one, the Hurtbox is the empty green box). A Pushbox is a box that represents the physical occupied space by a character, and keeps characters from overlapping.</div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
In most fighting games or brawlers there’s two other types of boxes that for simplicity we will not cover: <br />
The <b><span style="color: #8e7cc3;">grab or throw box</span></b><span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="font-size: 11pt; white-space: pre;">,</span></span> that determines where a character can be grabbed or thrown, and the <b><span style="color: #8e7cc3;">block box</span></b> that determines where an attacked player that’s pressing the back button will start blocking a certain attack instead of walking backwards.<br />
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
All these boxes are really important from a design point of view. Hitboxes and Hurtboxes of an attack determine not only how many frames an attack hits but also the blind spots of that attack and how vulnerable it leaves the player.<br />
For a great explanation on this focused on <b><span style="color: #8e7cc3;">Street Fighter</span></b> check <a href="https://www.youtube.com/watch?v=cL3lI9cLfuE">this video</a></div>
<br />
<h3>
Does this only apply to fighting games?</h3>
<div>
No! Almost every game has Hitboxes and Hurtboxes, from Dark Souls to Rayman, they can be three dimensional or two dimensional.</div>
<br />
So now that we have our terminology straight, let’s start working.</div>
<h2>
<br />What we want</h2>
<div>
Let’s check every type of box we’ll cover and see what we want from them:<br />
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="text-decoration-color: initial; text-decoration-style: initial;"><span style="color: #8e7cc3;"><b>Pushbox: </b></span></span>We need for two pushboxes to collide with each other and not overlap (that’s why it’s called a pushbox, it pushes the other character). Pushboxes should only interact with other pushboxes.</div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<b><span style="color: #8e7cc3;">Hurtbox:</span></b> It can register a hit, but it should not collide in the physical sense. Hurtboxes should only interact with Hitboxes.</div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="text-decoration-color: initial; text-decoration-style: initial;"><b><span style="color: #8e7cc3;">Hitbox: </span></b></span>It should be able to check if it’s overlapping a Hurtbox in arbitrary frames. It should only interact with Hurtboxes.<br />
<h2>
<br />Using Unity default components</h2>
</div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
The first approach one could do is map every kind of box that we talked about to a Unity default component. The obvious choice is some type of <b><span style="color: #8e7cc3;">Collider.</span></b></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
The Pushbox <span style="text-decoration-color: initial; text-decoration-style: initial;">can be directly mapped to a<span style="color: #8e7cc3;"><b> </b></span></span>Collider plus a <span style="text-decoration-color: initial; text-decoration-style: initial;"><b><span style="color: #8e7cc3;">Rigidbody</span></b></span>. That behaves exactly as we want it, it collides with things and doesn’t overlap.</div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
The only part we need to worry about (besides setting our Rigidbody as we want it) is the part about <span style="text-decoration-color: initial; text-decoration-style: initial;"><b><span style="color: #8e7cc3;">only colliding with other Pushboxes</span></b></span><span style="text-decoration-color: initial; text-decoration-style: initial;">.</span> If you’re familiar with Unity physics system, you already know that the solution is to use <a href="https://docs.unity3d.com/Manual/LayerBasedCollision.html">Layers and the Layer Collision Matrix</a>. For clarity we can create a layer called Pushbox<span style="text-decoration-color: initial; text-decoration-style: initial;">, assign it to our object and set the collision matrix so </span><b><span style="color: #8e7cc3;">Pushbox only collides with Pushbox.</span></b><br />
<b><span style="color: #8e7cc3;"><br /></span></b></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="47" src="https://lh6.googleusercontent.com/pzJ9xtgTjtK5xU33954ju7wZZ0WCp7D5OPx-U0xO_d56maTvUL1UghA3B3hjkZwnhf2mHgaU9tG-xAuGuDSxT10hGzYAS7RGspuDXEncfYDOjLVAgcTT--DuoA75z7DBNBDItOpy" style="border: none; transform: rotate(0rad);" width="514" /></span><br />
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="202" src="https://lh4.googleusercontent.com/qzkiJM3wpQFvVlnAdaaIlE0mfqT6l0S9gfxcLVX3UiyMqnlmgWMdRxodPwcLYoZZmEYCsjOZdh5RKfon0DfM6GavBRVXIQHhsVhsyG6K8yJ9fS8oIwGl3E3E9s1AfsLAPap2j80N" style="border: none; transform: rotate(0rad);" width="204" /></span><br />
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></div>
<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
For Hurtboxes we can use <span style="text-decoration-color: initial; text-decoration-style: initial;">a </span>Collider <span style="text-decoration-color: initial; text-decoration-style: initial;">using </span><b><span style="color: #8e7cc3;">isTrigger. </span></b>This ensures that it won’t collide in a physical sense and will only register other colliders entering it’s area. For actually registering the hit we will need to add a script in the same object that implements <b><span style="color: #8e7cc3;">OnTriggerEnter, </span></b>probably check the tag of the incoming collider to check that the one that triggered the event is the one we want and then do whatever damage and health calculations our game needs. You are probably familiar with this approach.<br />
We also need to create the layers Hurtbox and Hitbox, and use the Layer Collision Matrix again to make Hurtbox only collide with Hitbox and vice versa.<br />
<br /></div>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
Note that we don’t need a Rigidbody<span style="text-decoration-color: initial; text-decoration-style: initial;">, but only because I’m assuming that every trigger we will add is a child object of the </span>Pushbox object that already has a Rigidbody. This is important because Colliders <span style="text-decoration-color: initial; text-decoration-style: initial;">without a </span>Rigidbody <span style="text-decoration-color: initial; text-decoration-style: initial;">in itself or some of its parents will be set as <b><span style="color: #8e7cc3;">Static </span></b></span><span style="text-decoration-color: initial; text-decoration-style: initial;">by Unity and </span><b><span style="color: #8e7cc3;">moving them will be really inefficient. </span></b></div>
</li>
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
Also, we will probably need to distinguish between a Hitbox from the player or one from the enemies. The same goes for Hurtboxes. This way we can make the Hitbox from the player only hit the Hurtbox from the enemies, and the Hitboxes of the enemies only hit the Hurtboxes of the player. You don’t need this if you want to allow friendly fire, but you gotta be careful to avoid a player hitting its own Hurtbox.</div>
</li>
</ul>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br />
Hitboxes are maybe the least clear in how we should implement them. What we can use is a Collider using isTrigger <span style="text-decoration-color: initial; text-decoration-style: initial;">to avoid a physical collision, but there are really no colliders that “enter” a </span>Hitbox<span style="text-decoration-color: initial; text-decoration-style: initial;">. Actually is the other way around: A </span>Hitbox “enters” (<b><span style="color: #8e7cc3;">or checks if it’s overlapping</span></b>) a <span style="text-decoration-color: initial; text-decoration-style: initial;">Hurtbox</span><span style="text-decoration-color: initial; text-decoration-style: initial;"><span style="color: black; font-family: "arial"; font-size: 11pt; vertical-align: baseline; white-space: pre;"><span style="font-size: 11pt;"><span style="font-size: 11pt;">. </span></span></span>Nevertheless, we need a<span style="color: #8e7cc3;"> </span></span>Collider or <b><span style="color: #8e7cc3;">Unity will never call OnTriggerEnter</span></b> in our Hurtbox.<br />
For dealing damage to the Hurtbox we will need to add a script in the same object, so that our Hurtbox <span style="text-decoration-color: initial; text-decoration-style: initial;">can use <span style="color: #8e7cc3;"><b>GetComponent<T></b></span></span><span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="font-size: 11pt; text-decoration-color: initial; text-decoration-style: initial; white-space: pre;"> </span></span>and get it to know how much damage needs to be dealt. You can also do it the other way around, OnTriggerEnter gets called for both Colliders. We also need a way to make our Hitbox active only when we want to and not in every frame or when the character is not attacking for example. For this we can’t just disable our script because as the <a href="https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html">documentation</a> says: <i>“Trigger events will be sent to disabled MonoBehaviours, to allow enabling Behaviours in response to collisions”.</i></div>
What we can do is enable and disable the collider, or add a boolean property to our script that handles if it should hit or not.<br />
<h2>
<b style="font-weight: normal;"><br /></b></h2>
<h2>
Problems</h2>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<b><span style="color: #8e7cc3;">Hierarchy:</span></b> we need to have a script in every object with a Collider to be able to respond to OnTriggerEnter. If you like to have your scripts in the same place for organizational reasons, you will need to create a script just to delegate the call to your other object. </div>
</li>
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><b><span style="color: #8e7cc3;">Overhead:</span></b> With this approach our Hitboxes have a lot of functionality we don’t need. </li>
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><b><span style="color: #8e7cc3;">Events:</span></b> We rely on OnTriggerEnter for our functionality. Using <a href="https://docs.unity3d.com/Manual/EventFunctions.html" style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline;">Unity events</a> may not be a problem, but there’s <a href="https://blogs.unity3d.com/es/2015/12/23/1k-update-calls/" style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline;">reasons</a> to at least think if we should. You can also check <a href="https://unity3d.com/es/learn/tutorials/topics/performance-optimization/optimizing-scripts-unity-games" style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline;">this</a> (in the section<i>“Avoiding expensive calls to the Unity API”</i>) to know more.</li>
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><b><span style="color: #8e7cc3;">Visuals:</span></b> If you want to use different Hitboxes for different attacks, not only will the aforementioned problems repeat a lot, but you will have a lot of visual clutter on your editor window.</li>
<li dir="ltr" style="font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline;"><b><span style="color: #8e7cc3;">Little flexibility:</span></b> Using Colliders as Hitboxes means that if you want to change the shape of the collider, for example from a Box to a Sphere, you’ll have to remove the BoxCollider and add a SphereCollider manually (or implement an editor script to do this for you)</li>
</ul>
<div>
<br /></div>
<h2>
<br /> Rolling our own</h2>
As you probably realized while reading the previous section, Pushboxes and Hurtboxes map pretty much okay to Unity default components. <br />
Hurtboxes still have the problems mentioned and we will solve some of them, but the entity that seems to need its own abstraction is the Hitbox.<br />
If you’re making a combat heavy game with a lot of attacks and combos, you probably want to have all your attacks neatly organized in an object and use several combinations of Hitboxes for any of them.To do that you would need a script that strictly delegates OnTriggerEnter calls to your active attack or something along those lines.<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="292" src="https://lh6.googleusercontent.com/seomkI3rsGw-8E22U1joFqd8e1K2Y4fXxbz7u8BDFKEdSbh5cMtjS2Or9h_8ulYBKVb9laSDTmP6p6VOK3r1SzGDS6w_3sUG-f9hMp1x5bxvBUxTf0UJabZeDxCIh0Y4onfuvWCI" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="133" /></span><span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> </span><span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="210" src="https://lh4.googleusercontent.com/nXcEstnyP4GKAOa717tyjy7n3bGz1jX_xV3FH53R6fa-_qI-aZUnzAFypUMPJYxEdPeDjizQtPDB41AYwSQb2cYYq8WPPRIP9RnqouWV-IyimgkGoi5_rDp_tyFU8Ouz4Ad1A6-G" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="182" /></span></div>
<div style="text-align: center;">
<i>You don’t want to create a specific <b><span style="color: #8e7cc3;">Hitbox </span></b>object for every attack, here we can reuse the same changing the size!</i></div>
<h2 style="text-align: left;">
<i><br /></i> Hitboxes</h2>
Our new component will need to cover the following: <br />
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li>Have Hitbox behaviour: It should be able to check if it’s overlapping a Hurtbox in arbitrary frames. It should only interact with Hurtboxes. </li>
<li>Have a visual representation in the Scene view. </li>
<li>Be customizable and flexible. </li>
<li>Ideally, not depend on Unity API events. </li>
<li>Be independent enough to allow an script in another object to use it. </li>
<li>Not be coupled to a specific attack, Hitboxes should be usable by several different attacks.</li>
</ol>
<b style="font-weight: normal;"><br /></b>
<br />
<h3>
Behaviour</h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
First off, how do we check if some area is overlapping a Collider? The answer is to use <a href="https://docs.unity3d.com/ScriptReference/Physics.html">UnityEngine.Physics</a>.<br />
Physics has a lot of methods that can do what we want. We can specify the shape we want (Box, Sphere, Capsule) and also if we want to get the Colliders we hit (if any) as an array or pass an array to be filled with them. You shouldn’t worry right now about this, but the first one is allocating a new array, the other just fills the one you already had.<br />
<br />
Let’s start by checking a rectangular area and see if we hit something. For this we can use <span style="text-decoration-color: initial; text-decoration-style: initial;"><b><span style="color: #8e7cc3;">OverlapBox<span style="font-family: "arial";"><span style="font-size: 14.6667px; white-space: pre;">.</span></span></span></b></span><br />
<br />
We need to define the dimensions of the box we want to check. For this we need the center of the box, its half-extents, its rotation and the layers that it should hit. <b><span style="color: #8e7cc3;">Half-extents</span></b> are the half of the size in every direction, for example if you have a box with size (2, 6, 8) its half extents would be (1, 3, 4).</div>
For the center you can use the GameObject transform position and for the rotation the GameObject’s transform rotation or you can add public variables to set them specifically.<br />
Half-extents is simply a Vector3 so expose it and use it.<br />
For the layers to hit you can expose a public property of type <b><span style="color: #8e7cc3;">LayerMask</span></b>. That will let you select layers via the inspector.</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47e8-0bc0-4788-5d375636c0ae"><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Collider[] colliders = Physics.OverlapBox(</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">position</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">, boxSize, rotation, mask);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> (colliders.Length > </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">) {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline;"></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Debug.Log(</span><span style="color: #889b4a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">"We hit something"</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">);</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> }</span></span></div>
<div>
<br />
If you set that correctly and the box we are projecting is overlapping a Collider in the correct mask when you call this, you should see the message on the console.</div>
<div>
<h3>
<b style="font-weight: normal;"><br /></b>Visual Representation</h3>
That’s cool but... It’s not very functional. Right now we can’t see the box we are defining anywhere, it would be really difficult to set correct sizes and positions of Hitboxes this way.<br />
So how do we draw our box on the Scene view but not in-game? Using <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDrawGizmos.html">OnDrawGizmos</a>. <br />
As its <a href="https://docs.unity3d.com/ScriptReference/Gizmos.html">documentation</a> says: “<i>Gizmos are used to give visual debugging or setup aids in the scene view.</i>”, just what we were looking for!<br />
We need to give our <b><span style="color: #8e7cc3;">Gizmo </span></b>a color and a <a href="https://docs.unity3d.com/ScriptReference/Matrix4x4.html">transformation matrix</a>. Don’t worry about it, we’ll just create a matrix with the position, rotation and scale of our transform.<b style="font-weight: normal;"><br /></b>
<br />
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span id="docs-internal-guid-7ebf85ba-47e5-4be7-1cf0-edf39a822004"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #d3af86;"> </span>private</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">void</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> OnDrawGizmos() {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #d3af86; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">color</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> = Color.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">red</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span><br />
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.localScale);</span><br />
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.DrawCube(Vector3.zero, </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">new</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Vector3(boxSize.x * </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">2</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">, boxSize.y * </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">2</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">, boxSize.z * </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">2</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">)); </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">// Because size is halfExtents</span><br />
<span style="color: #d3af86; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<b style="font-weight: normal;"><br /></b>
<br />
If you want, you can use <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDrawGizmosSelected.html">OnDrawGizmosSelected</a> instead to only draw the box when you select the object.<br />
<h3>
<br /> Customization and flexibility</h3>
Customization is a broad subject and it’ll depend a lot on what kind of game you’re making and what functionality you are looking for. <br />
In this case we will allow for a quick change in hitbox shape and color. If you are using <b><span style="color: #8e7cc3;">Anima2D </span></b>or some kind of bone oriented animation, you’ll probably want to also allow for the Hitbox to scale following a bone scale.<br />
Changing the shape it’s as easy as adding a boolean and changing OverlapBox to some other shape, for example <span style="color: #8e7cc3;"><b>OverlapSphere</b></span>. You need to add a public radius property to configure the sphere. Remember that you’ll also need to change what’s inside OnDrawGizmos to actually draw the new shape (in our example, <span style="color: #8e7cc3;"><b>DrawSphere</b></span>).<br />
Note that we are not adding a new component or removing anything, it’s just a boolean that will select the shape to overlap when it checks collision. That allows us to change the shape of our hitbox basically for free depending on the attack (or even in the same attack if we want to).<br />
For color, I would like for a Hitbox to change color depending on if it’s inactive, if it’s checking for collisions or if it’s actually colliding with something. We will also need those states for our logic later so let’s add them.<br />
<br />
We’ll create an <b><span style="color: #8e7cc3;">enum </span></b>for the state and 3 colors and add them as properties of our Hitbox.<br />
<b style="font-weight: normal;"><br /><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">enum</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">ColliderState</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> {</span></b><br />
<span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a; font-size: 9pt;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;"> </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Closed</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">,</span><br />
<span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a; font-size: 9pt;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;"> </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Open</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">,</span><br />
<span style="color: #98676a; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;"> </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Colliding</span><br />
<span style="color: #98676a; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span><br />
<b style="font-weight: normal;"><br /></b>
<br />
Your class probably looks something like this:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47eb-9911-7afd-ab57ff5cadcf"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Hitbox</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">: MonoBehaviour {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> LayerMask mask;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">bool</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> useSphere = </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Vector3 hitboxSize = Vector3.one;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">float</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> radius = </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0.5f</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Color inactiveColor;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Color collisionOpenColor;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Color collidingColor;</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">private</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ColliderState _state;</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">/*</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">and your methods</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">*/</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span><br />
<b style="font-weight: normal;"><br /></b>
<br />
And now you can update your gizmos replacing the line <span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">color</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> = Color.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">red</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span> with a call to a new method:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47ed-fdf8-a03d-4a58ed390729"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> private</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">void</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> checkGizmoColor() {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">switch</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(_state) {</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ColliderState.Closed:</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">color</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> = inactiveColor;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ColliderState.Open:</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">color</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> = collisionOpenColor;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">case</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ColliderState.Colliding:</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Gizmos.</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">color</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> = collidingColor;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">break</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<br />
So where are we going to change our state? We will need three things:<br />
<div>
<ol>
<li>a way to tell the Hitbox to start checking for collisions </li>
<li>a way to tell it to stop </li>
<li>a way to actually check the collision</li>
</ol>
The first two are obvious:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47f0-2795-69b1-19dadeca687d"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">startCheckingCollision</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a;"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">_state = ColliderState.Open;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">stopCheckingCollision</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">_state = ColliderState.Closed;</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<br />
<div>
Now, while a Hitbox is active we want to check every frame if it’s colliding with something until it stops being active. That brings us to the next point…</div>
<div>
<h3>
<br /> Independence of Unity Events API</h3>
As you probably know, to check something every frame you can use <b><span style="color: #8e7cc3;">Update </span></b>(for sake of simplicity I didn’t add the check to change the shape):</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47f1-8569-e7a9-7da2dc070905"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> private void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Update</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> (_state == ColliderState.Closed) { </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">; }</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Collider[] colliders = Physics.OverlapBox(position, boxSize, rotation, mask);</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> (colliders.Length > </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">) {</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">_state = ColliderState.Colliding;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">// We should do something with the colliders</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">} </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">else</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> {</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">_state = ColliderState.Open;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br />
You can see we are returning only if the current state is “Closed”. This means we are still checking collisions if the Hitbox is colliding, wich allows the Hitbox to hit several objects at the same time and not only the first it hits. It depends on your game how you want this to work.<br />
We are using Update and we said we didn’t want to depend on Unity Events API! Well, depending on how you want to structure your code the solution is to make your own public update method, we could name it <b><span style="color: #8e7cc3;">hitboxUpdate </span></b>(the contents would be the same as our Update method above), and call it only in the Hitboxes used by the current attack. <br />
Obviously we would have a call to Update() in some object higher in the hierarchy, but we certainly don’t need to use it on every Hitbox all the time just because it’s there.<br />
<h3>
<br />Allowing an script in another object to use a Hitbox</h3>
</div>
Remember that a problem of using a Collider was that you needed a script in the same GameObject to implement OnTriggerEnter? As we are using our own script and can add to it whatever we want, the solution is pretty clear.<br />
We will add an object as a property so we could call some method on it when the Hitbox collides with something. <br />
There are several approaches to this:</div>
<div>
<ul>
<li>You can add a public GameObject and use <a href="https://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html">SendMessage</a>. (This is not performant at all) </li>
<li>You can do the same with a Monobehaviour that has a specific method to be called when a Hitbox collides. This has the disadvantage that if you want several different scripts to use Hitboxes you would need to add all those properties or inherit from a base script that has the method to be called</li>
<li>You can create an <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interface">interface</a> with the method you want to call and implement it in every class you want to use Hitboxes. </li>
</ul>
Design wise, an interface is the clear choice for me. The only problem in Unity is that the editor by default does not renders interfaces as public properties, so you can’t assign it via the editor. We’ll cover why that is not a real problem in the next point.<br />
<br />
Let’s create and use the interface:<br />
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="color: #98676a; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "consolas";"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> interface IHitboxResponder {</span><br />
<span id="docs-internal-guid-7ebf85ba-51a8-e741-0a67-f6d1fb7c71c3"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "consolas";"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">collisionedWith</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(Collider collider)</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">;</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<b style="font-weight: normal;"><br /></b>
<br />
Let’s add it as a property of our Hitbox…</div>
<div>
<br /></div>
<div>
<span style="color: #98676a; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "consolas";"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Hitbox</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> : MonoBehaviour {</span><br />
<span id="docs-internal-guid-7ebf85ba-51a8-1e28-b5a3-5c7a81c32e15"><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a; font-family: "consolas";"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">...</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">private</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> IHitboxResponder _responder = null;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">...</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">/*</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">and the rest of the class</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">*/</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<br />
You could also use an array instead of a single responder if you want.<br />
Let’s use the responder:</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-47f7-fa3d-f86f-8e8c86112d5f"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">hitboxUpdate</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">if</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> (_state == ColliderState.Closed) { </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">return</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">; }</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Collider[] colliders = Physics.OverlapBox(position, boxSize, rotation, mask);</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">for</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> (</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> i = </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">; i < colliders.Length; i++) {</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Collider aCollider = colliders[i];</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> _</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">responder?.collisionedWith(aCollider);</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">_state = colliders.Length > </span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ? ColliderState.Colliding : ColliderState.Open;</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<br />
If you’re not familiar with the ‘?’ operator, check <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators">this</a>. <br />
Cool! But how do we set the <span style="color: #d3af86; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;">_responder </span>property? Let’s add a setter and cover that in the next point.</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-4802-51fb-7dcd-3f8fc27cfd41"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">useResponder</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(IHitboxResponder responder)</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a;"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">_responder = responder;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<h3>
<br /> Not be coupled to a specific attack, Hitboxes should be usable by several different attacks</h3>
This section should make it clear why it doesn’t matter that we can’t set our <b><span style="color: #8e7cc3;">HitboxResponders </span></b>using the editor. <br />
First let’s talk about these “responders”. In the approach we took to implement our Hitboxes, a responder is any class that should do something when a Hitbox collides with a Collider, and therefore implements <b><span style="color: #8e7cc3;">IHitboxResponder</span></b>. An example would be an attack script, you probably want to do damage to the thing you hit.<br />
As we want to be uncoupled from any particular attack and be reusable, setting responders from the editor would not accomplish anything because we want to be able to swap responders on the fly.<br />
As an example, let’s suppose we have two types of attack, a straight punch and an uppercut with the same arm, and each one of them has its own script that says in which frames of the animation they should hit, how much damage they should do and those kind of things. As they both are attacks of the same extremity, let’s reuse the same Hitbox.</div>
<div>
<br /></div>
<div>
<span id="docs-internal-guid-7ebf85ba-4806-722d-5460-3f4e62448203"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Attack</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">: Monobehaviour, IHitboxResponder {</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="color: #98676a;"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">...</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> damage;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Hitbox hitbox;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">...</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">attack</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">()</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">hitbox.setResponder(</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">this</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">);</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">// and do the rest of your attack</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">collisionedWith</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(Collider collider)</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">Hurtbox hurtbox = collider.GetComponent<Hurtbox>();</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">hurtbox?.getHitBy(damage);</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<br />
Great! We got some working hitboxes. As you can see in the code above, we added a method <span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">getHitBy</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(int</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> damage</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">)</span> to our hurtboxes. Let’s check if we can improve those.</div>
<h3>
<br />Improving our Hurtboxes</h3>
<div>
Ideally we would want to cover more or less the same points we did with the Hitboxes. It should be easier because a Collider actually has the behaviour we want. Also we need to use a Collider or Physics.Overlap… won’t report a hit.<br />
Note that because of the way we structured our code, we don’t need to use OnTriggerEnter for anything, we are getting our script using GetComponent.<br />
That leaves us with customization and flexibility. To be as flexible as our Hitboxes we would need to add and remove colliders on the fly, and for customization we can draw a color over the collider depending on the state.</div>
<div>
<br /></div>
<div>
<span style="color: #98676a; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "consolas";"> </span></span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">class</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">Hurtbox</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> : </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">MonoBehaviour</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> {</span><br />
<span id="docs-internal-guid-7ebf85ba-51a6-da53-f077-4a9e2dc066a6"><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "consolas";"> </span></span></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> Collider collider;</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">private</span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> ColliderState _state = ColliderState.Open;</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">public bool </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">getHitBy</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">(int</span><span style="color: #f79a32; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"> damage</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">) </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">// Do something with the damage and the state</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">private void </span><span style="color: #f06431; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">OnDrawGizmos</span><span style="color: #98676a; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">() </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">{</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">// You can simply reuse the code from the hitbox,</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d6baad; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">// but taking the size, rotation and scale from the collider</span></div>
<div>
<span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; white-space: pre-wrap;">}</span></div>
<div>
<span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="color: #98676a; font-family: "consolas"; font-size: 12px; white-space: pre-wrap;"> </span><span style="color: #d3af86; font-family: "consolas"; font-size: 9pt; vertical-align: baseline; white-space: pre-wrap;">}</span></div>
<div>
<br />
Adding and removing Colliders on the fly is not as easy as with our Hitboxes. I haven’t found a satisfactory way to do this. What you can do is add several different Colliders to your script and select which one you want using a boolean as we did with the Hitboxes. the problem with this is that you need to add every Collider you want as a component and you end up with a lot of visual clutter in your editor window and in your object.<br />
Another approach is to add and remove the components via code, but that would add a lot of unnecessary garbage and probably not be as precise.<br />
What would be ideal is to be able to make Hurtbox inherit from Collider and make all the shape logic internal and only draw the one we are currently using, but I couldn’t make this work the way I wanted.</div>
<h3>
<br />So now what?</h3>
<div>
If you followed the post until here, you now have hitboxes, hurtboxes and pushboxes implemented in Unity. But most importantly, you now know those abstractions if you didn’t before and that will simplify everything you need to build on top of them.<br />
Your script inspector probably looks awful though, but don’t worry, we will cover that in another post:<b style="font-weight: normal;"><br /></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="165" src="https://lh5.googleusercontent.com/FfXMsT7oQ_a7-SEOGXqA6B3j8fLvw2lon09zBC3EvBRcvYp_KPvRkEl6s4OgaQ9Wht2IndsKkllqq6OH2lVd_qUHbXA8-RiTluU-0QFqzoESVHzH54ehDhjtL_O5TWjLs5U-7bUZ" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="514" /></span></div>
<div style="text-align: center;">
<i>You can convert this…</i></div>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><img height="245" src="https://lh4.googleusercontent.com/5z-DfrXrMVGRidyLtXs6YYhfufuP94se7J_d00k5b8-K2URW1MAwO_KYla94FKltbxFIqEYf5UmoSuzMsm3rdVtgKSD1l6DUycuaL_ddzVZiyDvoQ6HomFZFvrdQFVG9ad2PgnyQ" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="509" /></span></div>
<div style="text-align: center;">
<i>Into something like this!</i></div>
<br />
<br />
Any feedback or questions? Let me know in the comments!<br />
If you enjoyed the post, remember to check the <a href="https://www.patreon.com/strangewire">Patreon</a>!<br />
<br />
You can also follow Strangewire on <a href="https://www.facebook.com/Strangewire-199540187464125/">Facebook</a>, <a href="https://strangewire.tumblr.com/">Tumblr</a><br />
<br /></div>
</div>
Strangewirehttp://www.blogger.com/profile/09279427153219184221noreply@blogger.com5