<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>I Brew Code</title>
    <description>Programming and probably more.</description>
    <link>https://ibrewcode.com/</link>
    <atom:link href="https://ibrewcode.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 21 Nov 2018 21:25:52 +0000</pubDate>
    <lastBuildDate>Wed, 21 Nov 2018 21:25:52 +0000</lastBuildDate>
    <generator>Jekyll v3.7.4</generator>
    
      <item>
        <title>Components and Messages in Unity</title>
        <description>
&lt;p&gt;Up to now, I have had a tendency toward monolithic classes when developing in Unity. My experience has always been with the typical object-oriented approach (with the exception of when I was developing using &lt;a href=&quot;http://www.randomterrain.com/atari-2600-memories-batari-basic-commands.html&quot;&gt;batari Basic&lt;/a&gt;), but I’ve been trying to train myself toward small, reusable components with focused purposes. I’ve had some good success lately, breaking larger scripts into smaller ones and using interfaces as a means of communicating between components where possible.&lt;/p&gt;
&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;public class ReportAttack : MonoBehaviour, IDamageable {
    public Team team;
    void Start () {
		team = GetComponent&amp;lt;Team&amp;gt;();
	}

    void IDamageable.TakeDamage(MonoBehaviour from, DamageType type, float amount)
    {
		var attackerTeam = from.GetComponent&amp;lt;Team&amp;gt;();
		if (team &amp;amp;&amp;amp; attackerTeam &amp;amp;&amp;amp; team.team != attackerTeam.team)
			Debug.Log(gameObject.name + &amp;quot; says: I've Been Attacked by &amp;quot; + from.gameObject + &amp;quot; on team &amp;quot; + (attackerTeam ? attackerTeam.team.ToString() : &amp;quot;no team&amp;quot;) + &amp;quot; with &amp;quot; + System.Enum.GetName(typeof(DamageType), (DamageType)((int)type &amp;lt;&amp;lt; 1)) + &amp;quot; (&amp;quot; + (int)type + &amp;quot;)&amp;quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While I’ve been fairly satisfied with the use of interfaces for calls to multiple or unknown components, I recall fondly the rapid development and flexible approach provided by utilizing messages in my 2017 Global Game Jam submission, &lt;a href=&quot;https://globalgamejam.org/2017/games/metalmancer&quot;&gt;Metalmancer&lt;/a&gt;.&lt;/p&gt;
&lt;pre data-src=&quot;https://page-reflect.herokuapp.com/?target=https://raw.githubusercontent.com/nbrosz/gamejam-17/master/Audiomancer/Assets/Scripts/Attack.cs&quot; class=&quot;line-numbers language-csharp&quot;&gt;&lt;/pre&gt;
&lt;p&gt;However, since Unity’s message passing uses reflection (or at least &lt;strong&gt;probably&lt;/strong&gt; does, given that it takes the string name of the event to call), it does not perform particularly well. With that in mind, I hoped to make my own, alternative messaging system which is used much like the existing messaging system, but uses delegates and event handlers under the hood. &lt;a href=&quot;https://gist.github.com/nbrosz/a0544d3196765d739f5729bffe6e5b18&quot;&gt;This was the result&lt;/a&gt;.&lt;/p&gt;
&lt;pre data-src=&quot;https://page-reflect.herokuapp.com/?target=https://gist.githubusercontent.com/nbrosz/a0544d3196765d739f5729bffe6e5b18/raw/8b4b5d762e3197b46a6dc6c4a8108719a660846d/MessagingBehavior.cs&quot; class=&quot;line-numbers language-csharp&quot;&gt;&lt;/pre&gt;
&lt;p&gt;While I felt that I succeeded in my goal of providing a useful interface that hid the reflection-based old messaging system, I was crestfallen once I began running tests.
&lt;img src=&quot;https://ibrewcode.com/media/posts/components-and-messages-in-unity/figA.png&quot; alt=&quot;Performance Testing&quot; /&gt;
On average, I see a performance increase of about 33% over Unity’s built in SendMessage, with the complication that all components using the new system must inherit from the new MessagingBehavior abstract class, rather than directly from MonoBehavior. Still, given that a direct call (as would be the case using an interface) is still about ten times faster, I wasn’t particularly encouraged by these results.&lt;/p&gt;

&lt;p&gt;On the other hand, as &lt;strong&gt;tomvds&lt;/strong&gt; &lt;a href=&quot;https://forum.unity.com/threads/is-sendmessage-really-that-bad.38094/#post-245212&quot;&gt;said in the Unity forums&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Optimization is not about avoiding expensive code. It’s about avoiding expensive code where it matters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://ibrewcode.com/media/posts/components-and-messages-in-unity/figB.png&quot; alt=&quot;Performance Testing&quot; /&gt;
Still, stubborn as I am, it’ll be hard to convince myself to use even my own message passing architecture in lieu of more efficient interfaces. Or maybe I should just use an adaptation of &lt;strong&gt;wmiller&lt;/strong&gt;’s &lt;a href=&quot;https://gist.github.com/wmiller/3903205#file-events-cs&quot;&gt;Events system&lt;/a&gt;.
Or I should just stop worrying about it.&lt;/p&gt;
</description>
        <pubDate>Sun, 10 Dec 2017 00:00:00 +0000</pubDate>
        <link>https://ibrewcode.com/components-and-messages-in-unity/</link>
        <guid isPermaLink="true">https://ibrewcode.com/components-and-messages-in-unity/</guid>
        
        <category>Unity</category>
        
        
        <category>Game Dev</category>
        
      </item>
    
      <item>
        <title>Clearing Up Input Transparency</title>
        <description>
&lt;p&gt;The &lt;a href=&quot;https://developer.xamarin.com/api/property/Xamarin.Forms.VisualElement.InputTransparent/&quot;&gt;Xamarin Forms documentation&lt;/a&gt; for the VisualElement.InputTransparent property (as of this writing) states:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Gets or sets a value indicating whether this element should be involved in the user interaction cycle…. [The value is] false if the element should receive input; true if element should not receive input and should, instead, pass inputs to the element below. Default is false.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://ibrewcode.com/media/posts/clearing-up-input-transparency/figA.png&quot; alt=&quot;Element Layers&quot; class=&quot;left&quot; /&gt;
Imagine if &lt;strong&gt;A&lt;/strong&gt;, &lt;strong&gt;B&lt;/strong&gt;, and &lt;strong&gt;C&lt;/strong&gt; all have &lt;a href=&quot;https://developer.xamarin.com/api/property/Xamarin.Forms.View.GestureRecognizers/&quot;&gt;gesture recognizers&lt;/a&gt; on their elements, but &lt;strong&gt;B&lt;/strong&gt; has InputTransparent set to &lt;strong&gt;true&lt;/strong&gt;, while &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt; have an input transparency of &lt;strong&gt;false&lt;/strong&gt;. The documentation implies that &lt;strong&gt;C&lt;/strong&gt; would consume a tap gesture, preventing it from passing down, while &lt;strong&gt;B&lt;/strong&gt; would not, instead allowing &lt;strong&gt;A&lt;/strong&gt; to consume any gesture that wasn’t consumed by &lt;strong&gt;C&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, this does not appear to be the case. Instead, if &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt; had InputTransparent set to &lt;strong&gt;true&lt;/strong&gt; and &lt;strong&gt;B&lt;/strong&gt; had InputTransparent set to &lt;strong&gt;false&lt;/strong&gt;, the gestures wouldn’t be consumed at all.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ibrewcode.com/media/posts/clearing-up-input-transparency/figB.png&quot; alt=&quot;Element Hierarchy&quot; class=&quot;right&quot; /&gt;
Instead, it seems to work more like the figure above. Imagine that the hierarchy represents elements layered on top of one another, with &lt;strong&gt;A&lt;/strong&gt; being the bottom-most element, while &lt;strong&gt;C&lt;/strong&gt;, &lt;strong&gt;G&lt;/strong&gt;, and &lt;strong&gt;H&lt;/strong&gt; are the top-most layered elements. In this example, &lt;strong&gt;C&lt;/strong&gt; covers &lt;strong&gt;B&lt;/strong&gt;, which covers &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;G&lt;/strong&gt; and &lt;strong&gt;H&lt;/strong&gt; covers &lt;strong&gt;F&lt;/strong&gt;, etc., but &lt;strong&gt;D&lt;/strong&gt; does not cover &lt;strong&gt;B&lt;/strong&gt;, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://ibrewcode.com/media/posts/clearing-up-input-transparency/figC.png&quot; alt=&quot;InputTransparent Hierarchy&quot; class=&quot;left&quot; /&gt;
Suppose that we had a gesture recognizer on &lt;strong&gt;E&lt;/strong&gt;. In order for it to properly consume gestures, it would need its input transparency set to &lt;strong&gt;false&lt;/strong&gt;. Furthermore, &lt;em&gt;all&lt;/em&gt; recursive parents and children must also have their input transparency set to &lt;strong&gt;false&lt;/strong&gt; in order for the gesture to be properly consumed. If &lt;strong&gt;C&lt;/strong&gt; overlapped &lt;strong&gt;E&lt;/strong&gt; but we didn’t have gesture recognizer and we didn’t want it to block and consume gestures, it would need InputTransparent to be set to &lt;strong&gt;true&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ve found this to be true in iOS and Android as of Xamarin Forms version &lt;strong&gt;2.4&lt;/strong&gt; (I did not develop for Windows Phone). To correct this problem, I wrote a function to properly set the input transparency.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;// input transparency is based on whether the view, its parent, or its children have gestures
// for a gesture to be passed and register, the children, view, and parent with a gesture recognizer must all have input transparency set to false
// however, any view that has no gesture recognizers, nor any from its children, should remain with input transparency true so as not to block gestures
static bool SetViewTransparency(View view, bool parentHasRecognizer)
{
    if (view == null)
        return false || parentHasRecognizer;

    var hasRecognizer = view.GestureRecognizers.Count &amp;gt; 0;

    // branch on views with children (including layouts), since they do not implement a shared interface with which to access their descendents
    var contentView = view as ContentView;
    var scrollView = view as ScrollView;
    var layoutView = view as Layout&amp;lt;View&amp;gt;;

    if (contentView != null)
    {
        view.InputTransparent = SetViewTransparency(contentView.Content, hasRecognizer || parentHasRecognizer);
    }
    else if (scrollView != null)
    {
        view.InputTransparent = SetViewTransparency(scrollView.Content, hasRecognizer || parentHasRecognizer);
    }
    else if (layoutView != null)
    {
        var childrenHaveRecognizer = false;
        foreach (var child in layoutView.Children)
        {
            childrenHaveRecognizer = !SetViewTransparency(child, hasRecognizer || parentHasRecognizer) || childrenHaveRecognizer;

        }

        view.InputTransparent = !(childrenHaveRecognizer || hasRecognizer);
    }
    else
    {
        var isInputView = view is InputView; // input views must not be transparent, or else they can't be selected
        view.InputTransparent = !(hasRecognizer || parentHasRecognizer || isInputView);
    }
    
    return view.InputTransparent;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why is this the case? Truthfully, I have no idea. I was not able to find much discussion on the topic, so I arrived at this entirely through experimentation. Perhaps the described model is not correct and input transparency works differently than described, but I have yet to find a situation where the described function did not resolve my input issues.&lt;/p&gt;

&lt;p&gt;If you find cases to the contrary or if your findings seem to support this model, please leave a comment to let me know.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://ibrewcode.com/clearing-up-input-transparency/</link>
        <guid isPermaLink="true">https://ibrewcode.com/clearing-up-input-transparency/</guid>
        
        <category>Xamarin</category>
        
        
        <category>Mobile Dev</category>
        
      </item>
    
  </channel>
</rss>
