Hey guys!
Attached to this post, you’ll find the projects and resources used on today’s lecture:
CPH IT University Unity course files
Hey guys.
For those of you not attending; Joe Robins and I are running a Unity course at the IT University of Copenhagen this week. Given the highly mixed crowd, the our lectures range from absolutely no Unity knowledge required to at least some understanding needed for full potential unlock.
During these lectures, we create projects for demoing the focus of the lecture. These are either pre-prepared or built on stage and often get modified based on requests from the audience.
So now that we are all on the same track:
Attached to this post you should find three zip files of the content we have gone through in the classes so far. This is their state post responding to questions, so some of the stuff demoed earlier on might differ slightly.
Behave 1.2 released
That’s right! I know it’s only been … uh … well less time than I usually take to get it together and push out a new version. But since I was a bit on a roll with the release of Behave 1.1 not too long ago, and given that a last minute bug has snuck into that release, I decided to push on.
So here we are – new version out in a jiffy. What’s new you say? This is what’s new:
1.2:
- Fixed release building.
- Added the priority selector, introducing the API points:
- int IAgent.SelectTopPriority (Tree sender, params int[] IDs);
- enum BL[LibraryName].PriorityType { PriorityName, ..., Unknown };
- Added support for branch contexts, introducing the API points:
- enum BL[LibraryName].ContextType { ContextName, ..., Unknown };
- int Tree.ActiveContext { get; }
- Changed IAgent interface:
- Tick (bool init, Tree sender) -> Tick (Tree sender, bool init)
- Added "Select asset" button to the standard inspector.
- Interface polish.
I’ll make sure to update the documentation to reflect the new API changes and yes, more is coming on that front.
And yes I will be releasing a new demo project. I just wanted to make it something different, and nice for you guys, y’know? So hang in there.
Video: Behave – starting from scratch
I just finished uploading a new video for the Behave documentation section. It is a brief general introduction to the Behave authoring environment and shows you how to get up and running with Behave from a blank project.
Behave runtime documentation updated
It is no secret that the Behave documentation has been in a quite bad state for a while. With this release I intend to correct that and as a starting point, I have moved the outdated documentation offline and replaced it with documentation of the Behave runtime. Rest assured that I will be adding documentation on the authoring environment as well.
Go check it out: http://angryant.com/behave/documentation
Behave 1.1 released
Hello reader. It’s been quite a while since my last conf… post.
Yea sorry about that. Busy, busy, but then again I suppose most had probably figured that one out. However, I have had a bit of time here and there over the last few months to polish away on Behave and keep it compatible with Unity 3 as it developed.
A lot of this keeping up to date work at times resulted in some good old fashion rewrites – like the entire asset handling and parts of the compiler. This is probably not very interesting to you, but it is quite so to me as it has allowed me to restructure internally in ways that make the system as a whole more flexible and ready for change and additions.
One of those additions which I did sneak in next to the polish and updating is a new debugger. The in-game debugger has been thrown out in favour of one living in your editor environment. YAY! No really, yay. You will like this and not just because I say so. Ah and as much requested this one actually dives into sub-trees, making it actually quite useful compared to its predecessor.
Oh and the compiler runs on Windows too now. And I also shaved off some cruft in the action/decorator handler syntax, making Ricardo extra happy.
I will be putting up some short documentation for Behave 1.1 shortly, but if you still haven’t decided to download yet, here is a short teaser on the new debugger: This text is a link to a movie file. Click it. It will be fun!
Enough blabbering though. The package is available in the download section and the changelog is right here:
- Made compatible with Unity 3.0 - including ensuring that the 2.5-2.6.1 bug preventing compilation on Windows is fixed on the Unity side.
- UI tweaks and polish.
- Added the option to have return values of nodes be inverted.
- Fixed compiler bug when facing sequence or selector with only one child node.
- Renamed Library.Tree -> Library.InstantiateTree.
- Added Tree.Tick () and Tree.Reset () methods using the IAgent instance given at instantiation of the tree.
- Removed the abstract Library class.
- Changed generated library class:
- Trees -> TreeType.
- Actions -> ActionType.
- Decorators -> DecoratorType.
- Tree InstantiateTree (int, IAgent) -> static Tree InstantiateTree (TreeType, IAgent)
- int TreeID (Tree) -> static TreeType Type (Tree)
- bool IsAction (int) -> static bool IsAction (int)
- bool IsDecorator (int) -> static bool IsDecorator (int)
- Upped editor performance.
- New asset structure change with automatic import of Behave 1.0 assets.
- Changed action and decorator handlers. These are now the handlers mapped:
- public BehaveResult Init[Name][Action/Decorator] (Tree sender, string stringParameter, float floatParameter, IAgent agent, object data);
- public BehaveResult Tick[Name][Action/Decorator] (Tree sender, string stringParameter, float floatParameter, IAgent agent, object data);
- public void Reset[Name][Action/Decorator] (Tree sender, string stringParameter, float floatParameter, IAgent agent, object data);
- public BehaveResult Init[Name][Action/Decorator] (Tree sender);
- public BehaveResult Tick[Name][Action/Decorator] (Tree sender);
- public void Reset[Name][Action/Decorator] (Tree sender);
- public BehaveResult [Name][Action/Decorator] {get; set;}
- Added support for collection duplication.
- Moved debug rendering into the editor with its own dedicated debugger window, including actor listing.
- Debugger now renders active sub-trees as well.
Oh and if you are upgrading a previous Behave install in a project, please see Readme.txt for details on snags you might hit and how to solve the whole thing in 4-5 steps.
Ah and one more thing: Behave 1.1 removes the “only for non-commercial work” clause from the license.
Have fun! And remember to tell me about all your awesome projects!
FAFF cleanup: Sketch
As some of you might have read, at Unity we have a thing called FAFF – very much the same as Google and other IT businesses are doing. It generally lets you step out of the bit stream for a day and just, during work hours, go with whatever crazy idea(s) you’ve been throwing around.
Some of these ideas are pushed into the product later and others are just filed under “something to play with when bored” and “now I can stop wondering about that”. Sketch was a micro FAFF project I just remembered I had filed under “this was fun” and then forgot all about. Since then I’ve continued work on other projects and started new ones – in all likelihood I’ll not return to this project.
So I figured I’d push it to github and let you guys take it for a spin. If nothing else, it’s a nice demo of what you can do with Unity editor scripting.
The idea of Sketch is to have simple tools inside the Unity editor to modify meshes in your assets. My goal with the project was never to turn Unity into a mesh authoring environment, but rather to give people an extra tool for rapid prototyping.
So what’s in there now? The simplest I could think of: Triangle selection and movement.
- Workflow:
- Go to the GameObject->Create Other menu and click Sketch Cube.
- With the cube selected, click a triangle and with the handle that appears, drag it around to modify the mesh.
- GOTO 1.
Alternatively, you could drag in your own mesh from the Assets folder (make sure that it generates a mesh collider in its import settings) and attach the Sketch script to it.
- NOTICE: Sketch modifies the imported asset. This means that:
- If you modify a some of the basic geometry meshes (such as GameObject->Create Other->Cube), the changes will apply to all cubes until editor relaunch.
- If the geometry you’re modifying is based on an imported 3D asset, reimporting it will mean you loose your changes.
Structure-wise, Sketch consists of two components: A MonoBehaviour (Sketch/Sketch.cs) and a custom inspector (Sketch/Editor/SketchEditor.cs). The purpose of the MonoBehaviour is merely to do some bookkeeping and provide utility functions (it will even destroy itself at runtime) while the custom inspector holds the logic for doing the modifications.

