Tag: Unity 3D

RPG Game Dev Weekly #2

Well, so far not so great for getting weekly posts on this! It’s probably better for me to aim to do these periodically and summarize the last week or so of work. Fewer commitments that way and it’s a bit more realistic for me to achieve. With that said, let’s dive into it!

Entity Filtering in an RPG

Our RPG has had some notion of entity filtering for a long time, but to understand the current state of filtering, it’s important to understand the two major sets of entities and components we have:

  • Game Objects + Behaviors: Everything in our RPG game world is represented as a “game object” and the properties/capabilities are captured by components called “behaviors”
  • Definitions + Generator Components: The content for our game is represented by “definitions” and the “generator components” are how we transform this information into “game objects” and “behaviors”

Because I heavily focused on our loot generation system early on, the focus for filtering was really around being able to select loot from “drop tables” (which have item definitions on them and associated with enchantment definitions). Early on it was a goal to ensure that loot generation and other game systems could have extremely complex situations handled, so we needed to be able to do things like generate loot given arbitrary game state. Additionally, this system needed to be fully extensible to support any game state we wanted to add in the future.

In what might seem to be an extremely contrived example, assume we want to generate item X when:

  • The player is level 50+
  • The current weather on the map is raining
  • The current time of day in the game world is night
  • The player has completed quest A, B, and C
  • The player is holding item Y
  • We are generating loot for killing enemy N

These conditions represent a filter that we need to execute, but I never realized until recently that the implementation of this is actually something I’ve started calling “bidirectional filtering”. This means that we’re running a query with a filter over a set of drop tables, but we provide along some state and the drop tables are filtering backwards on this state. Sound complicated? It was, especially before explicitly thinking of it as bidirectional filtering!

It can be more easily digested when thinking of it this way:

Provided Game State:

  • Current weather
  • Current time of day
  • Player (level and equipment in this example)
  • Quest status

Required Filter from Game:

  • Drop table ID matching enemy N

Using the above information, we select all drop tables matching the required filter from the game. Essentially, any drop table ID for enemy N. For each of the drop tables that match this specific ID, we then run THEIR filters the opposite direction on the game state! If a drop table had no specific filters on it, it would match right away. However, if it had a weather filter on it, it would need to match the provided game state weather.

Okay so that’s bidirectional filtering in our RPG, but this is what ALREADY existed! So what did we need? We actually just needed single direction filtering. Literally just standard querying of game objects. Half the battle of what was already in place!

If you’ve played games like Path of Exile or even Last Epoch, you’ll see indicators in the game that there are tags associated with different things (like skills, items, enchantments). If in our game we want to be able to query all items in a player’s inventory that are of type “axe” or all skills associated with “fire”, we need some way to filter our entities. And in this case, there’s no need for the entities to filter backwards like in bidirectional filtering!

We expanded our filtering system to support this now, which unlocks:

  • Skills that require certain item types
  • Skill prerequisites that aren’t just a skill ID
  • Advanced skill targeting
  • Enchantments that boost skill stats (damage, levels, etc…) that match a particular filter
  • Crafting / Alchemy (i.e. filtering on ingredients)
  • Item socket patterns (this was already in game, but we can do this declaratively instead of writing custom-coded plugins)
  • Restricting applying poisons or consumables to certain item types
  • … this list goes on and on!

RPG Movement Overhaul

This block of work is what chewed up most of my RPG development time the past few days. I was frustrated with my initial and seemingly failed implementation of A* for path finding. For anyone that’s gone through popular computer science algorithms, A* is a pretty straight forward algorithm for finding shortest possible paths. It’s really popular in games because it’s extremely efficient! But my take on it just wasn’t cutting it for our RPG, and it would often report that no paths were possible (which just wasn’t true)!

Our RPG has an explore mode and a combat mode, sort of like Pokemon. However, the combat is tactical, so it’s sort of like Final Fantasy Tactics with respect to that. Being a 2D tile-based game, having tile-restricted movement makes a lot of sense. However, early on I felt that having free-form movement in the explore mode felt really fluid and fun. There was no great reason our explore mode needed to be tile restricted. However, making this movement system decision complicated all of our tile-based movement by trying to re-use the same code.

