Monday, July 27, 2015

Bit of a Block

Reality hit me in the face today as I tried to implement the system described below: I learned you can't create objects in Blueprints. Whaaa?

Only Actors can be created. Several people said to just make Actors for everything, so they're suggesting I make an Actor for every command issued and for each spell.

That sounds terrible. An actor is an object in the scene. A command is not and should not be an actor. What is the position of a command? How do you render a command? No, I refuse to do that.

Even if I wanted, I still couldn't structure it the way I wanted even with Actors. I'm not going to place an instance of a Fireball in every level just so I can attach it to my character.

All is not lost, though. We have the power of code by our side. The Command and Ability system will just need to be primarily driven in code. I can call into a native function that creates objects, and I can even return references to those objects. I just need to manage lifetime myself, but I'm used to that. I was hoping to do it all in Blueprints, but mostly as a self-imposed challenge. I'll gladly use code if it means the game is better structured.

I'm still not clear how you attach an instance of a Blueprint to an Actor. Let's say I have a Blueprint of a Fireball. It is the script for a Fireball, the visuals, etc. I would like some of my characters to have a Fireball as one of its abilities. What mechanism do I use to point to the Blueprint? Perhaps I make the Fireball an Actor Component and add it that way? I'm pretty sure you can add Actor Components at runtime, which will be important to support gaining abilities via level up.

But then again, you can't even instantiate objects so I probably shouldn't assume anything.

Moving Code Between Blueprints is Hard

The first step I'm taking in my plan outlined below is to move a bunch of my blueprint code out of the level blueprint and into a new PlayerController blueprint class I just made that derives from my custom native one.  A few notes on why this was harder than it should have been:

  • I had to update my DefaultPlayerController class in the Game Mode.  To do this, I look up the blueprint by path.  That path ended up being "/Game/Blueprints/TacticsGamePlayerControllerBlueprint". Apparently "/Game" maps to the root of my project, but I'm not sure how I was supposed to know that.
  • Despite the UI suggesting you can do it, copy and pasting large chunks of Blueprint code is not a good idea.  Nodes that don't have meaning (i.e. local variables or functions that don't exist in the destination) are simply removed.  This makes it very difficult to know which nodes you need to fix up -- I would've rather they import in and are disabled.
  • Some part of the native code change I made broke the Get node to my "Targeting State" property. It refused to treat it as an Enum in any of the nodes where I used it, calling it a Byte instead.  Deleting them and re-adding them fixed it.  Strikes me as some kind of bug.
  • I'm not sure if this is the case, but I suspect you can only have references to level objects from within the level blueprint.  That's reasonable. I had relied on that a bit, so I'll need to restructure  it such that the level blueprint passes those references into the player controller.  For now I just disabled the 1-3 hotkeys to select characters.
With those three obstacles out of the way, I'm now right back to where I started... but with cleaner code! :)

Sunday, July 26, 2015

Some Notes on Game Structure

I'm at a point now where I've got a few nice building blocks, and I can start turning them into more of a system.  I'd like to now move toward building commands, abilities, movement, etc.  I'll need a proper system to manage these pieces, and you'll see why thinking about them holistically is both necessary and hard.

For this post, I'm just going to think out loud stream of consciousness style to gather some thoughts on how I'm going to structure the command system from here.  Keep in mind my Unreal experience is quite low, so this might be a terrible way to do things.  But alas, we must move forward somehow, and we learn best when we get burned!

First, let's start with some requirements.

  • From the user's point of view, it'll be a standard tactics game style of UI.  Select a character, select an ability, go into targeting mode, select a target, confirm the target, execute the ability.  
  • Different abilities may have slightly different targeting rules and steps.
  • It'd be nice if the system can support an action history because I like seeing that in my tactics games.  
  • The same system should work for players and AI.  
  • I'd like it to be very easy to construct new abilities from simple building blocks.  
  • Finally, I want it to follow good engineering principles: solid code reuse, low coupling, etc.

There are different approaches you can take when designing a system like this.  I frequently use a bottom-up approach where I imagine what it would look like to build a few different things using this system that doesn't exist, then I look at the pieces I now require and move up a step.  I find that this approach makes it easier to understand real-world use cases.  A top down approach has a tendency to miss real-world cases, leaving you in the awkward position of saying the user can't do what is desired or hacking the system to make it work.

So let's see how we would build a Fireball ability.  This ability can target a location and explode, dealing instant damage to everything in range and applying a Burning debuff to them.  Let's write some pseudocode!

