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

<channel>
	<title>Gamelogic</title>
	<atom:link href="http://gamelogic.co.za/feed/" rel="self" type="application/rss+xml" />
	<link>https://gamelogic.co.za</link>
	<description>Tools and code for games.</description>
	<lastBuildDate>Wed, 14 Aug 2024 04:02:19 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://gamelogic.co.za/blog/wp-content/uploads/2024/04/cropped-gamelogic_icon-32x32.png</url>
	<title>Gamelogic</title>
	<link>https://gamelogic.co.za</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to document code</title>
		<link>https://gamelogic.co.za/2024/07/13/how-to-document-code/</link>
		
		<dc:creator><![CDATA[Herman Tulleken]]></dc:creator>
		<pubDate>Sun, 14 Jul 2024 00:41:02 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[clean code]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[writing]]></category>
		<guid isPermaLink="false">https://gamelogic.co.za/?p=5372</guid>

					<description><![CDATA[Documentation is secondary to good design. Well-designed code needs less documentation; it already expresses important ideas using the features of [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="has-drop-cap">Documentation is secondary to good design.</p>



<p>Well-designed code needs less documentation; it already expresses important ideas using the features of the programming language. For example, here are some important aspects of code design:</p>



<ul class="wp-block-list">
<li><strong>Names:</strong> Clear and descriptive names illuminate the function and operation of the code.</li>



<li><strong>Access control:</strong> Properly defined access levels indicate what can be known and modified by users, and implicitly, what is safe to modify or intended to be modified.</li>



<li><strong>Single path to success:</strong> Providing only one correct way to accomplish a task ensures consistent and correct implementation by engineers.</li>



<li><strong>Consistency:</strong> Maintaining consistency throughout the system simplifies its use and understanding. For instance, if you extend functionality through functional programming in one part of the system, avoid using inheritance in another.</li>
</ul>



<p>But the design cannot capture everything there is to know about code: a name cannot express all the constraints of a complex method; the architecture does not tell you <em>why</em> it was designed like that. This is where documentation comes in. Here, I will discuss the documentation that is included with the code:</p>



<ul class="wp-block-list">
<li>Doc comments</li>



<li>Error messages</li>



<li>Internal comments</li>



<li>Asserts</li>
</ul>



<h2 class="wp-block-heading"><a>Who will read your documentation?</a></h2>



<p>Like all writing, documentation is about transmitting ideas from your head to your readers. This requires that you think about them: What do they know? What do they want to know?</p>



<p>Broadly, your readers fall in two categories: users of your code, and maintainers of your code (the latter often includes yourself). Below we break these groups down further into different roles, with different needs. Thinking about these types of readers can help you write better documentation.</p>



<h3 class="wp-block-heading">Users</h3>



<h4 class="wp-block-heading">Assessors</h4>



<p>Assessors are people trying to figure out if they want to use your code (especially if it is a library).<br>They are interested in:</p>



<ul class="wp-block-list">
<li>Library purpose</li>



<li>Feature overview</li>



<li>Performance</li>



<li>Dependencies</li>



<li>Compatibility</li>
</ul>



<p>On a meta level, they are also interested in the quality of the documentation itself.</p>



<h4 class="wp-block-heading">Integrators</h4>



<p>Integrators are people trying to figure out how to use a system from your code.<br>They are interested in:</p>



<ul class="wp-block-list">
<li>Entry points</li>



<li>Integration steps</li>



<li>Examples</li>



<li>Troubleshooting</li>
</ul>



<h4 class="wp-block-heading">Consumers</h4>



<p>Consumers are people trying to figure out how a specific thing works or is meant to be used. They need to use it, but not necessarily integrate it – either because it has been done by someone else already, or it is not required. All C# programmers are consumers of the List type, for example.<br>The are interested in:</p>



<ul class="wp-block-list">
<li>What a method does, or a type or other entity represents</li>



<li>Contracts</li>



<li>Examples</li>
</ul>



<h4 class="wp-block-heading">Customizers</h4>



<p>Customizers are people trying to extend your system to fit their needs.<br>The are interested in:</p>



<ul class="wp-block-list">
<li>Customization hooks</li>
</ul>



<h3 class="wp-block-heading">Maintainers</h3>



<h4 class="wp-block-heading">Fixers</h4>



<p>Fixers are people trying to fix a bug in the code.<br>The are interested in:</p>



<ul class="wp-block-list">
<li>Details of how algorithms work</li>



<li>Links to authoritative sources of information</li>



<li>Invariants</li>



<li>Justification of choices</li>



<li>Pitfalls to avoid</li>
</ul>



<h4 class="wp-block-heading">Extenders</h4>



<p>Extenders are people trying to add a new feature to your code.</p>



<p>The are interested in:</p>



<ul class="wp-block-list">
<li>Customization hooks</li>



<li>Intended way to extend a system internally</li>



<li>Justification of choices</li>



<li>Alternatives considered (but not implemented)</li>
</ul>



<h4 class="wp-block-heading">Architects</h4>



<p>Architects are people trying to improve the design of the code.</p>



<p>The are interested in:</p>



<ul class="wp-block-list">
<li>Justification of choices</li>



<li>Alternatives considered (but not implemented)</li>
</ul>



<p class="has-ast-global-color-2-background-color has-background"> It is a mistake to think of the readers of your documentation simply as “users for your code”.</p>



<p>The two sets of readers correspond to two types of code documentation: doc comments and internal comments. But each of the specific use cases needs different types of documentation. When you write documentation, you need to consider <em>all</em> of them. If you don’t, your documentation will be lacking.</p>



<p class="has-ast-global-color-2-background-color has-background">There may well be other reader types; you can develop guidelines specific to them following the same line of thought as we use here.</p>



<p class="has-ast-global-color-2-background-color has-background">The roles above are not always different people. As a programmer, you probably take on all of these roles on a regular basis.</p>



<h2 class="wp-block-heading"><a>How will they read your documentation?</a></h2>



<ol class="wp-block-list">
<li><strong>They won’t.</strong></li>



<li>If they do, <strong>they will do it in a non-linear order</strong>: they visit the documentation in direct response to a problem they are having; not because they are drilling down from the top-level content.</li>



<li><strong>They’ll skim</strong>, looking for the exact piece they need to solve their problem. Therefore, they may well miss important information.</li>



<li><strong>They’ll read in a state of stress or annoyance. </strong>Since they are visiting the documentation in response to a problem, they are even more likely to be “poor” readers.</li>
</ol>



<p>One can argue that engineers should read documentation carefully, in the intended order, but the truth is that many don’t, and while it may hurt them, it also hurts you. No-one that rates an asset one star adds a disclaimer saying they did not read the docs so take their one-star with a pinch of salt. Players are not more tolerant to bugs caused by programmers not reading the docs. So, engineers not reading documentation is your problem.</p>



<p>Therefore:</p>



<ul class="wp-block-list">
<li>Design the code to minimize the need for documentation.</li>



<li>Lead engineers to important top-level documentation from specific documentation.</li>



<li>Make the content easy to skim. Use bullets, tables, and examples; carefully structure the content.</li>



<li>Important information should be easy to find from the perspective of something going wrong. If a user encounters an argument exception, the error should tell them what they did wrong, and not require them to read the library error handling documentation to find out what is the overall rules for arguments. (If such rules exist, the error message should also point to these).</li>



<li>Write well.</li>



<li>Proofread carefully, have it proofread, and test it on engineers.</li>



<li>Not everything is for everyone. We said that assessors will read your purpose; consumers typically won’t. Therefore, do not bother with information for consumers in your purpose doc. This will keep it more focused and relevant to the assessor that <em>will*</em> read it.</li>
</ul>



<p class="has-small-font-size">* might <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading"><a>Pieces of Documentation</a></h2>



<h3 class="wp-block-heading">Purpose and Feature Overview</h3>



<p>Summarize your library’s main features and reason for existence. This description should allow a reader to make an educated guess about whether what they may be looking for will be present. </p>



<p>If there are competing libraries, say what is the specific advantage (or tradeoff) using your library.</p>



<p>Briefly list the main features of your library, expanding on the summary mentioned above. This could introduce the entry points discussed below. </p>



<p>Include your design philosophy if you believe it will help the user choose or better understand your library. </p>



<p>Document next steps: how should users start learning the library? In smaller libraries, this may simply be pointing them to the main namespaces for them to drill down further. </p>



<h3 class="wp-block-heading">Entry Points</h3>



<p>In top-level documentation, list the key types of a system.</p>



<ul class="wp-block-list">
<li>How to create the system.</li>



<li>The core classes the user will interact with.</li>
</ul>



<p>All types that form part of a system need links (directly or indirectly) to the relevant entry points. Types without constructors should say how instances of them can be obtained.</p>



<p><br>The entry points are usually where you document aspects of the system the user needs to know, including the other pieces of information required for integration discussed below: integration steps, examples, and troubleshooting.</p>



<h3 class="wp-block-heading">Integration steps</h3>



<p>Document integration steps at the entry point. (If there is more than one, choose a principle one, and link there from the others).</p>



<p>If there are typical integration points or patterns to use, list them.</p>



<p>List the steps a user must take to integrate the system. Say:</p>



<ul class="wp-block-list">
<li>What types they need to define, if any.</li>



<li>What configuration objects they need to construct.</li>



<li>What central objects they need to construct.</li>



<li>What auxiliary objects they need to construct.</li>
</ul>



<p>Identify optional steps, and make it clear when the user should take them.</p>



<p>If there is more than one way to integrate the system, list them all. Explain when to use which.</p>



<h3 class="wp-block-heading">Examples</h3>



<p>Examples are very helpful to show how and when to use code.</p>



<p>Examples give you the opportunity to show terminology and best practices related to the feature. For example, if your API is designed to be used fluently, examples will make this clear.</p>



<p>Examples should be concrete, and from the domain the library is being used in. Examples should be from scenarios that could occur if possible.</p>



<p>If a feature was designed with specific use cases in mind, use those as examples. This is particularly important if your code abstracts a concept; engineers may not realize their concrete problem can be casted in your abstractions.<br>Use concrete examples that are easy to visualize. For example, if the domain is game development, then use types such as Player, Enemy, Monster.</p>



<p>In some cases the code may apply broadly, and not to a specific domain. Even then, use concrete examples. I like to use animals for objects; they make for vivid images, and are easy to put in hierarchies to show inheritance relationships through words such as Animal, Mammal, etc. It is also easy to come up with names for the start of the alphabet if you need something that can be sorted.</p>



<p>Avoid abstract entities such as <code>MyClass </code>or <code>Class1</code>, or letter.</p>



<p>If you have lots of examples in your code, you should define standards and apply them consistently.</p>



<p>One possibility is to use the same standards as applied to the code-base itself. This may be especially appropriate for internally used libraries.</p>



<p>It is, however, often desirable to have examples that are more compact than real code, so you may opt for more a permissive standard.</p>



<p>Internal standards may also be obscure; in this case you may choose a standard that is widely used (for example, Microsoft’s standard for .Net code).</p>



<p>Use real code compiled against the library when possible. This way the compiler can help ensure the documentation always has code that compiles and is up to date. Most documentation systems allow you to do this. It is usually tricky to get to work, but well worth the effort.</p>



<h3 class="wp-block-heading">Troubleshooting</h3>



<p>It is frustrating to use code that does not work as expected because of a configuration problem. Your design can help avoid incorrect configurations and carefully enforce contracts, but it may be impossible to avoid issues completely. How you report issues to the user is crucial in making your code useful and pleasant to work with.</p>



<p class="has-ast-global-color-2-background-color has-background">In some cases, providing helpful error messages requires changing the code design. For example, a parser might encounter various error states that only make sense within the context of how the parser works. Instead of just saying a bracket is missing, it&#8217;s more useful to tell the user that the system expects an &#8220;if-statement&#8221; and the syntax is incorrect. To provide this level of detail, the parser must be structured to have this context available when detecting errors.</p>



<p>Help the user deal with problems:</p>



<ul class="wp-block-list">
<li>List common problems.</li>



<li>Explain how they can program defensively to flag common issues.</li>



<li>Link to mechanisms a user can use to debug issues with the system.</li>



<li>Explain techniques a user can use to troubleshoot your system.</li>
</ul>



<h3 class="wp-block-heading">Exception error messages</h3>



<p>Logical errors should give information about the code that could help a user understand what they should change, and how. Application errors should have the information that could help them craft a suitable response, especially information that they may pass on to the user when their involvement is required.</p>



<p>Many errors are of the form: “expected something to have some condition, but instead it had a different condition”, for example, “Expected <strong>animal</strong> to be a <strong>cat</strong>, but it was a <strong>dog</strong> instead.” Messages for this error type should name all three things: what was inspected, what was expected, and what was observed.</p>



<p>In many cases you may well guess what happened: if you expect color values between 0 and 1, and see a value bigger than 1, the engineer probably forgot to normalize a byte. Similarly, if you see a large value when an angle in radians is expected, the engineer probably passed in an angle in degrees. Your message should refer to these common situations to speed things up:</p>



<p class="has-ast-global-color-3-background-color has-background">&#8220;Angle in ‘angle’ is larger than 2*Math.Pi. Did you pass in an angle in degrees?”</p>



<h3 class="wp-block-heading">Customization hooks</h3>



<h4 class="wp-block-heading">For customizers</h4>



<ul class="wp-block-list">
<li>There are a few standard ways in which a system can be customized, for example, using inheritance, supplying a configuration object, supplying functions or functors, and so on. List all these mechanisms at the entry point of the system, linking to other parts of the system if necessary.</li>



<li>Provide practical use-cases as examples.</li>
</ul>



<h4 class="wp-block-heading">For extenders</h4>



<ul class="wp-block-list">
<li>Extenders have all the hooks available that customers have, but because they can modify or add to the code base, they have additional mechanisms available. The additional mechanisms should be documented as an internal comment.</li>
</ul>



<h3 class="wp-block-heading">Algorithm details</h3>



<p>Some details of the algorithm should be given as the API documentation; the rest should appear as internal documentation. Where to put what is part of the design, but nothing should be omitted.</p>



<ul class="wp-block-list">
<li>Specify the name of the algorithm if it is a standard algorithm (for example, <code>MergeSort</code>).</li>



<li>Specify the contract the algorithm adheres to.</li>



<li>Specific features or optimizations (for example, using selection sort to sort small lists).</li>



<li>Give high level overview of the algorithm and its steps.</li>



<li>Use asserts throughout to test assumptions and invariants.</li>



<li>Document any “cleverness”, especially optimizations that rely on properties that are not immediately obvious.</li>



<li>Give the time and space complexity.</li>



<li>Provide links to algorithm descriptions (usually Wikipedia).</li>



<li>If you adapted source code, link to it, or if it is from a book, reference it.</li>
</ul>



<h3 class="wp-block-heading">Invariants</h3>



<p>An invariant is a property or condition that remains true throughout the execution of an algorithm or a portion of code. For example, in selection sort, the invariant at the end of the outer loop with index i is that the elements from 0 to i are in sorted order.</p>



<p>Invariants are often used to prove the correctness of algorithms, but they are very handy debugging aids.</p>



<p>The best way to add an invariant is through an assert statement. That way, your invariants are automatically checked when you run your code in debug mode. It is usually good to define validation methods for complex invariants. <code>Assert(BeginingOfListIstSorted(list, i))</code>.</p>



<p>Sometimes you need to do extra work to test a series of invariants. The neatest way to do this and have the code stripped out from Release builds is to define a method to check all the invariants, and make the method execute conditionally (in C#, by using the Conditional attribute.)</p>



<p>Many coding standards require that you need to add a message to assert. I am not sure this is that useful, as long as you use methods for complex assertions so the name can serve the purpose a message would.</p>



<p>Post conditions are usually better tested with Unit tests. However, in some cases you can perform a more precise or informative check using data internal to the method. In this case, asserting conditions on the return value is appropriate.</p>



<p>Predictions are usually checked explicitly so that you can throw appropriate exceptions. However, you may choose to limit these checks to public methods, and assume that they hold for private methods. In this case, it is appropriate to assert conditions on the parameters of a method. You may also choose not to do explicit checks for performance reasons. In this case, I would still add explicit tests but make them conditional on the mode (for example, only run them in debug builds).</p>



<h3 class="wp-block-heading">Design Choices</h3>



<p><strong>Document the reasons for your design choices.</strong> This will help others understand the intent of the code, and prevent them from making changes that could make the code worse in some way. For example, you may have chosen to use an array instead of a List because it allows you to use some other method without conversion. Documenting this will prevent someone from changing your method just to discover this fact later.</p>



<p><strong>Document design alternatives considered. </strong>This is helpful to prevent engineers from replicating that work when their intuition leads them to consider changing the system to one of these alternatives. List the alternatives you considered, how you evaluated them, and what criteria you used to make the final choice.</p>



<p>A series of these design considerations exhibit the underlying design philosophy or overarching goals of the library. Although thoughtful designers will document this on the outset, there will be a lot of principles and techniques that are revealed or discovered only after time.</p>



<h3 class="wp-block-heading">Implementation Pitfalls</h3>



<p>The first implementation of a method is often incorrect, because you are missing some detail or making some wrong assumptions. As you fix these problems, do document them in the code. Again, this will help a fixer with wrong assumptions from making changes that could break the code. <code>//I thought this list will never be empty, but it can be empty when...</code></p>



<p>This is particularly useful when you do checks to skip code. Why are the checks necessary? Why is it OK to skip the code?</p>



<h3 class="wp-block-heading">Entities</h3>



<p>When documenting entities (types and members), it&#8217;s crucial to address the needs of various readers. Documentation of entities commonly focuses on consumers but often neglects aspects important to customizers and extenders:</p>



<ul class="wp-block-list">
<li>For Consumers: Documentation typically covers what an entity means and how to use it. For example, when documenting an exception, describe what it signifies and how consumers can handle it.</li>



<li>For Extenders: Extenders need to know whether they should throw a specific exception or another one when implementing related features. Highlight the differences between similar exceptions to guide their decision, a point often overlooked.</li>



<li>For Customizers: Customizers look for whether an exception is suitable to extend from. Emphasize differences between exceptions to aid their choice, which is frequently neglected.</li>
</ul>



<p>As mentioned before, types that cannot be instantiated directly (abstract types, interfaces, types with private constructors) should specify how instances should be obtained. Clarify whether engineers are expected to create their own types or use provided ones. If both scenarios apply, describe what is typical or outline both explicitly.</p>



<p>Consider the user&#8217;s journey. Engineers often read about types because they encounter them as return or parameter types. For return types, explain what can be done with them. For parameter types, explain how to obtain instances.</p>



<h2 class="wp-block-heading"><a>Conclusion</a></h2>



<p>Good design reduces the need for extensive documentation, but it cannot replace it completely. Design and architecture lay the foundation, but documentation fills in the gaps by giving context, constraints, and use cases.</p>



<p>By considering the diverse needs of different readers, you can greatly enhance the usability, maintainability, and overall quality of your code.</p>



<p>Further reading:</p>



<ul class="wp-block-list">
<li><em><a href="https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670">Code Complete</a></em> by S. McConnell</li>



<li><em><a href="https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Clean Code</a></em> by R.C. Martin</li>



<li><a href="https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/">Framework design guidelines</a> (online)</li>



<li><em><a href="https://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613">Framework Design Guidelines: Conventions, Idioms, and Patterns for Reuseable .NET Libraries</a></em> by K. Cwalina, J. Barton, and B. Abrams.</li>
</ul>



<p class="has-background" style="background-color:#ffbab8"><em>I want to give a shout-out to my ex-colleagues at <a href="https://24bitgames.com/">24 Bit Games</a>, where the frequent discussions about code quality, design, clarity, and much more, was the soup in which these ideas took shape. </em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The design and implementation of object pools</title>
		<link>https://gamelogic.co.za/2024/07/08/the-design-and-implementation-of-object-pools/</link>
		
		<dc:creator><![CDATA[Herman Tulleken]]></dc:creator>
		<pubDate>Tue, 09 Jul 2024 06:12:16 +0000</pubDate>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[data structure]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[pool]]></category>
		<category><![CDATA[unity]]></category>
		<guid isPermaLink="false">https://gamelogic.co.za/?p=5300</guid>

					<description><![CDATA[Creating objects can sometimes be very expensive and lead to performance bottlenecks. A straightforward solution is to avoid recreating objects [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="has-drop-cap">Creating objects can sometimes be very expensive and lead to performance bottlenecks. A straightforward solution is to avoid recreating objects each time they are needed. Instead, we maintain a pool of inactive objects and activate them as required.</p>



<p>This general solution is known as the <strong>object pool design pattern</strong>.</p>



<p>If you are a game programmer, you may have seen the pattern described in Robert Bystrom’s <a href="https://gameprogrammingpatterns.com/object-pool.html"><em>Game Design Patterns</em></a>. His description and implementation are more relevant to languages such as C++. Here we look at the design and implementation of pools with a focus on C# and Unity.&nbsp;</p>



<h2 class="wp-block-heading"><strong>The problem</strong></h2>



<p>Here is more specifically the problems we can solve with an object pool:</p>



<ol class="wp-block-list">
<li>Repeatedly obtaining some resource (such as new objects or network connections) creates performance problems.</li>



<li>Allocating and deallocating lots of objects causes garbage collection pauses.</li>



<li>The number of resources of a certain type is limited, or you want to limit them. The number of simultaneous environment sounds is one example.</li>



<li>Our memory allocation pattern causes memory fragmentation, which can make it harder to get big blocks of memory.&nbsp;</li>
</ol>



<h2 class="wp-block-heading"><strong>A first implementation</strong></h2>



<p>The easiest way to implement an object pool is to use a stack of inactive objects.</p>



<p></p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">void InitPool(int n)
{
	inactiveObjects = new Stack&lt;Bat&gt;();
	
	for (int i = 0; i &lt; n; i++)
	{
		inactiveObjects.Push(new Bat());
	}
}

Bat Get() =&gt; inactiveObjects.Pop(); // what if the stack is empty
void Release(Bat obj) =&gt; inactiveObjects.Push(obj);</code></pre>



<p>And we will use the pool like this:</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">InitPool(100);

var bat = Get();
bat.Activate();

// Later...

bat.Deactivate();
Release(bat);</code></pre>



<p>This implementation suffers from a few issues:</p>



<ol class="wp-block-list">
<li>We need to repeat the three methods whenever we want an object pool. This is especially problematic when we need more than one pool in the same class.</li>



<li>We need to slightly modify the stack and methods for different types.&nbsp;</li>



<li>We could accidentally modify the stack in a way that is inconsistent with how we use it as a pool.&nbsp;</li>



<li>Running out of objects is handled poorly.</li>



<li>We need to remember to activate and deactivate objects when getting them from the stack and releasing them.&nbsp;</li>



<li>The code becomes messy if we want to implement a pool policy, such as behavior to execute when we do not have enough inactive objects.&nbsp;</li>
</ol>



<h2 class="wp-block-heading"><strong>A stack based pool</strong></h2>



<p>We can solve these issues by encapsulating the methods in a class, and adding a few small features. Since we will be introducing more pool types later, here is the common interface they all will implement:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp">public interface IPool&lt;T&gt; 
{
	int Capacity { get; }
	bool HasAvailableObject { get; }
	int InactiveObjectCount { get; }
	T Get();
	void Release(T obj);
	void IncreaseCapacity(int increment);
	int DecreaseCapacity(int decrement);
}</code></pre>



<p>And here is our stack-based implementation of this interface:</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public class StackPool&lt;T&gt; : IPool&lt;T&gt;
{
	private readonly Stack&lt;T&gt; inactiveObjects = new();
	private readonly Func&lt;T&gt; createActive;
	private readonly Action&lt;T&gt; activate;
	private readonly Action&lt;T&gt; deactivate;
	private readonly Action&lt;T&gt; destroy;

	public int Capacity { get; private set; }
	public int InactiveObjectCount =&gt; inactiveObjects.Count;
	public bool HasAvailableObject =&gt; inactiveObjects.Count &gt; 0;

	public StackPool(
		int capacity,
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; activate,
		Action&lt;T&gt; deactivate,
		Action&lt;T&gt; destroy)
	{
		Capacity = capacity;
		this.createActive = createActive;
		this.activate = activate;
		this.deactivate = deactivate;
		this.destroy = destroy;

		CreateActive(capacity);
	}

	private void CreateActive(int capacity)
	{
		for (int i = 0; i &lt; capacity; i++)
		{
			var newObject = createActive();
			deactivate(newObject);
			inactiveObjects.Push(newObject);
		}
	}

	public T Get()
	{
		if (inactiveObjects.Count == 0)
		{
			throw new InvalidOperationException("No available objects");
		}

		var obj = inactiveObjects.Pop();
		activate(obj);
		return obj;
	}

	public void Release(T obj)
	{
		deactivate(obj);
		inactiveObjects.Push(obj);
	}

	public void IncreaseCapacity(int increment)
	{
		Capacity += increment;
		CreateActive(increment);
	}

	public int DecreaseCapacity(int decrement)
	{
		int inactiveDecrement = inactiveObjects.Count &lt; decrement ? inactiveObjects.Count : decrement;
		
		for (int i = 0; i &lt; inactiveDecrement; i++)
		{
			var obj = inactiveObjects.Pop();
			destroy(obj);
		}

		Capacity -= inactiveDecrement;
		return inactiveDecrement;
	}
}</code></pre>



<p>Note the following:</p>



<ul class="wp-block-list">
<li>It is much easier to use the pool anywhere we need it.</li>



<li>The stack cannot be accidentally modified by a user.&nbsp;&nbsp;</li>



<li>It is generic, so we can pool objects of different types. To allow this we have to take in the createActive function.&nbsp;</li>



<li>The pool automatically activates and deactivates objects as they are being obtained and released. To allow this we have to take activate and deactivate actions.</li>



<li>The pool provides a way for the user to check whether there is an object available, and throws an exception when the user tries to get an object but cannot.&nbsp;</li>



<li>The pool supports crude resizing. To allow this, we take a destroy action.&nbsp;</li>
</ul>



<h2 class="wp-block-heading"><strong>For pool users: how to implement the pool delegates</strong></h2>



<p>The pool user needs to supply the pool with four delegates. Here are notes on how these delegates should be implemented.&nbsp;</p>



<p><strong>createActive:</strong> This function should create an active object. The pool will deactivate them after they have been created. If this seems slightly counter intuitive, note that creation functions (such as Unity’s <code>Instantiate</code>) usually give objects that are active by default, so if we required users to supply inactive objects, they would have to deactivate the objects themselves.&nbsp;</p>



<p>This function should do any work that does not need to be repeated, including allocating the resources for the class to use. If you create and destroy objects in your <code>activate</code> and <code>deactivate</code> actions, that could work against your pooling strategy — so instead those objects should be created and destroyed in the create and destroy delegates, and made active and inactive as the main object itself.</p>



<p><strong>activate:</strong> This action should prepare the object for use, for example, make it visible, start coroutines, etc. This action should not create objects. Be careful to not accidentally allocate memory when activating objects (for example, by duplicating a material by setting its color or calling an allocating LINQ method).&nbsp;</p>



<p><strong>deactivate:</strong> This action should make the object inactive: make it invisible, stop its update from running, stop coroutines, and so on. It should also make any of the objects it controls inactive, especially if they were created or became active after the object itself became active.&nbsp;</p>



<p>If the object acquired resources that cannot be reused, this action should release them. (If this behavior of your object causes garbage collection pauses, you need to redesign how these resources are managed so they too can be reused instead.)</p>



<p><strong>destroy: </strong>This action is only invoked when the capacity of the stack is reduced. It should destroy the object if it is required to do so, as is the case with Unity objects. Generally, this object should not replicate any work of the deactivate action. Instead, the pool should invoke the deactivate action before destroying objects if this is necessary.&nbsp;</p>



<h2 class="wp-block-heading"><strong>Pool variations</strong></h2>



<p>Our <code>StackPool</code> class is still pretty crude. In this section, we will look at some variations of pools that are more robust or implement specific pooling policies.</p>



<ul class="wp-block-list">
<li><strong>Self-growing pool:</strong> Automatically increases capacity as needed.</li>



<li><strong>Active object tracking pool:</strong> Keeps track of active objects too, allowing us to forcibly release objects when needed.&nbsp;</li>



<li><strong>Priority pools:</strong> Can release active objects based on priorities assigned to them.&nbsp;</li>



<li><strong>Fake pools:</strong>&nbsp; Do not really pool and are used for benchmarking.&nbsp;</li>
</ul>



<h3 class="wp-block-heading">Self-growing pool</h3>



<p>This pool increases the pool capacity when we need an object and we are out of inactive objects.&nbsp;</p>



<ul class="wp-block-list">
<li>We usually start the pool at capacity 0, so it never creates more objects than is required.&nbsp;</li>



<li>We usually grow the capacity by one if needed, but if there is overhead involved, we may grow it by a larger number to reduce the effect of this overhead.&nbsp;</li>



<li>It is common to allow the user to specify a maximum capacity.&nbsp;</li>
</ul>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public class SelfGrowingPool&lt;T&gt; : IPool&lt;T&gt;
{
	public StackPool&lt;T&gt; pool;
	
	public int Capacity =&gt; pool.Capacity;
	
	public int InactiveObjectCount =&gt; pool.InactiveObjectCount;

	public bool HasAvailableObject =&gt; pool.HasAvailableObject;

	public SelfGrowingPool(
		int initialCapacity,
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; activate,
		Action&lt;T&gt; deactivate,
		Action&lt;T&gt; destroy) 
		=&gt; pool = new StackPool&lt;T&gt;(initialCapacity, createActive, activate, deactivate, destroy);

	public T Get()
	{
		if (!pool.HasAvailableObject)
		{
			pool.IncreaseCapacity(1);
		}

		return pool.Get();
	}

	public void Release(T obj) =&gt; pool.Release(obj);
	public void IncreaseCapacity(int increment) =&gt; pool.IncreaseCapacity(increment);
	public int DecreaseCapacity(int decrement) =&gt; pool.DecreaseCapacity(decrement);
}</code></pre>



<h3 class="wp-block-heading">Active object tracking pools</h3>



<p>Our simple StackPool does not keep track of objects obtained through Get. This has some problems:</p>



<ul class="wp-block-list">
<li>If the user forgets to release objects, they are lost forever.</li>



<li>There is no easy way to release all objects.</li>



<li>We cannot reduce the pool capacity below the number of inactive objects in a robust way.&nbsp;</li>



<li>There is no guarantee that we created an object we are asked to release (potentially causing&nbsp;very subtle bugs).&nbsp;</li>
</ul>



<p>We can address these issues if we also keep track of the active objects we hand over to the user. For the collection of active objects, we need a data structure that allows us to add and remove specific objects efficiently. This is in contrast with the inactive objects, where we only need to remove <em>any </em>object efficiently.</p>



<p>For pools that are not very big, it is fine to use a list and search for the item. For bigger pools, a set is appropriate.&nbsp;</p>



<p>Here, we will be using <strong>hash sets</strong>, which work with any type as long as the type is safe to hash. An alternative strategy would be to use <strong>ordered sets</strong>, which works on any type as long as the type is orderable. We can wrap objects to allow them to be either hashed or ordered.&nbsp;</p>



<ul class="wp-block-list">
<li>Using hash sets gives us a better performance guarantee (constant time insertion&nbsp;and deletions, versus logarithmic time for ordered sets).</li>



<li>To implement priority pools described below, we also would like to use our objects in dictionaries, so we would need our objects to be hashable anyways.&nbsp;</li>
</ul>



<p class="has-background" style="background-color:#f9ee34"><strong>When are objects safe hash? </strong>Objects are safe to hash when equal objects have equal hash codes. This constraint can be violated if a class carelessly overrides one (or both) of the <code>GetHashCode</code> or <code>Equals</code> methods in a way that breaks it. When using a type in a hash set or dictionary, check whether the class has overridden either of these, and if so, whether it has been done to satisfy the hashing constraint.&nbsp;</p>



<h3 class="wp-block-heading">Priority pools</h3>



<p>When we do not have enough inactive objects when a new one is required, one strategy is to release an active object and re-use that instead. Often, we want to do this based on some type of priority — for example, oldest first, or smallest first, or least important first. We will assume these priorities do not change more frequently than we need to get objects from the pool.</p>



<p>To support prioritized release, we need to track active objects, as with an active-tracking pool. And as before, if the amount is small enough to use a list, we may simply look for the least element through the list linearly. For larger pools, we want a data structure that allows efficient adding objects, removing of the minimum, and efficiently removing specific objects. Assuming priorities do not change frequently, a data structure that does this is an <strong>index priority queue</strong>.&nbsp;</p>



<p>Assuming we do not want to modify the objects we pool, we can use a dictionary to keep track of object indices, making entries into the dictionary as we create objects. As with the active tracking object pools, this means our type needs to be safe to hash.&nbsp;</p>



<p>For priority pools, it is useful to also provide <code>ReleaseMin(int n = 1)</code> method that can be used by the <code>DecreaseCapacity</code> method if you also allow active objects to be destroyed.&nbsp;</p>



<p>If the priorities of objects can change, we need to update them in the index priority queue. We can add a method for this to the pool.&nbsp;&nbsp;</p>



<p class="has-background" style="background-color:#f9ee34"><strong>What is an index priority queue?</strong> This little-known data structure provides quick access to elements by index, while also maintaining the min element efficiently. It is described in <a href="https://algs4.cs.princeton.edu/home/"><em>Algorithms</em> 4th Edition</a> (2011) by Robert Sedgewick and Kevin Wayne, and also in <a href="https://www.geeksforgeeks.org/indexed-priority-queue-with-implementation/"><em>Index Priority Queue with Implementation</em></a> on Geeks for Geeks.&nbsp;</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public class PriorityPool&lt;T, TPriority&gt; : ITrackedPool&lt;T&gt;
{
	private readonly Action&lt;T&gt; reactivate;
	private readonly Func&lt;T, TPriority&gt; getPriority;
	public StackPool&lt;T&gt; pool;
	private readonly IndexPriorityQueue&lt;T, TPriority&gt; activeObjects;
	private readonly Dictionary&lt;T, int&gt; objectToIndex;

	public int Capacity =&gt; pool.Capacity;	
	public int ActiveObjectCount =&gt; activeObjects.Count;
	public int InactiveObjectCount =&gt; pool.InactiveObjectCount;
	public bool HasAvailableObject =&gt; pool.HasAvailableObject;
	
	public PriorityPool(
		int initialCapacity,
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; activate,
		Action&lt;T&gt; reactivate,
		Action&lt;T&gt; deactivate,
		Func&lt;T, TPriority&gt; getPriority,
		IComparer&lt;TPriority&gt; priorityComparer, 
		IEqualityComparer&lt;T&gt; objectComparer)
	{
		this.reactivate = reactivate;
		this.getPriority = getPriority;
		int objectCount = 0;
		pool = new StackPool&lt;T&gt;(initialCapacity, CreateActive, activate, deactivate, Destroy);
		activeObjects = new IndexPriorityQueue&lt;T, TPriority&gt;(initialCapacity, priorityComparer);
		objectToIndex = new Dictionary&lt;T, int&gt;(objectComparer);
	
		return;

		T CreateActive()
		{
			var obj = createActive();
			objectToIndex[obj] = objectCount++;
			return obj;
		}
		
		// Nothing to do
		void Destroy(T _){}
	}

	public T Get()
	{
		T obj;
		int index;
	
		if (pool.HasAvailableObject)
		{
			obj = pool.Get();
			index = objectToIndex[obj];
		}
		else
		{
			(index, obj) = activeObjects.Dequeue();
			reactivate(obj);
		}
	
		activeObjects.Enqueue(index, obj, getPriority(obj));
		return obj;
	}

	public void ReleaseMin()
	{
		(int _, var obj) = activeObjects.Dequeue();
		Release(obj);
	}

	public void Release(T obj)
	{
		pool.Release(obj);
		activeObjects.Remove(objectToIndex[obj]);
	}
	
	public int ReleaseMin(int count)
	{
		int releasedCount = 0;
		while (releasedCount &lt; count &amp;&amp; !activeObjects.IsEmpty)
		{
			ReleaseMin();
			releasedCount++;
		}

		return releasedCount;
	}
	
	public void UpdatePriority(T obj)
	{
		int index = objectToIndex[obj];
		if (!activeObjects.Contains(index))
		{
			throw new InvalidOperationException("Object is not active");
		}

		activeObjects.UpdateValue(index, obj, getPriority(obj));
	} 

	public void IncreaseCapacity(int increment) =&gt; throw new NotSupportedException();
	public int DecreaseCapacity(int decrement) =&gt; throw new NotSupportedException();
}</code></pre>



<h3 class="wp-block-heading">Fake pools</h3>



<p>Fake pools implement the pool interface, but instead of pooling objects, they create and destroy them as you would if you did not use pooling. You can easily replace a real pool with a fake one to make comparisons and ensure your pools are giving you the benefits that you are using them for.&nbsp;</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public class FakePool&lt;T&gt; : IPool&lt;T&gt;
{
	private readonly Func&lt;T&gt; create;
	private readonly Action&lt;T&gt; destroy;
	
	public int Capacity { get; private set; }
	public bool HasAvailableObject =&gt; InactiveObjectCount &gt; 0;
	public int InactiveObjectCount { get; private set; }
	
	public FakePool(
		int capacity,
		Func&lt;T&gt; create,
		Action&lt;T&gt; destroy
	)
	{
		Capacity = capacity;
		this.create = create;
		this.destroy = destroy;
	}

	public T Get()
	{
		if (!HasAvailableObject)
		{
			throw new InvalidOperationException("No available objects");
		}
		
		InactiveObjectCount--;
		return create();
	}

	public void Release(T obj)
	{
		destroy(obj);
		InactiveObjectCount++;
	}

	public void IncreaseCapacity(int increment) =&gt; Capacity += increment;

	public int DecreaseCapacity(int decrement) =&gt; Capacity -= decrement;
}</code></pre>



<h2 class="wp-block-heading"><strong>More design techniques</strong></h2>



<h3 class="wp-block-heading">Managing pooled objects through an interface</h3>



<p>So far, we looked at designs of pools that can manage objects of any (safely hashable) type. In this section we look at how the design of pools change if we require that pooled objects implement an interface.&nbsp;</p>



<p>Using this approach simplifies the pool class:</p>



<ul class="wp-block-list">
<li>We do not need to pass the activate, deactivate (and even destroy) as actions — we can make them part of the interface and call them directly.&nbsp;</li>



<li>If we want to use prioritized release, we can make the priority and object indices part of the interface, and so do not have to pass in an evaluation function, or maintain a dictionary of object indices.&nbsp;</li>
</ul>



<p>There are some disadvantages to this design:</p>



<ul class="wp-block-list">
<li>We can only support types outside our control by wrapping them.&nbsp;</li>



<li>It couples objects to the pool.&nbsp;</li>
</ul>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public interface IReusableObject
{
	bool IsActive { get; }
	void Activate();
	void Deactivate();
	int Id { get; }
}

public interface IReusableObject&lt;out T&gt; : IReusableObject
{
	public T Value { get; }
}

// Non-generic version
public class ReusableObjectPool : IPool&lt;IReusableObject&gt;
{
	private readonly StackPool&lt;IReusableObject&gt; pool;

	public int Capacity =&gt; pool.Capacity;	
	public int InactiveObjectCount =&gt; pool.InactiveObjectCount;
	public bool HasAvailableObject =&gt; pool.HasAvailableObject;
	
	public ReusableObjectPool(int initialCapacity, 
		Func&lt;IReusableObject&gt; createActive,
		Action&lt;IReusableObject&gt; destroy)
	{
		pool = new StackPool&lt;IReusableObject&gt;(initialCapacity, createActive, Activate, Deactivate, destroy);
	
		return;
	
		void Activate(IReusableObject obj) =&gt; obj.Activate();
		void Deactivate(IReusableObject obj) =&gt; obj.Deactivate();
	}

	public IReusableObject Get() =&gt; pool.Get();

	public void Release(IReusableObject obj) =&gt; pool.Release(obj);

	public void IncreaseCapacity(int increment) =&gt; pool.IncreaseCapacity(increment);

	public int DecreaseCapacity(int decrement) 
		=&gt; pool.DecreaseCapacity(decrement);
}

public class ReusableObjectPool&lt;T&gt; : IPool&lt;T&gt;
	where T : IReusableObject
{
	private readonly StackPool&lt;T&gt; pool;

	public int Capacity =&gt; pool.Capacity;	
	public bool HasAvailableObject =&gt; pool.HasAvailableObject;
	public int InactiveObjectCount =&gt; pool.InactiveObjectCount;

	public ReusableObjectPool(int initialCapacity, 
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; destroy)
	{
		pool = new StackPool&lt;T&gt;(initialCapacity, createActive, Activate, Deactivate, destroy);
	
		return;
	
		void Activate(T obj) =&gt; obj.Activate();
		void Deactivate(T obj) =&gt; obj.Deactivate();
	}

	public T Get() =&gt; pool.Get();
	public void Release(T obj) =&gt; pool.Release(obj);
	public void IncreaseCapacity(int increment) =&gt; pool.IncreaseCapacity(increment);
	public int DecreaseCapacity(int decrement) =&gt; pool.DecreaseCapacity(decrement);
}</code></pre>



<p>And here is the priority pool implemented in this way:</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public interface IPrioritizedObject&lt;out TPriority&gt;
{
	TPriority Priority { get; }
}

public class PriorityReusableObjectPool&lt;T, TPriority&gt; 
	where T : IReusableObject, IPrioritizedObject&lt;TPriority&gt;
{
	private readonly StackPool&lt;T&gt; pool;
	private readonly IndexPriorityQueue&lt;T, TPriority&gt; activeObjects;

	public PriorityReusableObjectPool(
		int capacity,
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; destroy, 
		IEqualityComparer&lt;T&gt; objectComparer,
		IComparer&lt;TPriority&gt; priorityComparer)
	{
		int counter = 0;

		var objectToIndex = new Dictionary&lt;T, int&gt;(objectComparer);
		activeObjects = new IndexPriorityQueue&lt;T, TPriority&gt;(capacity, priorityComparer);
		pool = new StackPool&lt;T&gt;(capacity, CreateActive, Activate, Deactivate, destroy);
	
		return;

		T CreateActive()
		{
			var obj = createActive();
			objectToIndex[obj] = counter++;
			return obj;
		}

		void Activate(T obj)
		{
			obj.Activate();
			activeObjects.Enqueue(objectToIndex[obj], obj, obj.Priority);
		}

		void Deactivate(T obj)
		{
			obj.Deactivate();
			activeObjects.Remove(objectToIndex[obj]);
		}
	}

	public T Get()
	{
		if (pool.HasAvailableObject)
		{
			return pool.Get();
		}

		(int index, var obj) = activeObjects.Dequeue();
		obj.Deactivate();
		obj.Activate();
		activeObjects.Enqueue(index, obj, obj.Priority);
		return obj;
	}

	public void Release(T obj) =&gt; pool.Release(obj);
}</code></pre>



<h3 class="wp-block-heading">Self-releasing objects</h3>



<p>Sometimes it is convenient to let objects release themselves when they are ready. For example, when we generate a particle whose behavior is completely controlled from within itself, it would be good if it was automatically released when it is at the end of its lifetime. This way we can “get and forget” about the particle.&nbsp;</p>



<p>To do this, you can either reference the pool that owns them, so objects can call the release method with themselves as parameter, or you can create an event that the pool can subscribe to that will be raised when the object wants to be released.&nbsp;</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public interface ISelfReleasingObject&lt;out T&gt;
{
	T Value { get; }
	void Release();
}

public class SelfReleasingObjectPool&lt;T&gt; : IPool&lt;ISelfReleasingObject&lt;T&gt;&gt;
{
	private class SelfReleasingObject : ISelfReleasingObject&lt;T&gt;
	{
		private readonly IPool&lt;SelfReleasingObject&gt; owner;
		public T Value { get; }
		
		public SelfReleasingObject(T value, IPool&lt;SelfReleasingObject&gt; owner)
		{
			Value = value;
			this.owner = owner;
		}
		
		public void Release() =&gt; owner.Release(this);
	}

	private readonly StackPool&lt;SelfReleasingObject&gt; pool;
	
	public int Capacity =&gt; pool.Capacity;	
	public int InactiveObjectCount =&gt; pool.InactiveObjectCount;	
	public bool HasAvailableObject =&gt; pool.HasAvailableObject;
	
	public SelfReleasingObjectPool(
		int initialCapacity,
		Func&lt;T&gt; createActive,
		Action&lt;T&gt; activate,
		Action&lt;T&gt; deactivate,
		Action&lt;T&gt; destroy)
	{
		pool	= new StackPool&lt;SelfReleasingObject&gt;(initialCapacity, CreateActive, Activate, Deactivate, Destroy);
		return;

		SelfReleasingObject CreateActive()
		{
			var obj = new SelfReleasingObject(createActive(), pool);
			return obj;
		}
		
		void Destroy(SelfReleasingObject obj)
		{
			destroy(obj.Value);
		}
		
		void Activate(SelfReleasingObject obj) =&gt; activate(obj.Value);
		void Deactivate(SelfReleasingObject obj) =&gt; deactivate(obj.Value);
	}
	
	public ISelfReleasingObject&lt;T&gt; Get()
	{
		var obj = pool.Get();
		return obj;
	}
	
	public void Release(ISelfReleasingObject&lt;T&gt; obj) =&gt; pool.Release((SelfReleasingObject)obj);
	public void IncreaseCapacity(int increment) =&gt; pool.IncreaseCapacity(increment);
	public int DecreaseCapacity(int decrement) =&gt; pool.DecreaseCapacity(decrement);
}</code></pre>



<h3 class="wp-block-heading">Wrapping unsuitable types</h3>



<p>If we want to pool objects of a type that does not satisfy some requirements — typically a type outside our control — we may wrap it to give it what is missing. For example, we can use this to implement a specified interface, or make the objects safe to hash.&nbsp;</p>



<p>The general technique is as follows:</p>



<ul class="wp-block-list">
<li>If there is not a public interface the object needs to conform to, provide one. This should give the user everything they need to work with the object.</li>



<li>Define a static class that provides the creation method for the pool.&nbsp;</li>



<li>Define an private inner type that implements the pool interface or the one defined above. This type exposes additional functionality that can be used by pool delegates.&nbsp;</li>



<li>Define the delegates in terms of the public type. The action delegates may cast to the private type to do their work.&nbsp;</li>



<li>Define the static method to create a pool in terms of the public type.&nbsp;</li>
</ul>



<p>This example shows how to wrap objects to make them hashable. </p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public interface IHashable&lt;out T&gt;
{
	T Value { get; }
}

public static class Pools
{
	private class IdHashable&lt;T&gt; : IHashable&lt;T&gt;
	{
		private readonly Id&lt;IHashable&lt;T&gt;&gt; id = new();
		public T Value { get; }
		public override int GetHashCode() =&gt; id.GetHashCode();
		public IdHashable(T value) =&gt; Value = value;
	}

	public static IPool&lt;IHashable&lt;T&gt;&gt; GetPoolWithActiveTrackingForNonHashables&lt;T&gt;(
		int initialCapacity, 
		Func&lt;T&gt; createActive, 
		Action&lt;T&gt; activate,
		Action&lt;T&gt; deactivate, 
		Action&lt;T&gt; destroy)
		where T : class
	{
		return GetPoolWithActiveTracking(initialCapacity, CreateActive, Activate, Deactivate, Destroy, null);
		
		IHashable&lt;T&gt; CreateActive() =&gt; new IdHashable&lt;T&gt;(createActive());
		void Destroy(IHashable&lt;T&gt; obj) =&gt; destroy(obj.Value);
		void Activate(IHashable&lt;T&gt; obj) =&gt; activate(obj.Value);
		void Deactivate(IHashable&lt;T&gt; obj) =&gt; deactivate(obj.Value);
	}
}</code></pre>



<h3 class="wp-block-heading">Hiding creation and destruction</h3>



<p>There are situations where you may want to hide the creation and destruction of objects, so that the only way users can get instances is through the pool.&nbsp;</p>



<p>The general technique is as follows:</p>



<ul class="wp-block-list">
<li>Define a public type the user will interact with. This type will not define a constructor.</li>



<li>Define your pool type.&nbsp;</li>



<li>Define a private type of inside the pool type that implements or extends from the public type.&nbsp;</li>



<li>Define private methods for creating and destroying objects of the private type.&nbsp;</li>



<li>In your pool type, define a pool field that you can delegate all the work to. This should be in terms of the private type. This in contrast with how wrapping works, where the pool was defined in terms of the public type. This is because we can do the type conversion in the Get and Release methods, and keeping the pool in terms of the private type is more convenient.</li>



<li>Define Get and Release methods in terms of the public type, doing type conversions as required.</li>



<li>Define any other pool methods you want to support.&nbsp;</li>
</ul>



<p>This type of pool is usually not useful when you don’t control the creation of the objects. For example, since any <code>MonoBehaviour</code> can be created through the Unity&#8217;s <code>Instantiate</code> method, this pool is not very useful to manage any <code>MonoBehaviour</code>.&nbsp;</p>



<pre class="wp-block-code has-small-font-size"><code lang="csharp" class="language-csharp">public interface IEnemy
{
	public int Health { get; set; }
}

public class EnemyPool
{
	private readonly ReusableObjectPool&lt;Enemy&gt; pool;

	private class Enemy : IEnemy, IReusableObject
	{
		public int Health { get; set; }
		public bool IsActive { get; private set;}

		private readonly Id&lt;Enemy&gt; id = new();
		public int Id =&gt; id.value;
	
		public void Activate()
		{
			Debug.Assert(!IsActive);
			// Make active in scene
			IsActive = true;
		}

		public void Deactivate()
		{
			Debug.Assert(IsActive);
			// Make inactive in scene
			IsActive = false;
		}

		public override int GetHashCode() =&gt; id.value;
	}

	public EnemyPool(int initialCapacity) =&gt; pool = new ReusableObjectPool&lt;Enemy&gt;(initialCapacity, CreateEnemy, DestroyEnemy);

	public IEnemy Get() =&gt; pool.Get();
	public void Release(IEnemy enemy) =&gt; pool.Release((Enemy)enemy);
	private static Enemy CreateEnemy() =&gt; new();
	private static void DestroyEnemy(Enemy enemy) { }
}</code></pre>



<h1 class="wp-block-heading"><strong>Best Practices</strong></h1>



<ul class="wp-block-list">
<li>Measure the effect of your pool on the metrics you are trying to improve. As with all performance measuring, take the measurements in the right contexts (on the same platforms as you are developing for, in circumstances that occur in natural gameplay, with the same number of objects that are typically in play, and so on). You can make a comparison easily by using the fake pool described earlier.&nbsp;</li>



<li>Redo benchmark measurements each time you make changes that could affect the execution of any of the pool delegates.&nbsp;</li>



<li>For pools that control visual effects, consider centralizing pool capacities and policies so you can easily tie these with performance profiles.&nbsp;</li>



<li>Classes that use generic hash tables or dictionaries should take an optional comparer that is fed to the hashtable or dictionary. This ensures your class is truly usable for any object. (In the example implementation the comparison is compulsory, this is to avoid accidentally forgetting to pass a comparator along in this system of pools).&nbsp;</li>



<li>Be careful with pooling structs. Most of the discussion in this post assumes that the objects we want to hash are reference types. Structs are often smaller objects, and their creation does not directly affect garbage collection, so in many cases it may not make sense to pool them at all. Besides, when passing them between methods, their values are copied, so any gains trying to avoid creation will be thwarted. There may well be occasions where pooling structs may be useful. In that case though, the pool designs discussed here will probably not be appropriate.&nbsp;</li>



<li>Be careful when decreasing the pool capacity:
<ul class="wp-block-list">
<li>Make sure to destroy inactive objects first.</li>



<li>Decide how to handle active objects. In the implementation here we do not decrease below the number of inactive objects. In active object tracking pools, you can also destroy active objects if you choose. With non-tracking pools, how to interpret what it means to reduce beyond the inactive objects is difficult. What if users try to return objects beyond the current capacity? Do you destroy them then?</li>



<li>If your pool can destroy active objects, let the user specify whether to deactivate active objects first before destroying them.</li>
</ul>
</li>



<li>In any operation where you ask for <em>n</em> things to be done, if it is possible for less than <em>n</em> things to be done, return the actual number of things done. This will enable the user to decide what to do if not everything was done.&nbsp;</li>



<li>For ordinary pool users, the number of active and inactive objects will not be that useful. However, these values are very useful when implementing a new type of pool based on the existing pool, so therefore, include them in your interface.</li>
</ul>



<p class="has-background" style="background-color:#f9ee34">You can get the code used in the post on BitBucket: <a href="https://github.com/Gamelogic-Code/Pools/">https://github.com/Gamelogic-Code/Pools/</a></p>



<p class="has-background" style="background-color:#f9ee34">If you are a Unity user, you may also want to check out our free <a href="https://assetstore.unity.com/packages/tools/utilities/gamelogic-extensions-19323" data-type="link" data-id="https://assetstore.unity.com/packages/tools/utilities/gamelogic-extensions-19323">Gamelogic Extensions</a> library which contains robust implementations for Unity, and some examples of using them.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tool Documentation Overhaul</title>
		<link>https://gamelogic.co.za/2017/06/23/tool-documentation-overhaul/</link>
					<comments>https://gamelogic.co.za/2017/06/23/tool-documentation-overhaul/#comments</comments>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Fri, 23 Jun 2017 15:08:31 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[tools]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5132</guid>

					<description><![CDATA[We started this week to do a major overhaul to the documentation of our tools. The first step was to [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>We started this week to do a major overhaul to the documentation of our tools.</p>
<p>The first step was to use a different HTML generator.</p>
<p>We used GhostDoc before, but we have had some big problems with the generated HTML. Many links were broken because GhostDoc generate links with the wrong case (we reported this to them but so far, no luck with a fix). Although we could fix this by hacking the HTML ourselves, it also meant the documentation was not searchable, which makes it much less useful.</p>
<p>We use Sandcastle now, and so far, it seems to be working great. Sandcastle also allows us to add some conceptual documentation, which means we can bring together the documentation spread all over the site to one place. You can already see the extra pages we added for Grids 2: <a href="https://gamelogic.co.za/documentation/grids2/">https://gamelogic.co.za/documentation/grids2/</a>.</p>
<p>The second step is to “translate” the many documentation articles we made for Grids 1 to Grids 2. One example of this is the guide we wrote that shows how to do everything in Amit Patel’s great <a href="http://www.redblobgames.com/grids/hexagons/">Hexagonal Grids</a> article with the Grids library. You can see the work-in-progress result here: <a href="https://gamelogic.co.za/documentation/grids2/html/f9d4f8f2-6eaa-4e52-bb24-0bca2a06a541.htm">https://gamelogic.co.za/documentation/grids2/html/f9d4f8f2-6eaa-4e52-bb24-0bca2a06a541.htm</a>.</p>
<p>The third step (and this is really happening concurrently with step 2) is to add the many missing API documentation entries, starting with the most important classes (such as <a href="https://gamelogic.co.za/documentation/grids2/html/9E6A32B2.htm">GridPoint2</a> and <a href="https://gamelogic.co.za/documentation/grids2/html/8EF4D3A5.htm">IGrid</a>) and working our way down to the more obscure machinery such as <a href="https://gamelogic.co.za/documentation/grids2/html/7C6B867B.htm">IPointPartition</a>.</p>
<p>And after this, we have to do the same for the other tools!</p>
<p>It will be a long process, and we want to upload the newest version of the documentation every day or two, so it means you may see the odd ghost of a GhostDoc tag that is misinterpreted, or pages that are incomplete. Please be patient <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> And if you see anything amiss, please let us know, and if you have questions, ask us on the <a href="https://gamelogic.quandora.com/">Knowledge Base</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://gamelogic.co.za/2017/06/23/tool-documentation-overhaul/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>What is new in Grids Pro 2.3.5</title>
		<link>https://gamelogic.co.za/2017/06/01/what-is-new-in-grids-pro-2-3-5/</link>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Thu, 01 Jun 2017 19:15:43 +0000</pubDate>
				<category><![CDATA[Grids 2]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5118</guid>

					<description><![CDATA[A new update for Grids Pro is in the asset store. In this version, We added a new Simple Grid [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>A new update for Grids Pro is in the asset store.</p>
<p>In this version,</p>
<ul>
<li>We added a new Simple Grid example where you can find some of the new ways to create grids by code that are way simpler than before. You can still use the old way if you need more control though. You can find this example in Examples/SimpleGrids/.</li>
<li>We added a new Space Filling Curves example, check it out is pretty cool. You can find this example in Examples/SpaceFillingCurves/.</li>
<li>We added a new Basic Fat Hex example to illustrate how this shape can be achieved by code. You can find this example in Examples/BasicCode/FatHex/.</li>
<li>We added the option to have random offsets, specific offsets or no offset at all in the HeightSpaceMap Node for Space Maps.</li>
<li>We added a few swapping axes methods we were missing and that were requested by users.</li>
<li>The 3D Shapes example has been fixed.</li>
<li>The Triangular Grid example has been fixed.</li>
<li>The Animation example has been fixed.</li>
<li>The Prims Algorithm example has been fixed.</li>
<li>The Complex Shape example has been fixed.</li>
<li>The Rect, RectTile and Hex mesh examples have been fixed.</li>
<li>We fixed an incorrect call to a Destroy method in editor time for the Puzzle example.</li>
<li>We fixed the warning compile messages, if you spot new ones let us know.</li>
<li>We fixed the format of scripts, variables and inspectors fields on all examples.</li>
<li>We fixed some UnityEditor cross dependencies in the graph.</li>
<li>For Grids 1 some examples had a wrong camera configuration, this has been fixed. Also some Unity Editor dependencies have been resolved.</li>
</ul>
<p><img fetchpriority="high" decoding="async" class="aligncenter wp-image-5121 size-full" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/06/screen_636319255046689651.png" alt="FillingCurve" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/06/screen_636319255046689651.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/06/screen_636319255046689651-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/06/screen_636319255046689651-600x300.png 600w" sizes="(max-width: 680px) 100vw, 680px" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What is new in Grids Pro 2.3.2</title>
		<link>https://gamelogic.co.za/2017/05/30/what-is-new-in-grids-pro/</link>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Tue, 30 May 2017 19:34:47 +0000</pubDate>
				<category><![CDATA[Grids 2]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5103</guid>

					<description><![CDATA[Our dear Grids Pro has been updated too. We are working hard to make the library easier and more useful. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Our dear Grids Pro has been updated too. We are working hard to make the library easier and more useful.</p>
<p>In this version,</p>
<ul>
<li>We updated the version of <a href="https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/">Extensions </a>to latest.</li>
<li>We added a new Basic Editor folder under Examples/GridSetup/ with more examples on how to create different grids.</li>
<li>Inspector messages is now shown to let you know if you did not specify the grid shape or map, and how to create them. This is in all builder scripts and examples.</li>
<li>The location of shared resources used by examples has been changed so is easier to find, also more stuff is in there now.</li>
<li>There is code to create grids by code more easily, along with some presets in the context menu and graphs. Some of them are still experimental and more will be on the way, so all feedback is appreciated, especially if you have ideas on what would be most useful.</li>
<li>We added a hex spiral iterator to complement the rect spiral iterator.</li>
<li>More explicit shapes have been added to make it easy to create some of the commonest shapes, such as a flat hex rect shape.</li>
<li>We made various improvements in the code and in the <a href="https://gamelogic.co.za/documentation/grids2/">webpage documentation</a>. There is still a lot to do, but that is in the works.</li>
<li>We fixed a lot of other minor bugs as well, including font sizes (in the examples), alignment, deprecated comments/documentation, and so on.</li>
</ul>
<p><img decoding="async" class="aligncenter wp-image-5107 size-full" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636317565742586262.png" alt="gridsUpdate" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636317565742586262.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636317565742586262-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636317565742586262-600x300.png 600w" sizes="(max-width: 680px) 100vw, 680px" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What is new in Abstract Strategy 2.1.1</title>
		<link>https://gamelogic.co.za/2017/05/29/what-is-new-in-abstract-strategy/</link>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Mon, 29 May 2017 17:29:55 +0000</pubDate>
				<category><![CDATA[AbstractStrategy]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5098</guid>

					<description><![CDATA[Abstract Strategy has been updated. In this version we, Upgraded Abstract Strategy to the newest version of Extensions and Grids [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Abstract Strategy has been updated.</p>
<p>In this version we,</p>
<ul>
<li>Upgraded Abstract Strategy to the newest version of <a href="https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/">Extensions </a>and <a href="https://gamelogic.co.za/2016/08/18/support-for-bitmask-shapes-and-polyominoes-in-grids-2-3/">Grids 2 (Pro)</a>. This version use a DLL, but you can get the source code if you<a href="https://www.assetstore.unity3d.com/en/#!/content/66291"> own Grids 2</a> separately.</li>
<li>The documentation has been improved, both in code and in our <a href="https://gamelogic.co.za/documentation/abstract-strategy/">webpage</a>.</li>
<li>Some examples had missing references that have been fixed.</li>
<li>Various other minor fixes and improvements have been done to the code in general.</li>
</ul>
<p><img decoding="async" class="aligncenter size-full wp-image-5100" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636316552379115818.png" alt="screen_636316552379115818" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636316552379115818.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636316552379115818-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/screen_636316552379115818-600x300.png 600w" sizes="(max-width: 680px) 100vw, 680px" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What is new in Words 2.0.2</title>
		<link>https://gamelogic.co.za/2017/05/25/what-is-new-in-words/</link>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Thu, 25 May 2017 15:36:10 +0000</pubDate>
				<category><![CDATA[Words]]></category>
		<category><![CDATA[words]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5084</guid>

					<description><![CDATA[Our new update goes to Words. In this version we, Upgraded Words to the newest version of Extensions and Grids [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Our new update goes to Words.</p>
<p>In this version we,</p>
<ul>
<li data-listid="5" data-aria-posinset="1" data-aria-level="1">Upgraded Words to the newest version of <a href="https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/">Extensions </a>and <a href="https://gamelogic.co.za/2016/08/18/support-for-bitmask-shapes-and-polyominoes-in-grids-2-3/">Grids 2 (Pro)</a>. This version use a DLL, but you can get the source code if you <a href="https://www.assetstore.unity3d.com/en/#!/content/66291">own Grids 2</a> separately.</li>
<li data-listid="5" data-aria-posinset="1" data-aria-level="1">The documentation has been fixed, both in code and in our <a href="https://gamelogic.co.za/documentation/words/">webpage</a>.</li>
<li data-listid="5" data-aria-posinset="3" data-aria-level="1">Reorganized the Example folder to make it easier to navigate.</li>
<li data-listid="5" data-aria-posinset="4" data-aria-level="1">Fixed the Word Finder and the Word Maker example.</li>
<li data-listid="5" data-aria-posinset="4" data-aria-level="1">Other minor fixes and improvements have been done on the code..</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-5085 size-full" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/Words.png" alt="Words" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/Words.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/Words-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/Words-600x300.png 600w" sizes="auto, (max-width: 680px) 100vw, 680px" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What is new in Colors 1.1.6</title>
		<link>https://gamelogic.co.za/2017/05/24/what-is-new-in-colors/</link>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Wed, 24 May 2017 13:32:52 +0000</pubDate>
				<category><![CDATA[Colors]]></category>
		<category><![CDATA[colors]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5078</guid>

					<description><![CDATA[Not only Extensions has been updated, but also Colors. In this version we, The Extensions version used in Colors has [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Not only <a href="https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/">Extensions has been updated,</a> but also Colors.</p>
<p>In this version we,</p>
<ul>
<li>The Extensions version used in Colors has been updated to the newest version.</li>
<li>We added <a href="https://gamelogic.co.za/documentation/colors/?topic=html/T-Gamelogic.Colors.ColorGenerator.htm">generators for procedural color generation</a>. This is now the preferred method for generating colors in code. The idea is to add node editors for generators at some stage, which will replace the current node editors for generating colors sets. This is a long-term plan, so it won&#8217;t be any time soon.</li>
<li>The documentation has been fixed, both in code and in our <a href="https://gamelogic.co.za/documentation/colors/">webpage</a>.</li>
<li>Minor fixes and improvement have been done on the code.</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-5089 size-full" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/ColorGeneration2.png" alt="ColorGeneration2" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/ColorGeneration2.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/ColorGeneration2-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/ColorGeneration2-600x300.png 600w" sizes="auto, (max-width: 680px) 100vw, 680px" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What&#8217;s new in Extensions 2.2.1</title>
		<link>https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/</link>
					<comments>https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/#comments</comments>
		
		<dc:creator><![CDATA[Gamelogic]]></dc:creator>
		<pubDate>Tue, 23 May 2017 18:16:40 +0000</pubDate>
				<category><![CDATA[Extensions]]></category>
		<category><![CDATA[extensions]]></category>
		<guid isPermaLink="false">http://gamelogic.co.za/?p=5073</guid>

					<description><![CDATA[We recently updated all our libraries. We will publish posts detailing the updates over the next few days. This is [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>We recently updated all our libraries. We will publish posts detailing the updates over the next few days. This is the first one.</p>
<p>In this version we,</p>
<ul>
<li>Added new attributes and drawers (<a href="http://www.gamelogic.co.za/documentation/extensions/?topic=html/T-Gamelogic.Extensions.ReadOnlyAttribute.htm">Readonly</a>, ReordableList, <a href="http://www.gamelogic.co.za/documentation/extensions/?topic=html/T-Gamelogic.Extensions.WarningIfNullAttribute.htm">WarnIfNull</a>). We also added a detailed example, showing all the drawers – old and new – in action.</li>
<li>Added state trackers. A state tracker is a class in the same spirit is <a href="http://www.gamelogic.co.za/documentation/extensions/?topic=html/T-Gamelogic.Extensions.StateMachine-1.htm">StateMachine</a>, and was originally designed to implement showing a loading graphic for asynchronous actions (such as making WWW calls) that happen in no particular order, and can overlap. See StateTracker, TimeStateTracker).</li>
<li>Improved the design of response curves, and added new response curves (<a href="http://www.gamelogic.co.za/documentation/extensions/?topic=html/T-Gamelogic.Extensions.Algorithms.StepResponse.htm">StepResponse</a>, <a href="http://www.gamelogic.co.za/documentation/extensions/?topic=html/M-Gamelogic.Extensions.Algorithms.Generator.Dither.htm">DitherResponse</a>). We also added a common interface for this class, and a new Evaluate function to mimic Unity&#8217;s animation curves and gradients.</li>
<li>Added a custom editor class for GLMonoBehaviour, and added support for automatic inspector buttons for annotated methods. This is also demonstrated in the new example mentioned above.</li>
<li>Removed the Gamelogic top-level menu and moved items to appropriate menus.</li>
<li>Renamed the Plugin folder to Plugins to improve compilation times. (If you upgrade, make sure to make a backup first, and rename your Plugin folder to Plugins before to prevent duplicate imports).</li>
<li>Made several small additions, bugfixes and refactorings.</li>
<li>Fixed the documentation.</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5093" src="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/PropertyDrawers.png" alt="PropertyDrawers" width="680" height="340" srcset="https://gamelogic.co.za/blog/wp-content/uploads/2017/05/PropertyDrawers.png 680w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/PropertyDrawers-300x150.png 300w, https://gamelogic.co.za/blog/wp-content/uploads/2017/05/PropertyDrawers-600x300.png 600w" sizes="auto, (max-width: 680px) 100vw, 680px" /></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://gamelogic.co.za/2017/05/23/whats-new-in-extensions/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
