Planet Tech Art
Last update: November 29, 2014 01:00 AM
November 27, 2014

Behave 2.4

It is finally time for a more substantial update for Behave. With version 2.4, Behave ventures out of its former behaviour tree comfort zone and adds built-in support for utility and blackboard constructs.

Records

Combined under the label “Records”, this expansion adds three primary new library objects:

  • Fields
  • Curves
  • Graphs

Similarly to how behaviour trees can be connected to agent blueprints, records are tied to so called “collections”. These are effectively “smart tables”, which can be queried (by name) for the value of a specific record – as well as be asked to set the current value of a record.

You can either choose to use these collections on their own or directly integrate them with your behaviour trees.

For more information, see the behave documentation as well as the new Records video.

Onwards

So as you might have guessed, the internal refactoring work mentioned in earlier releases, paved the way for this expansion. However, as per usual, the implementation is somewhat restrained. Any feedback and requests would be most welcome.

That is not to say that the expansion plans end here, but more on that later.

Changelist:


2.4:
 - Introducing “records”.
     - Float fields stored in “collections” - essentially ‘smart tables’.
     - Blackboard fields.
     - Utility curves.
     - Utility graphs.
     - Behaviour Tree integration.
          - “Tester” component.
          - “Writer” component.
          - Record mode for Priority Selector component.
 - Editor behavioural change: Deleting a tree no longer deletes reference nodes targeting that tree from other trees. Their target is merely cleared.
 - Editor behavioural change: The Reference node is only available in the component bar if the library contains more than one tree. Same behaviour for Tester and Writer with records.
 - Behavioural change: Invert flag is now properly applied by the Priority Selector.
 - Debugger connection stability improvement.
 - Connection disabling has been removed. This confusing feature caused more harm than good.
 - Video player now displays video title and description.


2.3.5:
 - Fix home screen video player.


2.3.4:
 - Better error messages in case of insufficient file access privileges (OHAI Perforce).
 - Added simple version check to the home screen.
 - New icons for Priority Selector and "form new tree".
 - Smaller, embedded, JSON library.
 - Fix annoying behaviour with tree renaming where text fields would keep last entry.
 - Fix similar behaviour with component text fields on tree selection change.
 - Unity 5 compatibility fixes (tested on beta 2).


2.3.3:
 - Fix focus handling issue with auto-complete.
 - Parametrisation is now correctly applied for reset handler calls.


2.3.2:
 - Fix sidebar item duplication and deletion only functional during rename.


2.3.1:
 - Fix GUI error being logged on tree selection.
 - Proper handling of currently edited library asset being deleted.


2.3:
 - Added support for instant repeaters.
 - Added support for mandatory contexts.
 - Added optional target parameter to Tree.ResetForwards.
 - Added Tree.TickWrapping method.
 - Added debugger auto-launch settings to library build options.
 - Added home screen - shown on launch or via the Help menu, full of resources.
 - Behavioural change: Decorators no longer forward the instant flag of their child node.
 - Behaviour of decorators receiving a Running signal from their control connection is now defined.
 - Dependencies now shipped as separate (replaceable) files for minimal project impact.
 - Editor polish.
     - Added support for running multiple editor debugging instances on one machine.
     - Added focus-follow for debugger and canvas.
     - Added both scrollwheel/pad and drag-to-scroll support to all canvas views.
     - Drag connection to occupied input slot to replace.
     - Directly drag-drop trees from the sidebar onto the canvas as reference nodes.
     - Instant flag doesn't show on nodes connected to parents ignoring the flag.
     - "Last edited library" now tracked per project.
     - Last selected tree is now also restored between sessions and playmode transitions.
     - A bunch of minor adjustments and improvements.
     - Performance + memory + disk space optimisations.
     - Minor bugfixes.
 - New documentation layout and enhancements (already released as available).
 - Reshuffling of code to make way for exciting new things down the road.


2.2.2:
 - Addressed protobuf issue causing Parallel component completion setting to not get stored correctly.


2.2.1:
 - Fixed issue causing parallel components to fail compilation.


