<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BrendanLoBuglio</title>
    <description>The latest articles on DEV Community by BrendanLoBuglio (@brendanlobuglio).</description>
    <link>https://dev.to/brendanlobuglio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F142148%2F25d2b3ee-7312-43c1-bc69-6aa74470a920.png</url>
      <title>DEV Community: BrendanLoBuglio</title>
      <link>https://dev.to/brendanlobuglio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brendanlobuglio"/>
    <language>en</language>
    <item>
      <title>Welcome to Rabbit Hell! Reliable AI Locomotion with TDD</title>
      <dc:creator>BrendanLoBuglio</dc:creator>
      <pubDate>Thu, 23 May 2019 19:00:14 +0000</pubDate>
      <link>https://dev.to/brendanlobuglio/welcome-to-rabbit-hell-reliable-ai-locomotion-with-tdd-97e</link>
      <guid>https://dev.to/brendanlobuglio/welcome-to-rabbit-hell-reliable-ai-locomotion-with-tdd-97e</guid>
      <description>&lt;p&gt;Test-driven development (TDD) is a software workflow where code is written alongside small "unit test" programs that quantify whether each component is working. While automated unit tests are hard to apply to game development due to randomness, 3D interaction, and unpredictable player input, we were able to utilize a TDD workflow to write stable and regression-proof creature locomotion for &lt;em&gt;ElemenTerra.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F5r4UjhJ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F5r4UjhJ.gif" alt="Virtual rabbits navigating a series of "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Basics of Test-Driven Development
&lt;/h1&gt;

&lt;p&gt;Those experienced in TDD can skip this section; for everyone else, here is a basic primer.&lt;/p&gt;