Woah. That’s a lot of talk. Here’s the repository – go nuts: http://github.com/AngryAnt/Sketch
Building a menu of delegates and enums
I like delegates. I also like enums. Furthermore, I happen to be part of a small group of people who actually enjoy the immediate mode GUI system in Unity. And I want you to like it too
So – menus. After having observed quite a few very funky approaches, in the IRC channel, to building main menu functionality and giving advice in there, I decided to sow together those ideas into a short example.
The main idea here is to be able to build and manage a menu system quickly and easily. This line adds a new submenu to the system – designated MyMenuState and implemented in the OnMyMenuGUI method:
m_Menus [MenuState.MyMenuState] = OnMyMenuGUI;
Notice that since we’re using delegates, the GUI method needn’t be implemented in the same script and could even live on an entirely different GameObject. Why is this so clever (besides enums and delegates being cool)? Because managing and switching between menus set up like this is insanely easy. This is the central GUI method for the menu system:
{
m_Menus [m_CurrentState] ();
}
And this is GUI code inside a menu GUI method for switching to a different submenu:
m_CurrentState = GUILayout.Button ("Credits") ? MenuState.Credits : m_CurrentState;
So there. Enough talk. Have some example code:
public class Menu : MonoBehaviour
{
delegate void OnGUIImplementation();
{Main,Settings,Credits};
public struct Settings
{
public bool m_ThisSetting, m_ThatSetting, m_TheOtherSetting;
};
static Vector2 m_StandardMenuSize = new Vector2 (200.0f, 300.0f);
static string m_LogoURL = "http://download.unity3d.com/images/top-menu/mm_unity_icon.png";
static Texture2D m_Logo = null;
private MenuState m_CurrentState = MenuState.Main;
private Dictionary<MenuState, OnGUIImplementation> m_Menus;
private Settings m_Settings;
{
m_Menus = new Dictionary<MenuState, OnGUIImplementation> ();
m_Menus [MenuState.Main] = OnMainMenuGUI;
m_Menus [MenuState.Settings] = OnSettingsGUI;
m_Menus [MenuState.Credits] = OnCreditsGUI;
StartCoroutine (GetLogo ());
}
{
WWW www = new WWW (m_LogoURL);
yield return www;
if (www.error == null)
{
m_Logo = www.texture;
}
}
{
m_Menus [m_CurrentState] ();
}
{
GUILayout.BeginArea (new Rect ((Screen.width - m_StandardMenuSize.x) * 0.5f, (Screen.height - m_StandardMenuSize.y) * 0.5f, m_StandardMenuSize.x, m_StandardMenuSize.y));
GUILayout.BeginVertical (GUI.skin.GetStyle ("Box"));
GUILayout.Label (title, GUI.skin.GetStyle ("Box"));
}
{
Color color;
GUILayout.BeginHorizontal ();
GUILayout.FlexibleSpace ();
color = GUI.color;
GUI.color = Color.grey;
GUILayout.Label ("My game version 2.4X");
GUI.color = color;
GUILayout.FlexibleSpace ();
GUILayout.EndHorizontal ();
GUILayout.EndVertical ();
GUILayout.EndArea ();
}
{
BeginStandardMenu ("Main menu");
if (m_Logo != null)
{
GUILayout.BeginHorizontal ();
GUILayout.FlexibleSpace ();
GUILayout.Label (m_Logo);
GUILayout.FlexibleSpace ();
GUILayout.EndHorizontal ();
}
if (GUILayout.Button ("New game"))
{
Application.LoadLevel ("Level one");
}
m_CurrentState = GUILayout.Button ("Settings") ? MenuState.Settings : m_CurrentState;
m_CurrentState = GUILayout.Button ("Credits") ? MenuState.Credits : m_CurrentState;
GUILayout.FlexibleSpace ();
EndStandardMenu ();
}
{
BeginStandardMenu ("Settings");
m_Settings.m_ThisSetting = GUILayout.Toggle (m_Settings.m_ThisSetting, "This setting");
m_Settings.m_ThatSetting = GUILayout.Toggle (m_Settings.m_ThatSetting, "That setting");
m_Settings.m_TheOtherSetting = GUILayout.Toggle (m_Settings.m_TheOtherSetting, "The other setting", GUI.skin.GetStyle ("Button"));
GUILayout.FlexibleSpace ();
m_CurrentState = GUILayout.Button ("Main menu") ? MenuState.Main : m_CurrentState;
EndStandardMenu ();
}
{
BeginStandardMenu ("Credits");
GUILayout.Label ("This game was created by some of the most awesomestest people on the planet. Having failed in their mission to Pluto, they started making games, which - as you can see - resulted in much joy and success!");
GUILayout.Space (20.0f);
GUILayout.BeginHorizontal ();
GUILayout.FlexibleSpace ();
GUILayout.Label ("The awesomestest people inc.");
GUILayout.EndHorizontal ();
GUILayout.FlexibleSpace ();
m_CurrentState = GUILayout.Button ("Main menu") ? MenuState.Main : m_CurrentState;
EndStandardMenu ();
}
}
Example project: Menu.zip – built with Unity 2.6.1
Pick me! Pick me!
Say you’re developing an RTS or maybe a connect-the-dots sort of game. What would be the easiest way to go about handling object selection? This is my suggested solution.
In the given example, I’m taking advantage of the object-mouse event handling that MonoBehaviours on GameObject with colliders on them give for free. You might be in a scenario where raycasting or otherwise resolving selection requests makes more sense, but the basic logic still applies. This example is merely intended to get your from start to goal as fast as possible.
First off, we need a selection manager class (cleverly named SelectionManager in my example). This is where we store selection state and via static accessors, we can get and modify the current selection. Seeing as this class is both public and all accessors are static, you can put its source anywhere. In my example I’ve simply put it right after the MonoBehaviour used for testing it.
SelectionManager
public class SelectionManager
{
private static GameObject s_ActiveSelection;
public static GameObject ActiveSelection
{
get
{
return s_ActiveSelection;
}
set
{
s_ActiveSelection = value;
}
}
{
if (selectionValue)
{
Select (gameObject);
}
else
{
Deselect (gameObject);
}
}
{
ActiveSelection = gameObject;
}
{
if (ActiveSelection == gameObject)
{
ActiveSelection = null;
}
}
{
return ActiveSelection == gameObject;
}
}
And the promised MonoBehaviour using the SelectionManager class:
public class SelectableObject : MonoBehaviour
{
public Rect m_SelectionWindowRect = new Rect (10.0f, 10.0f, 300.0f, 100.0f);
{
SelectionManager.Select (gameObject, !SelectionManager.IsSelected (gameObject));
}
{
SelectionManager.Deselect (gameObject);
}
{
renderer.material.color = SelectionManager.IsSelected (gameObject) ? Color.green : Color.white;
}
{
if (SelectionManager.IsSelected (gameObject))
{
m_SelectionWindowRect = GUI.Window (GetInstanceID (), m_SelectionWindowRect, SelectionWindow, gameObject.name);
}
}
{
GUILayout.Box ("I am the selection and my name is " + gameObject.name);
GUI.DragWindow ();
}
}
And that is all there is to it. By popular demand, I’m now starting to provide pre-built projects with these tips and tricks posts. Download, unzip, open and play. Requires Unity 2.6.1:
SelectableObject
Optimising coroutine yielding in C#
When needing to yield a coroutine for a single frame in C#, most people – including myself usually go about it this way:
{
while (m_Alpha < 1.0f)
{
m_Alpha += Time.deltaTime;
yield return 0;
}
m_Alpha = 1.0f;
}
However, as Rodrigo recently brought to my attention, this approach ofcourse performs unneeded memory allocation, given that the zero needs boxing and unboxing before its passed to the coroutine system. Using null in stead saves you that work and allocation.
This might not seem like a lot at first glance, but if you make this a habit every time you need to yield for a frame, I guarantee you that you’ll see results in larger scenarios.
The more optimal way of yielding for a single frame in C#. Minor difference, but allocation saved – which is always awesome:
{
while (m_Alpha < 1.0f)
{
m_Alpha += Time.deltaTime;
yield return null;
}
m_Alpha = 1.0f;
}
An interesting test could be to, on a larger co-routine heavy project, do a project-wide find and replace on “yield return 0;” and “yield return null;” back and forth and measuring the performance difference with the profiler (for non-pro users, maybe the performance gain is even measurable using external monitoring tools).