So I did a thing that I find feels counter-intuitive as a programmer normally… I duplicated a bunch of code, one for supporting tile-based movement and the other for freeform. No more “common code” for this. From here, I found I could actually start correcting each movement system and tailoring it to do the right thing. I was hitting this blockage before because these really were two fully separate implementations of class that can support movement.

From there, I worked through my path-finding issues. I built out some visuals that can determine where the player can move, and used this to validate what I believed I was seeing in my unit tests. 2D stuff is easier to understand visually! The following is an example that shows a snag that I hit where our logic to check “can we move to this position” was incorrectly calculating the distance to that point. If the player has only 3 moves to make, why does it think it can get to the tile labeled 4?

The answer? It was doing birds-eye distance checks back to where the player was standing. Not going to work for our RPG! Instead, I was able to re-use part of the A* algorithm to calculate the distance as the algorithm progresses through neighboring nodes. I also needed to update A* to report the total distance in addition to the positions on the path. The result was consistent calculations between our valid walk points and the actual pathfinding algorithm. The next snapshot shows a small update to the visuals:

And at this point, it was really just about showing/hiding/updating the valid walk highlighting at the right times! So I figured I’d whip up a little video to show progress on that:

What’s Next In Our RPG?

We’ve been making some awesome progress on our RPG. We’re starting to look into random dungeon generation, and I’ll probably try to find something more architectural to tackle. I find I burn out fast when I spend too long on things that feel strictly visual or like I’m polishing things. In this case, the movement part of combat is critical so it needed to get done. But reflecting on all of the changes there was nothing fundamentally changed in our game to accomplish this.

Additionally, I’m going to start doing a better job of adding more content. I’ll be adding in item affixes for item generation, prefixes/suffixes item name creation, and ideas for items that can drop. I don’t think we fully have the components required to define all the items I’d like to make, so I’ll start just by recording my thoughts in a consistent format.

Overall, we’re moving in the right direction! But there’s no denying making an RPG is a ton of work!


RPG Development Progress Pulse – Entry 1

Progress Pulse

Progress Pulse – Entry 1

For the first entry in the progress pulse series I’ll touch on some things from the past week or so. There’s been a lot of smaller things being churned in the code base, some of them interesting, and others less interesting so I want to highlight a few. As a side note, it’s really cool to see that the layout and architecture is allowing for features to be added pretty easily, so I’ll dive a bit deeper on that. Overall, I’m pretty happy with how things are going.

Unity3D – Don’t Fight It!

I heard from a colleague before that Unity3D does some things you might not like, but don’t try to fight it, just go with it. To me, that’s a challenge. If I’m going to be spending time coding in something I want it to be with an API that I enjoy. I don’t want to spend time fighting it. An example of this is how I played with the stitching pattern to make my Autofac life easier with Unity3D behaviours.

However, I met my match recently. At work, we were doing an internal hackathon where we could work on projects of our choosing over a 24 hour period, and they didn’t have to be related to work at all. It’s a great way to collaborate with your peers and learn new things. I worked on Macerus and ProjectXyz. I was reaching a point where I had enough small seemingly corner-case bugs switching scenes and resetting things that I decided it was dragging my productivity down. It wasn’t exciting work, but I had to do something about it.

After debugging some console logs (I still have to figure out how to get visual studio properly attached for debugging… Maybe I’ll write an article on that when I figure it out?) I noticed I had a scenario that could only happen if one of my objects was running some work at the same time… as itself? Which shouldn’t happen. Basically, I had caught a scenario where my asynchronous code was running two instances of worker threads and it was a scenario in my game that should never occur.

I tried putting in task cancellation and waiting into my unity game. I managed to hang the main thread on scene switching and application close. No dice. I spent a few hours trying to play around with a paradigm here where I could make my ProjectXyz game engine object run asynchronously within Unity and not be a huge headache.

I needed to stop fighting it though. There was an easier solution.