function Fireball::Execute
    damage = CalculateDamage()
    characters = target.GetCharactersNearTargetPoint(explosionRange)
    for each character in characters
        ApplyDamage(character, damage)
        AddEffect(character, Burning)

function Fireball::CalculateDamage()
    return baseDamage + scalingDamage * myCharacterLevel

function Target::GetCharactersNearTargetPoint(range)
    return SearchCharacters(targetPoint, range)

Okay, so I've highlighted some pieces worth talking about.

Target: The ability needs to know where to apply its effect.  A target object seems like a nice way to encapsulate that concept.

MyCharacterLevel: The ability also needs to know some information about who is using the ability.

ExplosionRange: To reduce coupling, we pass in any relevant ability information to the targeting object so it doesn't need to know anything about the ability. 

Note: my first draft had me passing the ability into the target, but that caused a two-way dependency, which is generally icky.  By pushing the data into the target rather than having the target pull the data out of the ability, that makes all flow unidirectional. Conceptually I like this, too -- an ability needs to have a target in order for it to execute, but a target can stand alone and doesn't need an ability to exist.

This suggests a basic class structure already: A character has an ability. An ability has a target (hold onto this thought).  

As of right now, an ability also has a reference to its character. This goes against what I just said about explosionRange, but for some reason this coupling bothers me a bit less.  Probably because conceptually an ability naturally feels like it only exists as a result of a character and also because the Unreal Component structure is such that the Character will already be accessible to any Abilities Component inside it.  I'm going to move on for now, and we can revise this later if I feel gross about it once I understand the rest of the system more.

So now that we know what an ability is, how do we execute it?

The user has a selected character that we keep track of.  There's also some UI that maps each ability, so when I press a button or hotkey, I activate that ability (which is itself a multi-step process).  We'll call this request to use an ability a Command.  Not only does Command work conceptually, but we're literally using the Command design pattern as well. 

Interestingly enough, this article on the Command pattern showed up on my Twitter feed this morning, so I even have a relevant link to give for those not familiar with the pattern:http://gameprogrammingpatterns.com/command.html.  I know, it's unfashionable to talk about design patterns these days, but I still stand by them when used appropriately, especially when it comes to easily communication through a shared language.  But I digress...

I like the idea that a Command brings together an Ability and a Target and tells them to combine (execute).  This tells me that we'd create a target object, run a state machine until it's valid and locked in, then pass that Target into the Ability when telling it to execute.  That thought I told you to hold onto above: an Ability only has a Target when it's executing (i.e. we pass it in as a parameter).

Let's bring it back to Unreal now.  When the user hits that ability hotkey, we'll need to construct a Command.  The PlayerController can probably handle that construction.  It'll then pass in the ability.

Once the ability is passed in, the command will ask the ability to construct a target object.  We go factory style on the target because, as we'll discover later, the exact subclass of Target depends on the ability.

I'm going to apologize right now for my inconsistent capitalization and just stop trying to pick a style. It makes sense in my head, okay?

Once we have the command, the PlayerController would hold onto it as the current active command. It would also bind some events on that command so it can respond as the state machine updates.  It would also immediately ask the command to begin targeting.

The command then forwards the targeting request to the targeting object, along with any per-command information it needs (such as caster location).  That causes the targeting object to show and update as the user's mouse is moved around. The ability had already fed in information like whether or not it requires line of sight, the types of characters that are valid, etc. The targeting object uses all that information to determine whether or not the target is valid, which it uses when updating the UI.

Once the user clicks, the targeting object fires an event that the target has been acquired.  The command was listening for this event and will advance the state machine to the lock in phase.  Some UI will get updated and show a confirmation frame.  If confirmed, that will then cause the command to execute, which calls the Execute function on its ability, passing in the target.

For external systems, such as UI frames, I imagine the PlayerController sends an event any time the active command changes.  Those systems can then register directly on the active command so they can respond to changes in lock in and targeting state.

Finally, let's talk about the actual class hierarchies.  I know this is getting long, but I need these notes to help gather my own thoughts. :)

We have a Command, and I'm going to look slightly ahead and have a base class for Command and a subclass for CommandCharacterAbility.  This way I can use commands for other things if necessary.  For example, what if Save was a command?  Or how about that most useful of debugging tools -- cheat commands?

Command
    void Activate()
    void Execute()

CommandCharacterAbility extends Command
    void BeginTargeting()
    Ability* ability
    Target* target
   
As we said before, characters have a set of abilities.  They're not references here because characters own the abilities.