2.2:
 - Behavioural change: Support for multiple different action handler signatures is discontinued effective immediately.
    - Generated agent blueprint as well as accepted reflected signatures are now only:
        - public BehaveResult [Tick/Init][Name]Action (Tree sender);
        - public void Reset[Name]Action (Tree sender);
 - Added Tree class accessors - all valid only during an active init/tick/reset handler call:
    - string ActiveStringParameter
    - float ActiveFloatParameter
    - IAgent ActiveAgent
    - object ActiveData
 - Rather than waiting for the Unity bugfix, the built-in compiler API is now bypassed in favour of direct compiler binary execution.
    - An additional system-level mono SDK install is no longer needed to work around this Unity bug.
 - Tree.SetForward now returns boolean success value rather than logging error when passed unused action.
 - Full-library export now also available from the library settings in stead of menu-only access.
 - Even more UI polish: Better word-wrap, more contrasts for emphasis, instant flag hidden in unaffected scenarios and much more.
 - "Form new tree" nicely moves the new subtree up around the root socket rather than retaining the old position.
 - Default frame-rate of DebugUpdater now set to 20 fps rather than every frame. Gun safety and all that.
 - Massive codegen size save for larger libraries - from optimisation of tree-agent introspection codegen. Compile-time win.
 - More rigid parameter evaluation (remove needless occasional extra codegen).
 - Fixed copy and duplication procedures incorrectly not copying parameter values.
 - Force Unity to write serialised data before compiling.


2.1.1:
 - Fixed issue with tree paramterisation breaking debugger visualisation.


2.1:
 - Added autocomplete on action names, string parameters and component contexts.
 - Added mandatory actions (present in library regardless of use in trees).
 - Added partial library export and library merging / import-to-library.
 - Added Behave stripping - leave behind only a very lean Behave runtime, for redistribution or super slim deploy.
 - Added parameterised trees - get even more re-use out of your trees by overriding context and variables per reference.
 - Behavioural change: Tree.Reset will now delay resetting tree variables until after complete component reset.
 - Behavioural change: Tree.Tick will no longer automatically reset the tree upon completion. This plays very well with:
 - Added Tree.TickContinuously (int iterationCap = 1024) - ticks tree till completion or iteration cap is reached.
 - Added BehaveResult Tree.Result (bool value) utility function to side with Tree.Invert (BehaveResult value).
 - Added int Debugging.Local.ConnectionCount property - facilitating debug behaviour dependent on Behave debugger presence.
 - Moved default install path from Assets/Behave to Assets/Plugins/Behave.
    - WARNING: See Readme.txt upgrade guide.
 - Fixed decorator control node removal resulting in detached control connection.
 - Fixed decorator incorrectly not forwarding the instant status of its child node.
 - Fixed scenario where agent classes would get reflected for handlers even if blueprint derived.
 - Fixed unexpected corner cases of bad library configuration failing compiles (now causing warnings or simply being ignored).
 - Fixed Behave window breaking down when exiting play mode after having been active there.
 - Fixes to context getting incorrectly reset in some scenarios.
 - Fixed copy / paste functionality missing in some text fields.
 - Lots of UI polish and minor fixes.


2.0:
 - New editor.
    - Unified all controls into one window.
    - Completely customised look - compatible with both Unity light and dark skin.
    - Keyboard authoring interface in addition to drag & drop.
 - Debugger upgrade.
    - Remote debugging.
    - Tick and reset.
    - "Unplug" for debugger-only control.
    - Breakpoints.
    - Action overrides - override the return values of specified actions.
 - Decorator rewrite.
    - Deprecated old decorator.
       - Still compiles, but cannot be added.
    - Decorators are now control-type components.
       - No specific decorator handlers on agents.
       - Control is achieved via third connection socket.
    - Two initial decorator types: Repeater and Interrupter.
 - Asset restructuring.
 	- No more collections - for nesting, use paths in tree names.
 	- New serialization format - see Readme.txt for upgrade instructions.
    - Collections are gone. Use Unix-style path names for tree organisation.
 - IAgent.Tick (Tree, bool) changed to IAgent.Tick (Tree)
	- Init calls can now only be handled explicitly
 - Full coverage online documentation and other community resources.
 - Countless fixes and polish items.