I could make a synchronous and asynchronous API to my game engine. If you have a game where you want the engine on a thread, call it Async(). Unity3D already has its own game engine loop. Why re-invent it? So in Unity3D, I can simply just call the synchronous version of the game engine’s API. With this little switch, suddenly I fixed about 3 or 4 bugs. I had to stop fighting the synchronous pattern with my asynchronous code.

The lesson? Sometimes you can just come up with a simple solution that’s an alternative instead of hammering away trying to fix a problem you created yourself.

DevOps – Build & Copy Dependencies

This one for me has been one of my biggest nightmares so far.

The structure of my current game setup is as follows:

  • ProjectXyz.sln: The solution that contains all of my back-end shared game framework code. This is the really generic stuff I’m trying to build up so that I can build other games with generic pieces if I wanted to.
  • Macerus.sln: The game-specific business logic for my RPG built using ProjectXyz as a dependency. Strictly business logic though.
  • Macerus Unity: The project that Unity3D creates. This contains presentation layer code built on Macerus.sln outputs and ProjectXyz.sln outputs.

I currently don’t have my builds set up to create nuget packages. This would probably be an awesome route to go, but I also think it might result in a ton of churn right now too as the different pieces are constantly seeing churn. It’s probably something I’ll revisit as things harden, but for now it seems like too much effort given the trade off.

So what have I been doing?

  • I build ProjectXyz.sln.
    • The outputs go into this solution’s bin folder
  • I build Macerus.sln
    • There’s a prebuild step that copies ProjectXyz dependencies over
    • The outputs go into this solutions bin folder
  • I use a custom in-editor menu to copy dependencies into my Unity project
    • This resets my current “dependencies” asset folder
    • The build outputs form the other solutions are copied over
  • I can run the project with new code!

This is a little tedious, sure. But it hasn’t been awful. The problem? Visual studio can only seem to clean what it has knowledge about.

I’ve been refactoring and renaming assemblies to better fit the structure I want. A side note worth mentioning is that MUCH of my code is pluggable… The framework is very light and most things are injected via Autofac from enumerating plugin modules. One of the side effects is that downstream dependencies of ProjectXyz.sln (i.e. Macerus.sln) have build outputs that include some of the old DLLs prior to the rename. And now… Visual Studio doesn’t seem to want to clean then up on build. So what happens?

Unity3D starts automatically referencing these orphaned dlls and the auto-plugin loading is having some crazy behaviour. I’ve been seeing APIs show up that haven’t existed for weeks because some stale DLL is now showing up after an update to the dependencies. This kind of thing was chewing up HOURS of my debugging time. Not going to fly.

I decided to expand my menu a bit more. I now call MSBuild.exe on my dependency solutions prior to copying over dependencies. This removes two completely manual steps from the process I also purged my local bin directories. Now when I encounter this problem of orphaned DLLs, my single click to update all my content can let me churn iterations faster, and shorten my debugging time. Unfortunately still not an ultimate solution to the orphaned dependencies lingering around, but it’s better.

The lesson learned here was that sometimes you don’t need THE solution to your problem, but if you can make temporarily fixing it or troubleshooting it easier then it might be good enough to move forward for now.


Stitching – Combining Unity3D And Autofac

Stitching - Combining Unity3D And Autofac

Before We Talk About Stitching…

In Unity3D, the scripts we write and attach to GameObjects inherit from a base class called MonoBehaviour (and yes, that says Behaviour with a U in it, not the American spelling like Behavior… Just a heads up). MonoBehaviour instances can be attached to GameObjects in code by calling the AddComponent method, which takes a type parameter or type argument, and returns the new instance of the attached MonoBehaviour that it creates.

This API usage means that:

  • We cannot attach existing instances of a MonoBehaviour to a GameObject
  • Unity3D takes care of instantiating MonoBehaviours for us (thanks Unity!)
  • … We can’t pass parameters into the constructor of a MonoBehaviour because Unity3D only handles parameterless constructors (boo Unity!)

So what’s the problem with that? It kind of goes against some design patterns I’m a big fan of, where you pass your object’s dependencies in via the constructor. You can read my little primer about constructor parameter passing, dependency injection, and Autofac to learn more.