Character
   Ability[] abilities

Next the ability itself.  Abilities can all be executed.  They can also create targets.  In this way, AbilityFireball would construct a target of type TargetPointAOE while AbilityHeal would create a TargetCharacter. The Command and other classes could then operate on that target without caring what kind of target it is.  Yay polymorphism.

Right now I have the abilities deriving straight from Ability.  If I discover there are common ability archetypes, we could add another layer there.

Finally, the IsTargetValid function is worthy of special mention.  Imagine we disallow you to cast Heal on targets with full health.  I'd still like the targeting system to consider that a valid target, but I don't want you to be able to Lock In the ability.  If we simply prevented you from targeting at all, there'd be no opportunity to tell you why you can't cast the spell.  Also, that kind of complex validation where we look at character status doesn't feel right inside the Target class.  I'd rather custom validation like that occur inside the ability.  So there are two styles of validation: whether you can select the target and whether you can choose the selected target.

Ability
    void Execute(Target*)
    Target* CreateTarget()
    bool IsTargetValid(Target*)

AbilityFireball extends Ability
    override void Execute(Target*)
    override Target* CreateTarget() // Type: TargetPointAOE

AbilityMove extends Ability
    override void Execute(Target*)
    override IsTargetValid(Target*)
    override Target* CreateTarget() // Type: TargetPoint

AbilityHeal extends Ability
    override void Execute(Target*)
    override IsTargetValid(Target*)
    override Target* CreateTarget() // Type: TargetCharacter

Finally, we have the target.  The base target has a bunch of common properties, such as the origin position, range, etc.  Each subtype would draw a different kind of targeting UI and have different accessors for getting the data you'd need out of it.  For example, TargetCharacter has a GetTargetCharacter() function for obvious reasons, but that function doesn't make sense for TargetPointAOE.  The abilities know what their TargetClass is, so they'll be equipped to cast down during execution.

Target
    bool IsValid()
    void LockIn()
    Vector originPosition
    float range
    bool requiresLOS
    bool friendly

TargetPoint extends Target
    override bool IsValid()
    position GetTargetPoint()

TargetPointAOE extends TargetPoint   
    override bool IsValid()
    Character*[] GetCharacters()
    float aoeRange

TargetCharacter extends Target
    override bool IsValid()
    Character* GetTargetCharacter()
    void SetAllowedTypes(bitmask)

I still have some questions on this architecture.  For example, while targeting a Move, it would be nice to draw a path on the ground.  Who is responsible for that?  The Target object doesn't have enough information on that because different Characters may move differently.  I'll have to think about that some more.

I'm also a bit afraid at the number of parameters that'll go into the target classes.  Maybe it should just have a reference to the ability?  RequiresLOS, Friendly, and Range all seem like properties of an Ability, and duplicating them all down into the target just for some self-imposed encapsulation may cause more problems than it's worth.

So this was a massive post and far larger than I intended, but I think it highlights the amount of consideration needed when designing something as core as a command/ability/targeting system in your game.  Sure, it'd be super easy to just start writing code or blueprints, but decisions I make early will have a massive impact on what is easy and what is hard in the future.  A little forethought now can help make sure I don't design myself into a corner.

I'll also say that I lied a bit at the top of this post -- it wasn't stream of consciousness.  As I thought about it and discovered different considerations, I would go back and make changes.

This process of make a design, ask questions about it, revise, poke holes in it, etc. is very normal.  In fact, writing up this blog (i.e. explaining it) was very helpful in that process.  The act of explanation, whether on a blog or with a teammate, is probably your #1 tool when tech designing.  It's amazing how you find errors when you go through the exercise of putting words to it.  I spent most of the day on this post, and I feel like I made great progress on the game despite never opening Unreal.

That said, the threat of overengineering is real, especially on a personal learning project where the scope will be limited.  Perhaps it's time to start building so I can find those holes using real world problems?

I'll be sure to compare various stages of implementation with these notes to see how close we got.

Saturday, July 25, 2015

Why We're Bad at Estimates

So it took me an hour and a half to write the block of code in the previous post. I think it says a lot about software development and why we're so bad at estimations, so let's case study it.

I knew I wanted a function to convert a world position to a tile position. For the implementation, look below, but essentially take a vector, round X and Y down to the closest multiple of tile size then add half the tile size. Keep Z.

If someone asked how long it would take to write that function, I'd estimate a few minutes. I know the formula already, and I've written functions like it before many times. I would also guess I could do it in a handful of lines of code and the risk of getting it wrong is very low.