1.5:
 - Added Tree.TickActive - indicating if a tree is currently executing a tick or if it has completed evaluation.
 - In-tick tree reset requests now result in a reset at the end of tree evaluation rather than an immediate one.
 - Removed the legacy compatibility assembly (for compatibility with pre-1.2 assets) from the default distribution.
 - Fixed "X must be instantiated using the ScriptableObject.CreateInstance method instead of new X" warnings.

1.4:
 - Fixed decorator incorrectly initializing on every returning tick when tick handler returned Running.
 - Fixed debugger view dependency on active tree editor - causing reported null reference exception.
 - Fixed missing scrollbars on browser window.
 - Reduced logging noise from debug builds.
 - Agent blueprints can now be MonoBehaviour based.
 - Clarified wording on "library not loaded".
 - Now handling reset a bit cleverer - potential performance boost.
 - Changed the default success criteria of Parallel components from SuccessOrFailure to Success.
 - Added "instant" flag to components. Components marked instant will affect sequences and selectors when moving between child nodes. When a child node marked "instant" completes, rather than waiting for the next tree tick to tick the following child node, the sequence or selector does it immediately.
 - The compiler progress bar returns.
 - Editing a Behave asset now focuses the asset browser last instead of the tree editor.
 - Behave can now be installed in any subfolder of Assets - provided its internal folder structure remains intact.
 - Compilation speed improvements.
 - Enabled references across collection borders.
 - Added Tree.DataSize - returning the number of bytes used by a tree instance. This is also displayed in the debugger window.

1.3:
 - Fixed priority selector init flag resetting.
 - Fixed reference handling on tree renaming and deletion.
 - Fixed references still pointing at old collection post collection duplication.
 - Fixed compilation of actions and decorators with non-integral float parameters.
 - Fixed GUI list behaviours.
 - Fixed passing context back and forth between referenced trees and referrer.
 - Fixed reordering connections not causing save state to be set.
 - Various GUI tweaks.
 - Runtime optimisations.
 - Enabled scrolling of the tree list in the debugger window.
 - Exposed Tree.ReflectForwards.
 - Added Tree.ResetForwards.
 - Added agent blueprints - connecting to agent handlers through virtual methods rather than reflected handlers.
 - Made connections selectable in the tree editor via the connection nub.
 - Moved connection managing from the inspector to the tree editor, where it is more visible and handy.
 - Added support for disabling connections - for faster, less destructive debugging.
 - Double-click reference component to jump to referenced tree.
 - Changed "Cannot update unregistered tree" handling from an exception to an error message. Still need more info.
 - Now showing string and float parameters in the tree editor if either is set.

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.

1.1:
 - 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.

1.0:
 - Lots o fixes for Unity 2.5 compatibility.
 - Closer editor integration with new UI.
    - Component bar.
    - Node inspection.
 - Runtime tree debugging.
 - Direct mapping of action and delegate handlers via reflection.
 - Kitty demo.

0.3b:
 - Various tweaks to the editor UI.
 - Optimised the compiler.
 - Fixed the following editor bugs from the bug list:
    - When the editor scrips are recompiled and when the user enters and exits play mode, running editors will loose references, causing undetermined behaviour.
    - When a compile fails, the Behave compiler is locked and unusable – requiring a unity relaunch.
 - Implemented the following wishlist items:
    - Behaviour tree decorators.
    - Stand-alone edition of the Behave editor.
    - Behaviour tree debugging features.

0.2b:
 - Made the demo project a whole lot more interesting.
 - Implemented the editor wish list item: Ability to move trees between collections.
 - Various tweaks to the editor UI.
 - Fixed a ton of bugs in the compiler.
 - Fixed the following editor bugs from the bug list:
    - Not able to delete collections from library.
    - Not able to delete trees from library.
    - Not able to rename collections from library.
    - Not able to rename trees from library.
    - Missing "tree has been changed, save changes?" dialog.

0.1b:
 - Some documentation is available.
 - Compiler is now creating sensible output.
 - A simple test tree and script using it is provided with the demo.
 - Documentation is linked directly from the unity help menu.
 - Less spamming of the log with debug information.

Pre-release:
 - Magic happened. Behave was born.

by at November 27, 2014 11:00 PM


November 25, 2014