The challenge I’m trying to address is that my non-MonoBehaviour classes are all going to be setup to use constructor parameter passing as much as possible but the MonoBehaviour classes cannot. So I’d like to reduce the amount of disjoint coding styles as much as I can and make the MonoBehaviour classes feel like the rest of my stuff!

What Is “Stitching”?

Here’s where this little pattern I created called “Stitching” comes into play. Stitching involves using a class referred to as a Stitcher that’s single purpose is to take parameters in via a constructor, and wire them up to either public properties or public fields (but I REALLY suggest using properties) on the MonoBehaviour that we instantiate through the GameObject.AddComponent() API.

The code ends up looking something like this:

public sealed class MyComponentStitcher
{
  private readonly IDependency _dependency;

  public MyComponentStitcher(IDependency dependency)
  {
    // take in our dependencies and save them as fields
    _dependency = dependency;
  }

  public MyComponent Stitch(GameObject gameObject)
  {
    // create the MonoBehaviour instance using the Unity3D API
    var componentInstance = gameObject.AddComponent<MyComponent>();

    // wire up our dependencies (assign our field to a property on the component)
    componentInstance.Dependency = _dependency;

    return componentInstance;
  }
}

Where you can see that:

  • We inject dependencies into the Stitcher’s constructor
  • We call AddComponent() with the component type we want on the object we want to “stitch” to
  • We mutate the component
  • We return the newly made component

How Do We Use Stitching In Practice?

Now that we see the pattern for a how a Stitcher works, how do we actually use Stitching in practice? Let’s start by using another example:

public sealed class SomeClass
{
  private readonly IMyComponentStitcher _stitcher;

  public SomeClass(IMyComponentStitcher stitcher)
  {
    _stitcher = stitcher;
  }

  public void MyMethod()
  {
    // create a new Unity3D game object
    var gameObject = new GameObject("My Game Object");

    // "stitch" our 
    var myComponent = _stitcher.Stitch(gameObject);

    // we can use some information that would have been injected into the constructor
    // this should print the injected value
    Debug.Log(myComponent.InjectedInfo);
  }
}

From this, you can see that:

  • We have a class called MyClass following our constructor parameter passing paradigm
  • The method MyMethod()
    • Creates a new game object
    • Adds a MyComponent instance to our game object by calling the Stitch() method
    • Using our imagination and the example above, pretend our Stitcher implementation takes a parameter in its constructor to assign to the InjectedInfo property of of MonoBehaviour
  • Logs out the value of the InjectedInfo property found on our newly created instance

So What Makes Stitching Better?

You might feel like this is extra code right now, but this is where the power of Autofac comes into play. You can read my article about using Autofac with Unity3D for more information.

By creating a Stitcher, we can register it to our Autofac container. The Autofac container will then resolve any dependencies that our Stitcher requires for us. The net effect of this is that when we Stitch MonoBehaviours to GameObjects, we get what feels like Autofac resolving dependencies for our MonoBeaviours. We don’t need to mutate MonoBehaviour fields/properties all over our code to assign the dependencies the script needs to use. Instead, we treat the Stitcher class like a factory for our MonoBehaviour.

So in summary:

  • Stitching allows us to leverage Autofac for instantiating MonoBehaviours
  • Stitcher classes essentially become a factory class for our MonoBehaviours (with the side effect that they *must* mutate the GameObject that we need to attach the MonoBehaviour to)
  • Allows assignment of MonoBehaviour fields/properties for initialization to exist in one spot so we can put the bad object mutating code in one spot that feels hidden

Using Autofac With Unity3D

Autofac With Unity

Why Consider Using Autofac With Unity3D?

I think using a dependency injection framework is really valuable when you’re building a complex application, and in my opinion, a game built in Unity is a great example of this. Using Autofac with Unity3D doesn’t need to be a special case. I wrote a primer for using Autofac, and in it I discuss reasons why it’s valuable and some of the reasons you’d consider switching to using a dependency container framework. Now it doesn’t need to be Autofac, but I love the API and the usability, so that’s my weapon of choice.