Let's take a look at why I'd be so wrong while being completely correct with what I just stated.
The main problem with the estimate is there's no context to the request, and it turns out context is everything. In this case the context is Unreal, a system I'm just barely starting to learn.

My first problem was I didn't know where to put the code. I knew I wanted a Blueprint function (scope creep!), and it would just be a utility function.

I made a blank class and wrote the implementation in a static function. I then added the macro to make it a Blueprint, and compile error.

My class needs to derive from UObject if I want it in a Blueprint. Totally reasonable and makes sense. I have a handful of classes already, so I copied over the UClass macro and the body generation one. No dice. I fiddled a bit and compared it to others before I gave up and used Unreal to make a new class, knowing it would set it up correctly.

I didn't know what to derive from, though. UObject wasn't in the global list, but I found Blueprint Library. That one sounded right. So new class created, old one deleted, get my code in. It works, and I have it in a Blueprint now.

Pull it up in the Blueprint, but it requires a target (the instance I'm calling the function on). I really wanted this to be a simple, stateless function and not a manager class, and I know in regular C++ I would make this function static (or not even in a class, but I know a class is required).
Here's where I went wrong: I had also seen in Blueprints they call static functions pure. I Googled that and found the BlueprintPure specifier. No good. StackOverflow said I had to make the function const. They were wrong. After a few combinations, I went back to my gut and static was correct.

It all worked, and it did what I wanted. But good programmers relentlessly refactor, right? I moved the tile size from a literal to a constant. Easy. I then thought it'd be convenient if Blueprints had access to the tile size (more feature creep!). Turns out you can't make static member variables Blueprint properties. I then had to make it a function that returns the value... which led to a rabbit hole where I was curious how Unreal treats inline. Finally 90 minutes later, I was done.

You can see with all the problems above, plus some tools failure (Unreal crashes a lot) and compile time, why my initial estimate was off by an order of magnitude. This is more typical than atypical for software development, and scales with the size and complexity of the project and team.

So what can we take away from this? First, understand context. What is the project like you're working in? How experienced are your programmers in it? How similar is it to other completed tasks?

Next, what is the entire request? It wasn't just make that function, but make that function accessible by Blueprints as a pure function along with an accessor for tile size. Right there that would've signaled me since I didn't really know what a pure Blueprint is.

Finally, never underestimate testing, research, tools failure, compile times, curiosity distractions, and other sinks. Remember, a typical estimate is highly optimistic for lots of legitimate, human reasons, so we need to actively fight against that.

As a wise programmer once taught me: the problem isn't that we need more accurate estimates, it's that we need larger estimates.

Friday, July 24, 2015

Sometimes Code is Easier Than Blueprints

I've said a few times that I'm really enjoying Blueprints in Unreal.  The visual feedback and structure has a nice flow to it.  However, I just came across a function I wrote that has no business being in a Blueprint compared to code:


Compare that to the C++ version:


Thursday, July 23, 2015

Massive Chalice

I'll have more to say about this as I play further, but I've started playing Massive Chalice.  I'm probably about two hours in at this point, and I'm mostly enjoying it.  There's a good amount of interesting differences I'm noticing between XCom and Massive Chalice that I'm seeing since I've played both back-to-back.

First off, XCom's cover system is a real cornerstone of that game, and one I think may be underrated.  By having a cover system, it allows the game to be a lot harder. The tutorial, opening missions, and reaction VO make it very clear: if you're not in cover, you're doing it wrong.

This forces you to take a very cautious,almost puzzle-solving path when advancing. The world feels dangerous, and it in fact is dangerous. It also looks and feels really badass, like you're an alien-killing SWAT team, which fulfills the fantasy nicely. I also enjoyed the gamble you sometimes had to make to stand somewhere unsafe for that chance to finish off a dangerous enemy or save an ally. Overall it made for great drama and tension.

Massive Chalice has no cover system. Instead, characters can only rely on visibility to protect themselves from threats. Since defense is so limited, it seems as you're supposed to expect more death. You can't prepare for attacks well, and you have limited responses if you're overwhelmed. Like XCom, this is reinforced through tutorials and reaction VO. Upon my first death, the chalice made it very clear that that was the first of many.  Separate from combat, characters also die from old age at an astonishing rate. I'm just learning characters' names as they enter their golden years.

The result is that I'm already less attached to my characters than in XCom.  This is a common reaction. Kotaku's review makes the same complaint. While I enjoy playing matchmaker, and I get excited as they have babies and the babies grow up, I have trouble keeping track of individual heroes. When my first character died of old age, my first thought was "Who?"

I'm not sure yet if this is such a bad thing, though. The dark side of being so attached to my XCom characters is that I would reload saves when they died. This is clearly not the intended way to play, but I felt a single death was a game over sentence for me. I also very obviously had my favorites, and I would never bother bringing anyone else to battle. I probably would've enjoyed some more variety, but comfort kept me with the same six heroes. It also meant I had to have my core team survive because I wasn't leveling up any alternates.

So which is better? I think the verdict is still out, but I'm leaning toward higher attachment. I'll give it some more thought as I play through Massive Chalice further, and I'll share my thoughts on how you could hybridize the two in a future post.

Relying on the Game Engine

I'm taking a slightly different mindset for this project.  Instead of going into this knowing how I'm going to implement everything, I'm instead exploring and relying on the game engine.  This is partially because I want to learn Unreal better, but it's also because I'm curious where this will lead.

When I worked on my last side project, which also happened to be a tactic-like game, it was for a long-term game jam competition.  Because of the limited time, I dove straight into it with full intent of how I would implement everything.

Since it was a multiplayer game and I was both unfamiliar and not confident in Unity's multiplayer support, I went with an approach I knew.  The main architecture of the game was that the game client was just a "dumb" asynchronous view of the game state, and all the game logic ran on a standard LAMP stack.  There was a completely different codebase for the client engine (C# in Unity) and the game logic on the server (PHP/MySQL).

This decision forced a lot of how the game was built.  All logic was written in stateless PHP.  Essentially, I would receive a command as a JSON string, read the MySQL database, process the command, then return back updated game state as JSON.  It actually worked remarkably well, and I was really happy with the final result of the game.  It felt like a real game, it played well, and the multiplayer aspects worked flawlessly.

A major downside was that building the game content was not intuitive.  All game data lived in a MySQL database, including all NPCs, quests, the rules for building random dungeons, etc.  The game was a randomized rogue-like, so it worked for what we wanted, but content authoring was not easy.  We also couldn't take advantage of any of the game engine's features, such as AI, pathfinding, etc.

Another problem was that everything felt sort of stiff.  Sure, it's a turn-based game and that's a fairly common problem, but since the only processing that could occur was as the result of someone hitting the PHP backend (stateless system, and we never built a job scheduler), nothing would or could occur outside of you or another player issuing a command.

For this new game, I'm instead aiming for a purely single player experience.  I intend that levels would be built by hand in Unreal, NPCs can be scripted via Blueprints, etc.

A neat side effect of this is that I'm using a lot more of the tool than the previous project.  That project, built with Unity, really didn't make much use of the engine other than as a graphics engine and object manager.  This time, I'm having a lot of fun relying more heavily on the underlying AI tools, navigation system, physics for gameplay/UI, etc.

So while the underlying tactics genre is the same, these are ultimately very different games with very different architectures.

Ultimately, I think the end result will be a far richer game.  Where the previous project felt like a fancy game of chess where the tile was everything, this will feel more like a top-down turn-based shooter where tiles are just grid helper lines.  Even though the level has nothing to it, it already feels far more fluid and alive than the previous project.

I see now why Firaxis built XCom in Unreal, and I'm even starting to see some basic similarities form as the game takes shape.

Wednesday, July 22, 2015

I'm No Material Girl Afterall

So I was able to get the basic selection cube material working as I wanted, but I got stuck getting the exact gradient that I was looking for.

Here's a shot of the cube:

I was hoping for a bit more opacity on the bottom of the sides, but I figured it wasn't a valuable use of time getting too nitpicky on this right now.

For reference, here's the material:










Basic rundown is that I take a gradient texture and rotate it for times, once for each side.  I then pow each one to compress the gradient, subtract away anything that doesn't meet a threshold, clamp for good measure, then add them together.  I then multiple that by a glow color and value to get a nice emissive brightness.

For opacity, I take the world position of the pixel, subtract away the object's position to get a local position (is there a native function for that? I couldn't find one...).  I then normalize the values, mask to get just the Z, and multiply it by a negative number to cause the white to be down.  Multiply by a scalar parameter and feed that into opacity.