Bagels and Coffee, or, the vector dot product and you

I’ve been boning up on my math lately.
Like most TA’s I’ve cobbled together a bag of tricks from different situations I’ve dealt with over the years, but I’ve never really gone back to shore up my shaky high school trigonometry and pre-calculus. It’s certainly possible (at least, I hope it is!) to be a good TA with only seat-of-the-pants math skills — after all, we have parenting and scaling and all the other cool tricks in our apps to do the heavy lifting for us. Still, I’ve been finding that paying more attention to the math fundamentals is helping me solve problems more efficiently and elegantly than my patented hack-and-slash techniques did.
So, I’m starting an occasional series on some basic math concepts that I hope will be useful to other TA’s. I know it’s been helpful to me - there’s nothing that concentrates the mind like putting something out there on the internet for public commentary - it’s really forces you to think things through… At least, as long as you’re not on Twitter.


To kick off the series, I want to start off with a simple operation that I use all the time, the humble dot product. Also known as the 'scalar' product, the dot is an operation for turning lists of numbers into a single number. It’s also astonishingly useful for graphics. I’ve used it for years, but only recently did I try to see how and why it works instead of just relying on the second-hand assurance that it works.
The dot is all about combining operations on lists. We always run into it in the context of geometric vectors, but in the pure math world vector is just another way of saying “list of similar numbers.” If you go to the coffee shop every day and buy a $5 latte, its obviously going to cost $25 a week (Tote that up over 48 work weeks a year - it's a lot of money! I bring instant. But I digress). If you buy a $2 bagel on monday and a $3 cookie on Wednesday and Friday, how much will it cost?:
5 * 5 = $25 for coffee
2 * 1 = $2 for bagel
3 * 2 = $6 for cookies
This makes $33 total a week (you really should bring in your snacks from home. You'll save a ton!)
Besides helping you save money on lunch, this is a classic (though non-3-d related) example of the dot product in action. Dots are nothing more than a structured way of multiplying two lists of numbers. In this case we have list of prices:
[5, 2, 3]
and a list of quantities:
[5, 1, 2]
The dot operation merely multiplies the numbers in the same position in the list and adds them together. As you can see, this is trivial math:
(5 * 5) +  (2 * 1) + (3 * 2)

Despite it's humble origins, however, this trick -- multiplying ordered pairs of numbers and adding them up - is absolutely basic in 3-D graphics. The lists of prices and quantities become vectors (in fact, general purpose algebra calls any list a 'vector') and with a simple convention the dot product takes on a very interesting and useful set of properties for TA’s to exploit.
The most famous example of the dot product in graphics is the original Lambert shading equation:
N dot L
Where N is a surface normal and L is the angle of the incident light.


The 'Lambert shader' is based on this math textbook from 1760. How cool is that?

Lambertian shading is probably the single most common operation in computer graphics, but it’s the same math as figuring out your coffee budget. Here’s how the magical translation from bagels and coffee to shaded pixels works:
Imagine a sphere being lit by a directional light from straight above, in classic CG fashion. The vector to the light would be
[0, 0, 1]
On top of the sphere, the normal vector would point the same way - it too would point up towards
[0, 0, 1]
The dot of these two is:
(0 * 0) + (0 * 0) + (1 * 1) 
in other words, 1. This makes sense: our light is directly overhead, so the sample point on top of the sphere receives the full incoming light. Compare this to a point halfway down the sphere. A a normal point 45 degrees from the vertical might be
[.707, 0, .707]
And the dot would be
(0 *.707) + (0 * 0) + (1 * .707)
or .707. That means this sample point is getting about 70% of the incoming light. At the horizon of the sphere the dot will be [0,0,1] dot [1, 0, 0]. This dots out to
(1 * 0) + (0 * 0) + (0 * 1) 
or 0. This makes sense - at the horizon of the sphere the light is parallel to the surface and imparts no light.
Or, in pretty picture form:

Wherefore art thou cos(theta)?

So, it appears of this fancy-pants rendering is coming from the same bagels-and-coffee trick. How come? Lambert’s law isn’t some simple interpolation - it’s based on cosines, which give it the characteristic soft falloff around the horizon. How does this work?
The sharp-eyed reader might notice that all of the vectors in this example are normalized, that is to say the length of all of the vectors in this example are 1. That’s is the special convention that turns a plain-vanilla dot product into a geometric proposition. As long as the vectors are normalized -- but only if they are normalized -- the dot product of the light vector and the normal vector is the cosine of the angle between the two vectors. That’s what makes the nice soft falloff on a Lambert-lit object, but it has lots of other properties as well.
To understand how this bagels-and-coffee math turns into trigonometry, remember that ‘normalizing’ a vector just means setting its length to one. Visualize what happens if you sweep a 1-unit long line segment around in a circle, starting from the horizontal. As the segment rotates, you can draw a right triangle from it’s end point up or down to the horizontal axis, as in the example below:


If you recall your high-school trigonometry you’ll remember that the cosine of an angle in a right triangle is the ratio between the side of a right triangle next to the angle and the hypotenuse of the same triangle (the “CAH” in “SOHCAHTOA,” if you learned it the way I did). In this case, our hypotenuse is always 1 (it’s a unit line). so  the cosine is just the width of our right triangle. All of this works as described only if the vectors are normalized,however - when your dots give you wonky results, non-normalized vectors are always the first thing to look for.
This video from Khan Academy gives you a more in-depth derivation if this description isn’t clear.
Once you grasp the unit-circle-cosine setup, it’s easy to see how dotting unit vectors creates cosine values rather than lunch budgets. See what happens when you dot a random vector against [1,0,0]:
example = [.866, .5, 0]
reference = [1, 0, 0]
example dot reference = (.866 * 1) + (.5 * 0) + (0 * 0) = .866
As you can see the X component of the example vector has been preserved, but the other two are zeroed out. (This illustrates the meaning of the dot project - it’s the projection of one vector on to another. We’ll touch on that more in the next post).
In this case, projecting that 60 degree line segment onto the vector [1,0,0]creates a line segment from [0,0,0]to [.866,0,0] and the same kind of right triangle we described above. The ratio of the hypotenuse vector to this new ‘adjacent’ vector is .866 / 1, that is, plain old .866 — which we we know from the unit circle is the cosine of 60 degrees and the answer we were looking for.
This is how the dot of two normalized (!) vectors is alway the cosine of the angle between them.

Dot's all, folks

So that's the basic theory of the dot product. Of course what the ruthlessly practical TA will want to know about is uses, not theory. Some of the applications will be obvious but there is a plethora of less obvious ways the dot product can make your life eaiser. I’ll hit those in my next post.  In the meantime, bring instant coffee instead of paying for that venti tripple mocchachino every day. That stuff’ll totally blow your budget.

by Steve Theodore (noreply@blogger.com) at November 25, 2014 03:56 PM


November 19, 2014

Big (?) Python bucks!

I've frequently commented in the past on the Game Developers Salary Survey.  For you Pythonistas out there, there's some nice data (amateur grade, but still pretty good) to be found at the Python Developer Salary Survey.  No mention of what you get for knowing Max / Maya, however, but by crunching the numbers I'd guess it subtracts about $30k per year.

Or maybe that's just because we're all lousy programmers.

EDIT: fixed bad link


by Steve Theodore (noreply@blogger.com) at November 19, 2014 05:12 AM


November 18, 2014

Nexus Voltron

This is the second product based on the Nexus Framework that both me and Daniel here at YCDIVFX have been developing along with our good friend Jonathan de Blok as Lead Developer on this project.

Codename “Nexus Voltron” is a plugin for 3ds Max and After Effects that will allow you to interop between the two applications very easily. Sorry, not that many details for now but I will keep everyone posted! Meanwhile here are some cool videos!

Click here to view the embedded video.

Click here to view the embedded video.

 

by Artur Leao at November 18, 2014 10:42 PM


Rigging Reel 2014


Breakdown:

01. Elephant Rig
Creature rigging in Autodesk Maya using Maya Muscle. A custom flexible auto rigging script for the Variable FK trunk was written in PyMel.

02. Variable Foot
Organic and flexible foot posing using only a couple of controls without stacking of a large number of variable foot parameters. This solution allows the animator to position the pivot on any part of the foot and control the direction and falloff of the bend.

03. Delta Mush
This deformer is based on Voodoo's Delta Mush deformer and requires almost no skinning work to be done. Using the vertices tangent space it provides a smart deformer that preserves volume and shape.

04. Smooth Skin Decomposition
The results of using the Delta Mush deformer are decomposed and applied to the rigid skin of the character. This solution produces a skin with deformations that are as close as possible to the Delta Mush deformations.

05. Bezier Spine
An animation friendly spine rig that uses a minimum amount of animation controls without sacrificing any flexibility. The chest and hip controllers can change their location and provide different points from which the spine bends. By adjusting the chest and hips tangent handles the spine shape can be further defined and tweaked.

06. Shape Rasterizer
A 3D shape is projected onto a plannar mesh and rasterized to create a look that immitates low resolution screens. The shapes vertex colors are used to define the colors of this rasterized shape.

07. Herman and Chad
Responsible for body and facial rigs, skinning, UI writing and rig maintenance.

08. Spherical Mirror
Written in Fabric Splice for Maya. Creates a mesh instance that is mirrored using a spherical mirror. Supports animation.

09. Wheel and Threads Node
Custom node written in Fabric Splice for Maya. The node provides a complete solution for wheels and threads. The wheel rotation works in world space and works in any direction. The same is true for the threads. The thread mesh is automatically instanced and the thread control points define the shape, size and rotation of the threads.

by Armin Halac (noreply@blogger.com) at November 18, 2014 11:16 AM


November 17, 2014

Long live Slack, down with egotistical email

We use Slack for team communication at Cozy. I struggled with the transition. When I reflected on my struggles, it made me better understand what a destructive format email is for workplace communication.

A quick disclaimer. This is only about work communication and not personal communication. I love email. I think email will be around for a long time and I will lament if and when it goes away. I just don’t think we should be using email for work.

Oration is the highest form of feeding an ego. You craft your message carefully. You research, write, and rehearse. Finally, you take the stage. You command everyone’s attention. And once you’re done, an important topic has been thoroughly addressed and everyone can go on with their lives, better off after hearing what you said.

Email is oratory without the speaking* (or skill). My problems with email stem from when it is used for one-way communication. I suspect that most emails I’ve ever received from anyone in management have been one-way. Generally these emails are meant to, first and foremost, communicate the sender/manager’s self-importance. Often the email contains a nugget of actual information which should be hosted elsewhere. Sometimes the email is an announcement no one understands. And as a rule, you can’t rely on people reading the email you send anyway.

When you craft a long email, like an orator crafts a speech, it is an ego boost. Each one is a masterpiece. You are proud of your fine writing. When you craft a long chat message, on the other hand, you look like a dramatic asshole. It puts in stark perspective how awful the written format is for important or high-bandwidth communication. I’ve never seen someone post a 300-word message to chat. How many 300-word emails do you have in your inbox?

Removing email also levels the playing field for communication. You don’t need to be a manager or orator. Everything you write has a visibility you can’t change. You choose your audience based on topic. Is there a question about a product’s design? Well, it goes into the product or design channel, whether you are Executive Emperor or QA Associate II. Also, no one really wants to read your dramatic flair so please keep it short and to the point.

I used to get frustrated when I’d write an excellent email, send it out, and within a few minutes someone would reply with a message like “Yeah, just to build on what Rob said, it’d be a good idea to do X.” You idiot! You are an Ice Cream Truck driving through the State of the Union. But of course, the problem was mine, playing a manipulative game, focusing too much on this amazing message I’d created. Sometimes these emails would be about the manipulative games people were playing and how we weren’t focused on the employees and customers and things that were actually important.

Email in the workplace is a systematic problem. We take it for granted. We use it constantly. We don’t question it. But email has a cost. It feeds into the already inflated ego of managers. It encourages one-way communication. It is wonderful for grandstanding. We spend a lot of time crafting museum-quality correspondence no one wants to read. And in the end, there are better ways to accomplish what we use it for.


* One of the greatest “speeches” of all time, Pro Milone by Cicero, was written, not spoken. We know great orators by their writing, not their speaking.

by Rob Galanakis at November 17, 2014 02:05 PM