Building a game can result in many complex systems working together. Not only that, if you intend to build many games it’s a great opportunity to refactor code into different libraries for re-usability. If we’re practicing writing good code using constructor dependency passing with interfaces, then things really start to line up in favour of using a dependency injection framework.

Getting Set Up

At the end of my autofac primer article, I provided a link to the Nuget package for Autofac. You’ll notice that there’s a version dependency for .NET 4.5, so if you’re not sure how to get Unity3D working with .NET 4.5, you’ll want to check this other article of mine. It’s very simple, so don’t worry!

Unity3D, at the time of writing this and using version 2018.1.1f1, there’s no native Nuget package support. I haven’t spent too much time investigating alternatives, but not to worry. I’ll explain a quick work around. The TL;DR is that we need the binaries from the Nuget package to be loaded up by Unity3D and we’ll miss out on the Nuget-y-ness for now. Not a huge deal since we’ll still have Autofac support!

  • Start a new Visual Studio C# project
    • Ensure that the .NET framework is at least 4.5 and more specifically, the version of .NET that you’d like to use in your Unity3D project
  • Open up the Nuget package manager in Visual Studio
  • Search for Autofac online in the package manager (it should be the same one I referred to above!)
  • Add this package to your visual studio project
  • Compile this visual studio project
  • Assuming you built in debug, go to the output folder (which is in bindebug if you didn’t change anything from default)
  • In the output folder, you’ll find “Autofac.dll”
  • You’ll want to add this into your Unity3D project’s “Assets” folder
    • I like nice folder hierarchies, so I’d suggest making a subfolder inside of “Assets” called “Third Party” or “Dependencies”… Something that’s obvious for what it means
    • Drop in the Autofac.dll file into there
  • Unity3D will add a corresponding *.meta file to go along with this

Great! We’re almost there. If you want to test it out, open up a script from Unity3D. This will launch a new Visual Studio instance if you haven’t opened up one for your Unity project yet. At the very top of your file you should be able to type:

using Autofac;

And the namespace should resolve! If not, sometimes this takes Unity3D a refresh operation to regenerate the project file on disc, so if you switch to Unity3D again and it starts doing some processing, switching back to Visual Studio might resolve this.

Using Autofac With Unity3D

Up until this point, we’ve proven we can reference Autofac. I’m not going to explain all the ins and outs for how you’ll want to organize your Autofac initialization in this post, but we can walk through a quick example!

  • Pick a game object on your scene
  • Add a new C# script to it
    • Call it whatever you’d like, but make sure you know how to open it
  • … now go open it in Visual Studio 🙂
  • We should have a method in there called Start()
    • If not, feel free to add it:
    • private void Start()
      {
        // TODO: we'll add stuff here
      }
  • Let’s use this code to make a new class that you can put inside the same script file for now:
    • public sealed class MyAutofacObject
      {
      
        public MyAutofacObject()
        {
          Debug.Log("Constructor for our object!");
        }
      
        public void DoThing()
        {
          Debug.Log("Test!");
        }
      }
  • Inside this start method, let’s try doing something VERY simple to prove Autofac works!
    • var containerBuilder = new Autofac.ContainerBuilder();
      containerBuilder.RegisterType<MyAutofacObject>().SingleInstance();
      
      var container = containerBuilder.Build()
      var instance = container.Resolve<MyAutofacObject>();
      
      instance.DoThing();

Now if we run our game, here’s what should happen:

  • The script attached to the game object should run
  • The Start() method on the script should be the first thing that goes
  • The code we added should:
    • Make a new ContainerBuilder
    • Register our MyAutofacObject type as a single instance
    • Build the container
    • Resolve an instance of our type
    • Log out a message saying it’s in the constructor
    • Log out a message that says Test!

And voila! It’s simple, but it should demonstrate that Autofac is working!

Next Steps

This is a very contrived example of using Autofac with Unity3D. It proves that the code can be run, but it doesn’t do too much that’s useful. There are going to be many considerations you’ll need to make for how you want to organize your dependencies, register your classes/interfaces, and so on.