One thing I'm having trouble with is the glow is flickering as the camera moves.  I suspect there's a post process effect causing this.  I had some flickering with my selection circle due to temporal anti-aliasing being on.  It's set to FXAA now, and even though I went through and tried to disable a bunch of settings, I still have it.  Turning off all post processing fixes it, but then I lose my glow as well.

I'll look into this further later.  For now, I want to get movement, targeting, and tiles working.

Tuesday, July 21, 2015

Living In a Material World

I've figured out why Tech Artists are always so happy: working with materials is super fun.

I'll have more to say on Blueprints and node graph editing later, but building shaders in Unreal is pretty amazing. If you're not familiar, you basically choose a general type of materials, such as Surface, Decal, or Translucent. You're then given a node with a bunch of inputs, and you can build nodes in any way you want to feed into those inputs.

The brilliance comes in the ease (and daresay joy) in building nodes combined with the ease of previewing. As you're building up your graph, you can preview the entire material live, of course, but you can also preview any specific node to see how it's contributing to your final look.

The first shader I built, with the help of a guide, was a selection circle. The theory is pretty easy. Take a radial gradient and power it to sharpen the edges. Then take a second gradient with a smaller radius and subtract it. Feed that into the emissive multiplied by a color and glow factor, and you're done. It's important to set up all of these values as parameters so they can be easily manipulated in material instances.