&lt;p&gt;Let’s imagine we’re coding a custom function that adds two numbers. In a traditional workflow we would just write it the way we think it should work and move on. But to use TDD, let’s instead start the process by making a placeholder function and some unit tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int add(int a, int b){
 return -1;
}
// Our unit tests that throw errors unless “add” produces correct results:
void runTests(){
 if (add(1, 1) is not equal to 2)
   throw error;
 if (add(2, 2) is not equal to 4)
   throw error;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initially, our unit tests will fail because our placeholder function returns &lt;code&gt;-1&lt;/code&gt; for every input. But now we can go on to correctly implement &lt;code&gt;add&lt;/code&gt;, and have it return &lt;code&gt;a + b&lt;/code&gt;; all our tests will succeed! This may seem like a roundabout way to do things, but there are a few advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If we didn’t get enough sleep and write &lt;code&gt;add&lt;/code&gt; as &lt;code&gt;a - b&lt;/code&gt;, our tests still fail and we’ll immediately know to fix the function. Without the tests we might not catch our mistake, and experience strange behavior that takes time to debug later on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can keep our tests around and run them every time we build our code. This means that if another coder accidentally changes &lt;code&gt;add&lt;/code&gt; in the future, they’ll know immediately that they need to fix it because the tests will once again fail.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is all unnecessary for this simple example, but with complex features like predictable state-machine behavior (after eating 100 food, is &lt;code&gt;isFull&lt;/code&gt; true?) TDD saves time and improves a program’s stability.&lt;/p&gt;

&lt;h1&gt;
  
  
  TDD Application in Game Development
&lt;/h1&gt;

&lt;p&gt;There are two problems with TDD in game development. First, many game features have subjective goals that defy measurement. And second, it’s difficult to write tests that cover the entire possibility space of worlds full of complex interacting objects. Developers who want their character movement to “feel good” or their physics simulations to “not look jittery” will have a hard time expressing these metrics as deterministic pass/fail conditions.&lt;/p&gt;

&lt;p&gt;However, I believe that workflows more loosely based on TDD principles can still be applied to complex and subjective features like character movement, and in our game &lt;em&gt;ElemenTerra&lt;/em&gt; we did just that.&lt;/p&gt;

&lt;h1&gt;
  
  
  Unit Tests vs Debug Levels
&lt;/h1&gt;

&lt;p&gt;Before I get into my TDD practice, I want to make the distinction between an automated unit test and a traditional "debug level." It’s a common practice in gamedev to create hidden scenes with contrived circumstances that allow programmers and QA professionals to witness specific events.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj78ohyvo42jhz4qec28q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj78ohyvo42jhz4qec28q.png" alt="A secret debug level full of different objects in The Legend of Zelda: The Wind Waker"&gt;&lt;/a&gt;&lt;/p&gt;
A secret debug level full of different objects in The Legend of Zelda: The Wind Waker. &lt;a href="https://tcrf.net/File:TLoZTWW_K_Testc_1.png" rel="noopener noreferrer"&gt;Image Source&amp;lt;\a&amp;gt;&lt;/a&gt;



&lt;p&gt;A secret debug level full of different objects in The Legend of Zelda: The Wind Waker. Image Source&lt;/p&gt;

&lt;p&gt;We have many of these In &lt;em&gt;ElemenTerra&lt;/em&gt;: a level full of problematic geometry for the player character, levels with special UIs that trigger certain game states, etc. Like unit tests, these debug levels can be used to reproduce and diagnose bugs, but a few aspects separate the two:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit tests divide systems into their atomic parts and evaluate each individually, whereas debug levels test features on a more holistic level. After observing a bug in a debug level, developers still may need to search for the point of failure manually.&lt;/li&gt;
&lt;li&gt;Unit tests are automated and should produce deterministic results every time, whereas many debug levels are “piloted” by a player. This creates variance between sessions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this is to suggest that unit tests are strictly superior to debug levels; in many cases the latter is a more practical tool. But I also believe that unit testing is underutilized in game development, and should be explored further with systems to which it is not traditionally applied.&lt;/p&gt;

&lt;h1&gt;
  
  
  Welcome to Rabbit Hell!
&lt;/h1&gt;

&lt;p&gt;In &lt;em&gt;ElemenTerra,&lt;/em&gt; players use mystical nature powers to rescue the creatures hurt by a cosmic storm. One of those powers is the ability to create pathways out of the ground which guide creatures to food and shelter. Because these pathways are dynamic player-created meshes, the creature locomotion needs to handle strange geometric edge cases and arbitrarily complex terrain.&lt;/p&gt;

&lt;p&gt;Character movement is one of those nasty systems where "everything affects everything else"; if you’ve ever implemented such a system, you’ll know that it’s very easy to break existing functionality when writing new code. Need the rabbits to climb small ledges? Fine, but now they’re jittering up and down slopes! Trying to get your lizards to avoid each others’ paths? It looks like that works, but now their normal steering is all messed up.&lt;/p&gt;

&lt;p&gt;As the person responsible for both the AI systems and most of the gameplay code I knew I didn’t have a lot of time to be surprised by bugs. I wanted to immediately catch regressions as they came up, and so Test-Driven Development seemed appealing. The next step was to set up a system where I could easily define each creature locomotion use case as a simulated pass/fail test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FYA4Gc7x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FYA4Gc7x.gif" alt="Top-down view of the Rabbit Hell unit test scene"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This "Rabbit Hell" scene is composed of 18 isolated corridors, each with a creature body and a course designed to be traversable only if a specific locomotion feature is working. The tests are considered successful if the rabbit is able to continue indefinitely without getting stuck, and considered failures otherwise. Note that we’re only testing the creatures’ &lt;em&gt;bodies&lt;/em&gt; ("Pawns" in Unreal terms), not their AI. In &lt;em&gt;ElemenTerra&lt;/em&gt; creatures can eat, sleep, and react to the world, but in Rabbit Hell their only instructions are to run between two waypoints.&lt;/p&gt;

&lt;p&gt;Here are a few examples of these tests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FreiIDMF.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FreiIDMF.gif" alt="1, 2, 3: Unobstructed Movement, Static Obstacles, and Dynamic Obstacles"&gt;&lt;/a&gt;&lt;/p&gt;
1, 2, 3: Unobstructed Movement, Static Obstacles, and Dynamic Obstacles



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FzjMDu3W.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FzjMDu3W.gif" alt="8 &amp;amp; 9: Even slopes, and Uneven Terrain"&gt;&lt;/a&gt;&lt;/p&gt;
8 &amp;amp; 9: Even slopes, and Uneven Terrain



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F6W1xe9z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F6W1xe9z.gif" alt="10: "&gt;&lt;/a&gt;&lt;/p&gt;
10: "Navmesh Magnet" failsafe for floating creatures



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F145AMEz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F145AMEz.gif" alt="13: Reproduction for a bug where creatures would infinitely circle around nearby targets"&gt;&lt;/a&gt;&lt;/p&gt;
13: Reproduction for a bug where creatures would infinitely circle around nearby targets



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWULLMCI.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWULLMCI.gif" alt="14 &amp;amp; 15: Step-Up ability on flat and complex ledges"&gt;&lt;/a&gt;&lt;/p&gt;
14 &amp;amp; 15: Step-Up ability on flat and complex ledges



&lt;p&gt;Let’s talk about the similarities and differences between this implementation and "pure" TDD.&lt;/p&gt;

&lt;p&gt;My system was TDD-like in that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I started features by making failed tests, and then wrote the code needed to pass them.&lt;/li&gt;
&lt;li&gt;I kept running old tests as I added new features, preventing me from pushing regressions to source control.&lt;/li&gt;
&lt;li&gt;Each test measured only one feature in the system, allowing me to quickly pinpoint issues.&lt;/li&gt;
&lt;li&gt;The tests were automated and did not require player input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike Strict TDD:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There was an element of subjectivity in evaluating the tests; while true pathing "failures" (did not get from A to B) could be detected programmatically, things like position popping, animation syncing issues, movement jitters, and whether the steering “looked smooth” required human evaluation.&lt;/li&gt;
&lt;li&gt;The tests were mostly but not completely deterministic. Random factors like framerate variation caused small deviations, and a few courses had dynamic elements with randomized timing. Overall, creatures still usually followed the same paths and had the same successes/failures between sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Limitations
&lt;/h1&gt;

&lt;p&gt;Using TDD to write the &lt;em&gt;ElemenTerra&lt;/em&gt; creature locomotion was a huge boon for our schedule, but my approach did have a few limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The unit tests evaluated each movement feature in isolation, and so bugs with combinations of multiple features were not encompassed; unfortunately I didn’t have time to make 18² courses! Thus, my unit tests sometimes had to be supplemented by traditional debug levels.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;ElemenTerra&lt;/em&gt; has four creature species, but the tests only have rabbits. This is an artifact of our production schedule; the other three species were added much later in development. Fortunately all four share the same movement capabilities, but the larger body of our &lt;em&gt;Mossmork&lt;/em&gt; caused a few problems. If I had to do this all again, I would make the tests dynamically spawn a chosen species instead of using pre-placed rabbit bodies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz6w1nvgt3yn1d7m51566.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fz6w1nvgt3yn1d7m51566.png" alt="This galloping Mossmork requires a little more room to turn than a rabbit"&gt;&lt;/a&gt;&lt;/p&gt;
This galloping Mossmork requires a little more room to turn than a rabbit



&lt;h1&gt;
  
  
  Evaluation: Is Test-Driven Development Right for You?
&lt;/h1&gt;

&lt;p&gt;As developers it can be tempting to put a &lt;em&gt;little too much work&lt;/em&gt; into testing scenes the player will never appreciate; I won’t deny that I had a lot of fun building Rabbit Hell. Internal features like this can be a big waste of work and jeopardize milestones, so we need to take a hard look at when &amp;amp; whether a given feature warrants a unit testing apparatus. Below I’ve identified a few criteria that, in my eyes, justified TDD for &lt;em&gt;ElemenTerra&lt;/em&gt;’s creature locomotion.  &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Are your test cases time-consuming to produce manually?
&lt;/h2&gt;

&lt;p&gt;Before spending time on automated testing, we need to check whether we can evaluate a feature with the regular game controls. If you want to make sure your keys unlock doors, spawn a key and unlock a door with it! Creating unit tests for this feature would be an irresponsible time sink because it takes only seconds to test manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Are your test cases difficult to produce manually?
&lt;/h2&gt;

&lt;p&gt;Automated unit tests become justified when there are known, difficult-to-produce edge cases. Rabbit Hell course #7 tests creatures stepping off ledges, a circumstance their AI works very hard to avoid. Course #12 simulates the navmesh desyncing from the floor geometry, which only occurs during extreme lag. Such situations can be difficult or impossible to contrive with the game controls, while our tests produce them effortlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Do you know the desired results won’t change?
&lt;/h2&gt;

&lt;p&gt;Game design is all about iteration, and the goals of individual features may change as your game is redesigned. Even small changes in intent can invalidate the metrics by which you evaluate your features, and thus any unit tests along with them. While the creatures' eating, sleeping, and player interaction behaviors underwent several redesigns, we always needed them to get from point A to point B. Thus, the locomotion code and its unit tests remained valid throughout development.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Are regressions likely to go unnoticed?
&lt;/h2&gt;

&lt;p&gt;Maybe you’ve been in this situation: you’re wrapping up one of your final tasks before shipping a game, and suddenly you find a game-breaking bug in a feature you finished ages ago. Games are giant interconnected systems, and so it’s only natural that adding New Feature B might break Old Feature A. &lt;/p&gt;

&lt;p&gt;This isn’t so bad when the broken feature is ubiquitous, like the player’s ability to jump. If your core mechanic breaks, you’re bound to notice immediately. But the bug might slip under the radar if the broken feature is less frequently observed, like what happens when the player steps into a narrow crevice. Bugs detected in late development can jeopardize your schedule, and post-launch they hurt your player experience. Thus, unit tests can be great tools for maintaining edge case behavior, but are often redundant for functionality which already gets a lot of incidental testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. What’s the the worst-case cost of having tests, and what’s the worst-case cost of not having tests?
&lt;/h2&gt;

&lt;p&gt;Setting up a testing apparatus is a form of risk management. Let’s imagine that you’re deciding whether to buy insurance for a vehicle. The three questions you need to answer are: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How much do the monthly premiums cost?&lt;/li&gt;
&lt;li&gt;How likely is it the vehicle will be damaged?&lt;/li&gt;
&lt;li&gt;How expensive would the worst-case scenario be if you were uninsured?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For TDD we can imagine the monthly premiums as the production cost of maintaining our unit tests, the likelihood of vehicle damage as the likelihood of our feature breaking, and the cost of fully replacing the vehicle as the worst-case scenario for a regression bug.&lt;/p&gt;

&lt;p&gt;If a feature’s tests take a lot of time to create, the feature is uncomplicated and not likely to be changed, or it would be manageable if it broke in late development, then unit tests may be more trouble than they’re worth. If the tests are simple to put together, the feature is volatile and interconnected, or its bugs would cost a lot of production time, then tests can help keep us on schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The limits of automation
&lt;/h2&gt;

&lt;p&gt;Unit tests can be a great supplement to catching and reducing bugs, but I want to emphasize that they don’t replace the need for professional quality assurance on large-scale games. Proper QA is an art that requires creativity, subjective judgment, and excellent technical communication, which means that you need skilled and well-taken-care-of humans!&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the Waters
&lt;/h1&gt;

&lt;p&gt;While not the right choice for every circumstance, Test-Driven Development is a powerful tool that can and should be applied to more game development contexts. Let’s expand the horizons of what and how we test!&lt;/p&gt;

&lt;p&gt;If you have opinions on the points made in this article or have stories of using TDD in your own games, please shoot us an email. If you liked what you read and are looking for a skilled group of developers to build, improve, or help finish your game, &lt;a href="http://www.freeformlabs.xyz/contact" rel="noopener noreferrer"&gt;you can get in touch with Freeform Labs here&lt;/a&gt;. Until next time!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Freeform Labs, Inc.&lt;/strong&gt; is a games and software development team with a commitment to providing  the highest quality of digital craftsmanship, and a mission to inspire  learning and creativity through cutting-edge experience design. The team  is centrally located in Los Angeles, and maintains a network of trusted  partners across the globe. With specialized experience in VR, AR, Game  AI, and more, Freeform Labs provides an array of services including  consultation, work-for-hire software development, and on-site "ship it"  assistance. The company's portfolio includes work for Microsoft, Disney,  and Starbreeze - as well as award-winning original content.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>gamedev</category>
    </item>
    <item>
      <title>C#? In Unreal? Speeding up UE4 development with Mono-UE</title>
      <dc:creator>BrendanLoBuglio</dc:creator>
      <pubDate>Fri, 19 Apr 2019 20:50:04 +0000</pubDate>
      <link>https://dev.to/brendanlobuglio/c-in-unreal-speeding-up-ue4-development-with-mono-ue-3ci1</link>
      <guid>https://dev.to/brendanlobuglio/c-in-unreal-speeding-up-ue4-development-with-mono-ue-3ci1</guid>
      <description>&lt;p&gt;&lt;em&gt;“Should I make my game in Unreal or Unity?”&lt;/em&gt; is a frequent conundrum for gamedevs, and one of the biggest sticking points is Unity’s use of C# versus Unreal’s C++. Freeform Labs' dilemma while developing ElemenTerra was that we preferred Unreal's renderer and editor but Unity’s C# scripting. Our solution was to integrate the open-source &lt;a href="https://mono-ue.github.io/" rel="noopener noreferrer"&gt;Mono-UE plugin&lt;/a&gt;, which lets us write C# code for our Unreal game!&lt;/p&gt;

&lt;p&gt;C# versus C++ is a complex topic you can read about elsewhere. We’re fluent in both at Freeform Labs, but prefer C# for its faster development speeds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;C# is much quicker to compile; our C# solution builds in 3-5 seconds, while the C++ codebase takes an average of 100.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because the language builds faster, C# IDEs are quicker and more responsive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C# error messages are specific and coherent; C++ errors are verbose and often bury the lead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C# nicely catches its exceptions, whereas most C++ errors cause Unreal to crash.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, being able to work in C# was a huge productivity boost that justified jumping through a few hoops to integrate the plugin.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Basics of Mono-UE
&lt;/h1&gt;

&lt;p&gt;Let’s start with the core premise: Mono-UE works by hooking C# classes into the same bindings that connect Blueprints and C++.&lt;/p&gt;

&lt;p&gt;Those who’ve used Unreal will be familiar with making “Blueprint” children of C++ classes. Blueprint classes are authored with a visual editor that can add new components, scripting nodes, and plenty more. In C++ programmers use macros like UCLASS, UPROPERTY, and UFUNCTION to choose which definitions to expose to Blueprints. The compiler then creates “bindings,” Blueprint-accessible wrappers around C++ code that allow the two ecosystems to communicate.&lt;/p&gt;

&lt;p&gt;Mono-UE allows us to take these same bindings and create C# classes instead of Blueprints. The UCLASSes that are extensible by Blueprints can be inherited from in C#, and C# can call and override Blueprint-accessible UFUNCTIONs. This alone encompasses a huge swath of functionality, and lets us write complex gameplay logic in C# code. What’s more, C# classes can themselves be extended by Blueprint children!&lt;/p&gt;

&lt;p&gt;Here’s a simple example of a Mono-UE C# Class, with comment blocks highlighting the connection points between C# and C++:&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;



```

&lt;span&gt;/// A new C# class that extends Unreal’s “AActor,” which is defined in C++&lt;/span&gt;
&lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; &lt;span class="highlight"&gt;MyCSharpActor&lt;/span&gt; : Actor
{  
    &lt;span&gt;/// Overridden class constructors:  &lt;/span&gt;
    &lt;span&gt;protected&lt;/span&gt; &lt;span class="highlight"&gt;MyCSharpActor&lt;/span&gt;(ObjectInitializer initializer) : &lt;span&gt;base&lt;/span&gt;(initializer) {}  
    &lt;span&gt;protected&lt;/span&gt;&lt;span class="highlight"&gt; MyCSharpActor&lt;/span&gt;(IntPtr inNativeObject) : &lt;span&gt;base&lt;/span&gt;(inNativeObject) {}   
   &lt;br&gt;    &lt;span&gt;/// C# override of the ReceiveTick function, which is defined in C++  &lt;/span&gt;
    &lt;span&gt;protected&lt;/span&gt; &lt;span&gt;override&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; &lt;span class="highlight"&gt;ReceiveTick&lt;/span&gt;(&lt;span&gt;float&lt;/span&gt; deltaSeconds)  
    {     
        &lt;span&gt;base&lt;/span&gt;.&lt;span class="highlight"&gt;ReceiveTick&lt;/span&gt;(deltaSeconds)
        &lt;span&gt;// C# can invoke the UFunctions SetActorLocation and GetActorLocation,&lt;/span&gt;
        &lt;span&gt;//  just as we would from a Blueprint or C++:&lt;/span&gt;
        &lt;span&gt;this&lt;/span&gt;.&lt;span class="highlight"&gt;SetActorLocation&lt;/span&gt;(&lt;span&gt;this&lt;/span&gt;.&lt;span class="highlight"&gt;GetActorLocation&lt;/span&gt;() + &lt;span&gt;new&lt;/span&gt; Vector3(1f, 0f, 0f));
    }
   &lt;br&gt;    &lt;span&gt;/// Custom function that Blueprints can call because of the UFunction and&lt;/span&gt;
    &lt;span&gt;///  BlueprintCallable attributes  &lt;/span&gt;
    [UFunction, BlueprintCallable, Category(&lt;span&gt;"My C# Actor"&lt;/span&gt;)]
    &lt;span&gt;protected&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; &lt;span class="highlight"&gt;MyBlueprintCallableFunction&lt;/span&gt;(&lt;span&gt;int&lt;/span&gt; input)  
    {
        &lt;span&gt;// ...  &lt;/span&gt;
    }
    &lt;br&gt;    &lt;span&gt;/// Custom function with no UFunction attributes, callable only by other C# code&lt;/span&gt;
    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; &lt;span class="highlight"&gt;MyCSharpOnlyFunction&lt;/span&gt;(&lt;span&gt;int&lt;/span&gt; input)  
    {       
        &lt;span&gt;// ...  &lt;/span&gt;
    }       
}

```



&lt;/pre&gt;



&lt;p&gt;Mono-UE is open-source software maintained by &lt;a href="https://twitter.com/mjhutchinson" rel="noopener noreferrer"&gt;Mikayla Hutchinson&lt;/a&gt; and a lovely group of other volunteers to whom we are deeply grateful. The setup process is detailed &lt;a href="https://github.com/mono-ue/UnrealEngine/tree/monoue/Engine/Plugins/MonoUE" rel="noopener noreferrer"&gt;here&lt;/a&gt;. With the plugin still in development and some features missing or unfinished, be aware that you’ll need to pick up a handful of idiosyncratic workarounds as you learn to use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Our Mono-UE Workflow
&lt;/h1&gt;

&lt;p&gt;Now that we’ve established the essentials, let’s talk about the day-to-day of working with this plugin! I spent a year of my life in Mono-UE and could go on forever, but for brevity here are just a few usage notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;C# classes have access to almost all the functions available to Blueprints. This encompasses most of what we need, but sometimes we find C++ functions that don’t have bindings. This is a familiar problem for Blueprint scripters as well, and in both cases the solution is to write Blueprint-exposed C++ wrappers around the desired functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Most of our objects are “3-layer cakes” composed of a C++ base, a C# child class, and finally a concrete Blueprint. Generally, gameplay logic goes in C#, engine enhancements go in C++, and artists design audiovisuals in the Blueprint. Thus we spend the majority of our time in the language that’s fastest to write, work in C++ only when necessary, and keep our look-and-feel functionality in a format the artists can edit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5uvwse63f23owoodqb42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5uvwse63f23owoodqb42.png" alt="3-layer-cake-freeform-labs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Every once in a while we had to modify the Mono-UE source. Packaging &amp;amp; shipping a standalone executable wasn’t available when we started ElemenTerra, but we fixed the bug and shipped the game! Our modification has now been accepted as a pull request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Hot reloading” wasn’t working during ElemenTerra development, so we needed to close and reopen the editor after changing our C# code. This was annoying, but we still found it much faster than recompiling our C++. At the time of writing, there is a not-yet-integrated &lt;a href="https://github.com/mono-ue/UnrealEngine/pull/201" rel="noopener noreferrer"&gt;pull request claiming a partial fix&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these methods we enjoyed all the benefits of C# described above: faster build times, more responsive IDEs, better error messages, and exception handling that doesn’t crash the engine!&lt;/p&gt;

&lt;h1&gt;
  
  
  What about performance?
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;ElemenTerra&lt;/em&gt; is a VR game, which required us to hit 90+ fps. One of the main draws of C++ is that it’s a low-level language that can run extremely fast; does using C# then put us at a liability? The answer is not so black-and-white&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzftjbfglgh8jyvyh0dwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzftjbfglgh8jyvyh0dwq.png" alt="ue4 Performance Analysis"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start with the facts, we’ve observed that Unreal C++ runs unconditionally faster than Mono-UE C#. Where things get gray is that sometimes C++ is significantly faster, but often the difference is trivial. For generic algorithms and math functions we saw very little difference, but C# was slower when we were doing a lot of thunks. “&lt;a href="https://en.wikipedia.org/wiki/Thunk#Interoperability" rel="noopener noreferrer"&gt;Thunk&lt;/a&gt;” is a silly software term which in this context refers to a call from C# into an Unreal C++ function. These jumps between runtime environments are inherently expensive, and rack up a performance cost when done en masse.&lt;/p&gt;

&lt;p&gt;This is a factor that needs to be respected, but is by no means a dealbreaker on Mono-UE. Here are the best-practices we used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Never optimize before profiling!&lt;/strong&gt; C# objects that only had a few spawned instances or didn’t call thunks from loops usually didn’t chart on the profiler: no action necessary. This applied to the majority of our C# codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid redundant thunks.&lt;/strong&gt; Instead of thunking GetActorLocation() 3 times, we can thunk it once and save its output in a variable. Rather than call DestroyActor() on every object in an array, we can write a new DestroyMultipleActors() C++ function and call it once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port expensive C# code to C++.&lt;/strong&gt; When the profiler &lt;em&gt;did&lt;/em&gt; show a piece of our C# code was expensive, we moved it down to C++. Often this was done in the simplest way imaginable: copy the whole script, paste it into .h and .cpp files, do a few find-replaces, and fix the errors until it worked. We were surprised by how few complications came from this approach; often the C++ worked on its first run! Our strict encapsulation policies at Freeform Labs made this approach quite painless, as each script had few external dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these practices in place, we enjoyed the productivity boost of C# and still reached 90fps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Is Mono-UE Right for Me?
&lt;/h1&gt;

&lt;p&gt;This article is about why Mono-UE was the right choice for our team, and we have no regrets. If I've piqued your interest, I’ll close with advice for anyone interested in trying Mono-UE themselves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you’re a team with C# and C++ experience and want to be writing more of the former, Mono-UE might be right for you! Just be aware that there's an upfront cost to setting it up and that you may run into bugs you’ll need to fix in the plugin’s source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you’re a tech-inclined hobbyist looking for something new, give Mono-UE a look! It’s a great opportunity to learn more about how Mono and UE4 work under the hood, and as an open-source project it’s always looking for new contributors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you’re a Unity user who wants to try Unreal Engine and only knows C#, you’re in luck as long as you can tolerate the roadbumps that come with using still-in-development software. The first-time setup is tricky and you’ll encounter bugs which you need the community’s help to solve, but the payoff is definitely there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you’re new to programming and think C# would be easier to learn than C++, I’d recommend picking up Blueprint Scripting or Unity instead. Both of those tools already have an abundance of online resources for first-time learners, whereas the Mono-UE community is just getting started.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you’re looking to ship to console or mobile, Mono-UE does not yet support those platforms but may in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you want to get your company set up with Mono-UE but don’t know where to start, perhaps we can help! You can get in touch &lt;a href="http://www.freeformlabs.xyz/contact" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Programming Languages and Peace of Mind
&lt;/h1&gt;

&lt;p&gt;As game developers, picking the right tool is important both for the quality of our craft and for the quality of our lives. Personally, I find Mono-UE extremely fun to use: C# is a language where I can get into a great flow state, and not being interrupted by compile times or obtuse errors helps me maintain focus. Whatever you do decide to use, I hope this article has inspired you to reflect on your own development workflow!&lt;/p&gt;

&lt;p&gt;If you’re interested in trying Mono-UE yourself, this &lt;a href="https://mono-ue.github.io/" rel="noopener noreferrer"&gt;landing page&lt;/a&gt; will direct you to the source code and some community resources. Also feel free to contact us directly if you need a tip or &lt;a href="http://www.freeformlabs.xyz/contact" rel="noopener noreferrer"&gt;want to talk more&lt;/a&gt;. Until next time!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Freeform Labs, Inc.&lt;/strong&gt; is a games and software development team with a commitment to providing  the highest quality of digital craftsmanship, and a mission to inspire  learning and creativity through cutting-edge experience design. The team  is centrally located in Los Angeles, and maintains a network of trusted  partners across the globe. With specialized experience in VR, AR, Game  AI, and more, Freeform Labs provides an array of services including  consultation, work-for-hire software development, and on-site "ship it"  assistance. The company's portfolio includes work for Microsoft, Disney,  and Starbreeze - as well as award-winning original content.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>gamedev</category>
      <category>unreal</category>
    </item>
  </channel>
</rss>