I’ll continue to add into this Unity3D series of posts, but let me know what else you’d like to know about using Autofac with Unity3D! I’d be happy to try and answer, or even create an article to help explain.

Thanks!


Unity3D and .NET 4.x Framework

Unity

Unity3D Default .NET Framework

I recently wrote that I wanted to start writing more Unity3D articles because I’m starting to pick up more Unity3D hobby work. It felt like a good opportunity to share some of my learnings so that anyone searching across the web might stumble upon this and get answers to the same problems I had.

Unity3D as of 2018.1.1f1 (which is the version I’m currently using), still defaults to using .NET 3.5 as the framework version. Nothing wrong with that either. I’m sure there are reasons that they have for staying at that version, probably because of Mono and cross platform reasons if I were to guess, so I’m not complaining. For reference, this setting in Unity3D is referred to as “Scripting Runtime Version”. So if you’re googling more about this later, that’s what Unity calls it. For the libraries I was building to use as a game framework, I was using .NET 4.6 and discovered I was going to have a challenge getting them working in Unity3D.

If you want to see what your setting is currently set at, you need to check out the “Player” settings. This was kind of buried in the UI for me so I didn’t know it was a thing that could be adjusted. In Unity3D 2018.1.1f1, click Edit->Project Settings->Player. Here’s what it looks like:

Unity3D - Player Settings

In Unity, click Edit->Project Settings->Player

From there, you’re going to get “PlayerSettings” in your Inspector tab. You’ll need to expand the “Other Settings” to see your scripting runtime version:

Unity3D - Other Settings

“Other Settings” accordion control in PlayerSettings Inspector tab

Once you expand that, here’s the setting you’re interested in:

Unity3D - Scripting Runtime Version

Scripting Runtime Version – The selected .NET version Unity will use

Switching Unity3D to .NET 4.x

Now that you know where the setting is… it’s pretty easy 🙂

Unity3D - Scripting Runtime Version

Use the dropdown to pick which .NET framework version you’d like to use.

You can read more about this setting over at the official Unity3D documentation pages:

https://docs.unity3d.com/Manual/ScriptingRuntimeUpgrade.html

This outlines what things are affected in different platforms and scenarios so YOU SHOULD READ IT to understand what will change.

Hope that makes things a bit easier for you to get up and running with .NET 4.x assemblies in Unity3D!


API: Top-Down? Bottom-Up? Somewhere in the Middle?

A Quick Brain-Dump on API Desgin

I’ll keep this one pretty brief as I haven’t totally nailed down my thoughts on this. I still thought it was worth a quick little post:

When you’re creating a brand new API to expose some functionality of a system, should you design it with a strong focus on how the internals work? Should you ignore how internals work and make it as easy to consume as possible? Or is there an obvious balance?

I find myself trying to answer this question without ever explicitly asking it. Any time I’m looking to extend or connect systems, this is likely to come up.

Most Recently…

Most recently I started trying to look at creating an API over AMQP to connect my game back-end to a Unity 3D front-end. I had been developing the back-end for a little while now, so I had a pretty good idea for how things needed to work from that perspective. The front-end? Not so much really. I knew some basic actions that I was considering, so I tried coding up an early API for them.

A lot of my focus was around how I was going to implement the code on the back-end to make this API work. It resulted in some of the API calls looking a little bit gross. But the idea was that if I settled on an API that would make the back-end easy to implement, I could get it up and running faster.

After a little while, I feel like my API isn’t getting any cleaner from a consumer perspective, and funny enough, it’s not actually as easy to implement as I was hoping on the back-end. Which had me reflect on a work example…

Once Upon a Time at Work…

Well, it was only a couple of months ago, really. I was working with a colleague on integrating a new system into an existing code base. We decided we wanted to approach the API problem from a consumer perspective. We said “let’s make this as easy to call and use as possible so that people ACTUALLY want to use it”.