There's a upgrade to this material that I'd like to make: change the circle to be a dashed line that spins. I had a shower thought this morning on how to accomplish that. Keep in mind my material experience is practically zero, so there's a good chance this is not correct or ideal.

First I take the UV of the pixel I'm rendering and determine the angle of the vector it forms with the center of the texture. I then mod that by the angle of frequency for my dash. I then mod the original angle by X * Frequency where 1/X is the ratio of dash (so 2 means evenly dashed).

Conceptually, if the two mods are equal, draw black. If they're not equal, draw white. This essentially will create a pinwheel of black and white. I then subtract that from my circle prior to applying color and glow. I can accomplish this without a branch by subtracting the two mods and multiplying since the equal values will subtract to zero. I don't have to worry about multiplying the white with values above 1 since I clamp before applying color already.

So anyway, I think that will give me the look I want. I'll try to play later tonight with it.

The other material I want to make is for the effect when you click a tile. Upon clicking a tile, I want a box to appear with outlined glowy edges, a translucent body, and fading as it goes up.

I found a Liaret tutorial last night that builds a Tron material. This is a great start for what I want. The idea is to take a gradient texture, power it to sharpen, then rotate it for each side and apply. This makes a nice outline on the material. You the multiply be a glow factor and color, plus add parameters for glassiness and metal until you get the shine you're looking good for.

The next steps I'd make would be to set the opacity of the main body, possibly with a radial gradient. Then I'd make an opacity gradient based on the local height so that it blends out toward the top. A cube would have no top face.

That's the theory at least! Let's see how that goes.

Unreal

As I mentioned in the last post, I decided to work on this game in Unreal. Despite the explosion in popularity of Unity, I'd still argue that Unreal is the premiere AAA game engine out there. Tons of games use it, many developers can be hired with Unreal experience, and entire studios dedicate themselves to it. Now that Unreal has gone fully free, it can even compete for the indie and hobbyist mindshare.

That said, I know very little about it. I've fired it up here and there, especially when I worked on game tools, but I had zero practical experience with it.

It would've been very easy to develop this in Unity. I had already built a sort of tactics game for a game jam in Unity a few years back, and I'm comfortable with its paradigm. But if the point of this exercise was to stretch my wings, I would get a lot more by learning Unreal in the process.

Now that I'm a bit into this project, I can also say I'm so far very happy with this decision. The Blueprint Editor is surprisingly excellent, I'm actually having fun making materials, and having full access to engine code changes how I work and debug. There are also some easy engine components, such as pathfinding, that is changing how I was planning on building this game.

While I still stand by Unity's excellence, Unreal so far has shown me why it's been king for so long.

Why This Game

This past summer, I bought a ton of games on the Steam Sale, as one does. I hadn't played XCom's expansion pack yet, and since tactics games are on the top of my favorite genre list, I picked it up.
Almost immediately, I was inspired. When you stop and analyze what goes into these types of games, they're actually quite simple. That's not to take anything away from Firaxis -- XCom is a fantastic game where it's simplicity is one of its greatest assets. However, tactics games may be one of the more approachable games in terms of hobby game development.
So I decided to follow that inspiration and start noodling with my own tactics game for the purpose of learning. I decided to work in Unreal (more on that later) because I hadn't touched Unreal in about a decade and wanted to compare it to Unity.
Finally, like my last project, I wanted to blog about it so that I can reflect on what I'm learning and document the process. Perhaps someone will find it interesting?