We set out with this mission, and created a pretty simplistic API. The challenge? There was a lot of heavy lifting and a bit of voodoo going on behind the scenes. But you know what? We hid the magic in one spot of the code (instead of having ugly stuff scattered all over the code base) and it ended up being a very usable API.

So…

So does this consumer-first, top-down approach to API design always work? I’m not sure. Some similarities/differences in the scenarios:

  • In my current situation, I have a back-end implemented and very minimal code implemented on the caller side. In the work example, we had nothing implemented on the back-end, and a ton of code implemented where the caller side would be.
  • In both examples, at least one of the caller side or back-end side was reasonably well understood. For my game, the back-end was pretty well understood. For work, the caller side was pretty well understood and we had experience with what we’d call a “failed’ back-end implementation (that we were actually setting out to redesign).
  • The work example was a relatively small subset for an API, but the game example was about to be a very specific implementation that I’d need to adapt into a pattern for all messaging in my AMQP system

So there’s a few things to consider there. I think I’m at the point in my game where I’d like to revisit how I’m forming this API and try it from a client-first perspective. Now that I know some of the catches, maybe I’ll shed some new light!

How do you approach API design?


Multiple C# Projects In Your Unity 3D Solution

Unity

Problem: Visual Studio and Unity Aren’t Playing Nice!

UPDATE: This is for older setups with Visual Studio and Unity. You may want to look at Assembly Definitions.

I just started poking around in Unity 4.6 and I’ve been having a blast. I’ve made it to the point where I want to actually start hammering out some code, but I came across a bit of a problem: I want to start leveraging other projects I’ve written in my Unity solution while I’m in Visual Studio, and things are blowing up. So, what gives?

Okay, so let me start by explaining why I want to do this. I understand that if I’m making a simple game, I should have no problem breaking out my unity scripts into sub folders and organizing them to be nice and pretty. The problem I’m encountering is that I have existing projects under source control and I don’t want to copy and paste all of the code as scripts into my Unity folder. I also want to be able to create re-usable code for my future games, so I’d like to start breaking things out into libraries as I see fit.

So, if you’ve been playing around in Unity for a bit, you might say “Oh, well you’re a dummy! Unity can totally leverage your C# DLLs once you drop them into your asset folder”! And you’d be 100% correct. But that’s not the workflow I want.

The underlying problem here is this: Unity will re-write your solution and project file when you flip between Unity and Visual Studio. But I’m sure they have it that way for a reason.

The Goal: Visual Studio and Unity Should… Play Nice!

My ideal state would be something like this:

  • Work in visual studio as much as I’d like to new projects to my solution, and reference them accordingly
  • Flip back and forth from Unity and Visual Studio without having to reset things to compile/run again
  • Build from visual studio and have things end up in the right spot… NOT copy DLLs
  • Not copy+paste my entire project(s) already under source control elsewhere

Is this something that can be achieved though? I was pretty determined that I should be able to do *something* to have this working. Could I get it perfect? I wasn’t sure… But I knew I could make it better.

The Solution: Give and Take with Unity

My *almost* perfect sution, which I’ll walk you through, is this: Leveraging Visual Studio tools for Unity, modify the Unity solution as you see fit and use directory junctions (symlinks) to the build output directories of other projects.

  1. Let’s get Visual Studio tools for Unity installed. Visit that link and download the version that you need for the version of Visual Studio that you use. After installing, I opened up my project within Unity and I had to import the Visual Studio Tools package.Import Package
    After selecting this menu item, I was presented with a dialog for picking the items to import. I left it as is.Import Package2After importing these items, I could see that Unity had successfully added these entries under my Assets folder. Okay, now we’re getting somewhere. Next up, I wanted to configure Unity to not modify my solution every time I go back and forth from Unity to Visual Studio. This is the part that kills whether or not I’ve added projects to my solution. For me, it’s critical to have code I’m working on immediately accessible so that I can jump back and forth between projects. Lucky for us, this part is pretty easy. Go to the menu to access your new Visual Studio Tools menu item:

    VS Tools Configure
    Selecting “Configuration” opens up a really simple dialog. Let’s make sure “Generate solution file” is unchecked! It’s that easy.

    VS Tools Configure2
    Once we have all of this setup, we should be able to go into Visual Studio and add other projects to our solution.

  2. The one thing that I *could not* get this solution to do is have Unity leave my main game project alone in Visual Studio. As a result, the rest of this walk through is allowing us to play by Unity’s rules. Unity is good at magically referencing all of the managed DLLs that you include within your assets folder. If you drop DLLs somewhere within “Assets” and switch to Visual Studio, Unity will likely have modified your main project to reference this DLL.My next step was creating a spot where I wanted to drop the build outputs of my extra projects I wanted to reference. In my Visual Studio solution, I have my original game project and some newly added projects I want to build from source. In Unity, I wanted these to end up in “Assets/Dependencies/bin”. No problem. Let’s make that folder structure (or your equivalent if you don’t like my naming):Bin Dependencies
    The next part is probably the “trickiest” part because it’s… well… unusual. You could technically stop here and manually copy DLLs back and forth, but I’m not about that life. I want things to happen automatically. For this, we’re going to use junction points. Browse to your newly created folder in an administrator command prompt. I say administrator because only certain users have permissions to create junction points. Your non-admin user might, but this is my “safe” way of instructing you. On the command prompt, we’re going to use “mklink” to create a junction. The command is “mlkink /D /J <NAME_OF_YOUR_PROJECT> <RELATIVE_PATH_TO_YOUR_PROJECT>”. For example, if you had a C# project you wanted to reference that was “MyCoolLibrary.csproj” and was located in the directory above your Unity project, you might use the command “mlkink /D /J MyCoolLibrary “……..MyCoolLibrarybindebug””. Note that I used two dots to go back up a directory several times (since we’re inside of AssetsDependenciesbin and want to get outside of our Unity project). you should get a success message when your junction is created.

    Repeat this step for as many extra projects as you want to include. You can always come back and add more projects this way too, or remove the junctions if you don’t want to include a project anymore.

    At this point, you’re technically done. If you build from Visual Studio, you should have your other projects’ DLLs end up in your Unity folder, and your main game project will be updated by Unity to reference these now!

  3. But… You’re not done if you use source control for your Unity project and have separate source control on your other projects. The scary thing here is that usually we don’t want our build outputs to be stored in source control… But if we do nothing else, your source control system will likely want to include the newly created “AssetsDependenciesbin” folder and any of the contents you’re building into there. I just modified my git ignore file (I’m sure there’s an equivalent for SVN or other source control) to exclude the contents of “AssetsDependenciesbin”.The reason I didn’t excluded dependencies all together is because I can add other folders and DLL references here that I don’t want to build (like… the normal way). This gives me the flexibility of building the projects I want to control and still be able to just reference other pre-built DLLs!

Summary

In three easy steps, you should be able to use Unity, Visual Studio, and multiple projects in one solution in a what-feels-like-normal way. Because there’s still some dynamic stuff going on with Unity updating your main project, you might find the odd time you need to build twice to fix up compilation problems. I’ve seen this happen maybe once or twice so far, but otherwise it feels like normal. It’s also  important to note that you can’t escape the Unity project updating… don’t add references to your main project manually. That’s what that “AssetsDependencies” folder is for that we made.

Here are a few shots of what my setup looks like (proof that it works):

Solution Explorer

Unity Dependencies

And of course… it’s not the perfect solution. There’s still these things:

  • Unity gets mad at you for using junctions within your project. It actually tells you not to do this because you can mess things up. It’s working awesome for me right now though… So I’m going to just ignore this warning.
  • Remember step 3 where we ignored the AssetsDependenciesbin location in git? This actually ignored your junction points you created too. As a result, anyone else who clones your code will need to create junctions too. I’m working solo, so I’m not too worried about this step… But it’s definitely something that should be fixed up (again, I’m sure it’s doable, but I’m in no rush).

Hope that helps you feel more at home in Unity and Visual Studio! It certainly made it nicer for me.


  • Copyright © 1996-2010 Dev Leader. All rights reserved.
    Jarrah theme by Templates Next | Powered by WordPress