Mecanim Animation Events Workaround and Example

May 9th, 2013

Last night I spent a couple of hours trying to find a native solution for animation events in Mecanim in Unity, but all I found was a $35 Asset Store plugin. While I don’t doubt the usefulness of it and the interest of adding visual interface for events, it was much more than I needed (and was willing to pay for it). I couldn’t find any way to directly access animation frames either, so I spent the next few hours making a workaround for it.

If you know a better solution, don’t hesitate to use it and drop me a line. I’m sure it exists, but the doc is so incomplete that I simple couldn’t find it.

Now, what I wanted to do was to play a jump animation, then, during the last animation frame (before the transition to idle), teleport the character root to the new position of the biped. Here’s a video of what the final animation looks like in the Scene and Game views:

As you can see, the game object stays the same until the last frame of the animation, then it gets teleported to the position of the biped on top of the rock thingy. To achieve this, you will need to do a couple of things:

1. Import animations and set them up to work with your biped. For my example, you’ll need a jump animation that moves the root of the biped and an idle animation. You can look this up in billions of Mecanim tutorials on the Internet.

2. Put an empty game object at the position of the pivot point of your character (which should be on the ground between the character’s feet by the way), then parent it to the biped. I’m calling my object BipPivot. We will later use this object as a reference for teleportation.

3. Uncheck Apply Root Motion and check Animate Physics on the Animator component of your character. The former is done because we’re making a custom system to move the root and we don’t want the Animator to mess with it. Moreover, this option often gives strange errors (depending on your import settings). The latter is absolutely necessary, because it animates the avatar in FixedUpdate: we’re going to use this later to get the precise number of FixedUpdates of our animation.

4. Set up your Animator so that you have your Idle animation connected to your Jump animation and then Jump animation connected to your Idle animation.

5. Here’s where things get interesting. You have to select the transition from Jump to Idle and make the transition gap equal to 0% as shown in the image below. This is done because we want the Idle to kick in immediately after teleportation.

6. Now we’re going to measure the length of the Jump animation in FixedUpdates. To do this, you need to call your Jump animation by setting a parameter somewhere. Example: “animator.SetBool(“DoJump”, true);” Then run the following code:
private var frameCounter : int = 0;
//Base is the name of the animation layer, Jump is the name of the animation
//it is unclear from the documentation, but you can't compare the name in string
//it absolutely has to be hash
private var jumpState : int = Animator.StringToHash("Base.Jump");

function FixedUpdate()
{
if (animator.GetCurrentAnimatorStateInfo(0).nameHash == jumpState)
	{
		Debug.Log("I am a counter, the number you're looking for is on the right →");
	}
}

Run the game, run your Jump animation and observe the Console. The number on the right is the number of FixedUpdate “frames” of your Jump animation. In my case, the number is 158. Yours will probably be different. Remember it.

Once again, this is not a general Mecanim tutorial. If you don’t know how to start an animation, consult one of the Mecanim tutorials on the Unity website or on YouTube.

7. Now replace the code that you used to detect the number of frames by the code snippet below. It teleports the character to the position of our BipPivot game object.

private var frameCounter : int = 0;
//Base is the name of the animation layer, Jump is the name of the animation
private var jumpState : int = Animator.StringToHash("Base.Jump");
function FixedUpdate()
{
	//check the name of the current animation state
	if (animator.GetCurrentAnimatorStateInfo(0).nameHash == jumpState)
	{
		//increment frame count
		frameCounter++;

		//check if we have reached the last animation frame
		if (frameCounter >= 158) //because 158 is apparently the last jump animation frame
		{
			Debug.Log("Teleport now");

			//reset the frame counter
			frameCounter = 0;

			//teleport the parent game object to the position of BipPivot
			this.transform.position = this.transform.FindChild("Bip001").transform.FindChild("BipPivot").transform.position;
		}
	}
}

This method can be applied to any kind of animations and events. You can measure the length of the animation in FixedUpdates and then do something on a certain frame. I’m teleporting the character in the end of the animation. You can do something else.

I hope my code snippets will be useful to somebody and I also hope that there’s a better way to do this, because this is a hack, not a solution to the problem.

Coding, Unity3D | 4 Comments | Trackback

Untitled Story

February 12th, 2013

Visions of the ocean. Smell of burnt cinnamon. Prog rock echoing in my ears. You’re far away, you’re not with me.

Sometimes I dream of empty cinemas and large bodies of water, and a lonely cliff above an endless void. Cheap French wine, cotton stuffing in my limbs. Light and easy, gently dismissive. It’s not like anything else. This feeling.

The truth is, we all matter: you, me, her. Our choices carve the thin line that separates fear from devotion, faith from abuse, loyalty from fixation. You shoot a ray of light at the stars, it slides off the edge of your soul in a myriad of soap bubbles and dust particles. I intercept. I am still the boy standing in front of the big tree in my old neighborhood, playing with my rusty pocket knife.

You should not talk to strangers, you should believe in God, you should buckle up. It’s your responsibility, not mine. The next round is on me. He was such a great kid. A faraway planet is looking at you through a haze of nonexistence, its population running in fear, colliding with your dust particles, smelling the danger, drowning in the ocean. A small black figure near the edge of the biggest continent is immobile, resigned. It lifts its head and takes a long look at the supernova.

You’re supposed to, you have to, you must, we expect you to—obey, in so many words. The real danger is your own thoughts, your own actions, your own frailty. The fact that you really matter distorts your own consciousness to the point of nonexistence. You’re standing on the edge of a cliff, looking down into the void. I watch silent movies, all alone, enveloped in fear and anxiety. I see waves of water, hissing, and a flock of seagulls mixed with dust, bathed in late autumn sunlight. So pathetic. So heartwarming. So real.

It’s amazing how someone so incredibly hideous can be this beautiful. You know who you really are, you look in the mirror every day. You look at me and you see the same reflection, distorted and ghastly, unable to cope with the interference. Your world suddenly becomes unstable, and I can do nothing about it, falling through, trying to grasp the ultimate meaning of everything that ever happens. Pure thought, unrestrained, transparent in its unimaginable hopelessness. I am not really who you think I am. I am standing on the verge of myself, looking down into the void. You are falling through the membrane, soap bubbles dancing around your pale body. I am the only one who can really see you.

Fast forward to the beginning of our existence. Everything is there, within your reach. I hold out a hand and pat you on the back. You sigh equivocally. Something is not quite right and we both know it.

Suddenly, I realize that you are nothing but a separate entity. My eyes close and open again. I am no longer dreaming. I am right here, in front of the rest of the universe, emitting heat, reflecting and absorbing light, succumbing to the pressure of the atmosphere that covers our small planet. Resigned and a little sad, I look up at the supernova.

Writing | 1 Comment | Trackback

Lessons Learned from Two Ludum Dares

December 17th, 2012

This summer I participated in my first Ludum Dare, and I have to say that, as development goes, I managed to make a couple of really bad choices. Here’s a short list of what you should not do:

  1. Do not spend 30 hours making graphics assets and music.
  2. Do not make a game that relies heavily on animation, animation is the worst time-consumer.
  3. Do not use tools that you are not familiar with (in my case—RagePixel for Unity, an awesome but buggy tool that I decided to try for Ludum Dare).
  4. Do not spend hours making levels: level design is something that always takes more time than you expect.

Now, to give you an idea of what came out of this, go check out my 30-second game with lots of stuff packed into those 30 seconds, but 30 seconds nevertheless. It’s called Dissolution (screenshot is a link to Kongregate).

Now, I have learned my lessons. For my second consecutive Ludum Dare I sure as hell wasn’t going to repeat the same mistakes. Here’s my short list of conclusions regarding what you should do for a 48 hour solo game project if you want to actually complete it and maybe squeeze a few hours of sleep somewhere halfway through.

  1. Do make all things procedural. You’ve got enemies? Great, make them spawn procedurally and randomize their types. Got platforms? Generate short sequences and randomize them. Making a labyrinth game? Awesome, there’re dozens of maze generation algorithms on the web.
  2. Do make stylish graphics. Your Ludum Dare game can look good even without those shiny sprite sheets and complex 3D models. Keep your artwork as simple as possible and compensate by having nice-looking visual effects.
  3. Do make sounds and music. This is essential for correct perception of your awesome art style. What worked great for me so far is stylized graphics + more or less realistic sounds.
  4. Do design a simple game for each of the 12 themes in the final round of voting. It is a good exercise in game design, and it will help you get straight to coding once the theme is announced. Ideas are cheap, what counts is implementation.

As far as assets are concerned, you have to find a balance between sound and graphics, because you can’t make both very sophisticated, you have to prioritize. If you do all of the things suggested, you will find yourself being able to sleep a whole night and spend up to 12 hours polishing and optimizing your game, which, in turn, means that you will end up with something that feels infinitely better than most Ludum Dare games.

All those things out of the way, I give you Pineapple Dreams, my Ludum Dare 25 game about being a villain. The game features ultra-violence and was inspired by A Clockwork Orage, Drive and (you guessed it) Hotline Miami. Screenshot is clickable and leads to the game’s Kongregate page.

If you are looking for desktop versions, they also exist on the Ludum Dare page of the game. Below is the tune that I composed for this game.

Game Announcements, Game Jams, News | 4 Comments | Trackback

Paradis Perdus for Linux Released, Press Roundup and the Indie Dev Grand

December 1st, 2012

Today Paradis Perdus got nominated for the Indie Dev Grant by Bundle-in-a-Box. This means that people who buy the bundle will be given a chance to choose a game that they think deserves to get the grant. The grant itself is a certain percentage of money from every purchase of the bundle. This money will then be used by the development team (or the individual) who wins the grant fo finish their project.

The last Indie Dev Grant went to Simon Roth, who has recently joined the ranks of Kickstarter success stories with his kickass project, Maia. We’re really hoping to be the next.

And now that I’m done with this little promo (please, please vote for us when you buy the bundle!1), I’d like to say we are really thankful for all the support and feedback that we have received since release of the alpha, so to give something back, we are releasing a Linux version of the game now.

You can download the Linux version of Paradis Perdus (1.0.41) here:

http://www.mediafire.com/?j1cvxhrdygadgyd

You can still download Mac and Windows versions here: http://sergeymohov.com/paradis-perdus

From now on, we are going to update all three PC versions of the game simultaneously: Mac, Linux and Windows.

Please, leave comments, tell us how it works! We need your feedback, this is why the current version is called an alpha.

If you are not planning on buying Bundle-in-a-Box (which is, by the way, a mistake, there’re always plenty of super awesome games in it), you can also support us by tweeting about Paradis Perdus with #myouyagame hashtag. This might just get us an OUYA SDK and you an OUYA version of the game! Gamepad controls are already implemented, we just need a console to test them on.

Finally, to end this post, I’ve prepared a short roundup of media responses to Paradis Perdus (in chronological order).

Bundles, Game Announcements, News, Platforms | No Comments | Trackback

Paradis Perdus (Lost Paradises)

November 19th, 2012

Hello, good people of the world. I am happy to present my new game, made in collaboration with a couple of other awesome people from ENJMIN, my video game grad school. The game was originally created for Game à Niaque, a French game competition, but we are going to continue iterating on the thing. Meanwhile, I invite you to watch the gameplay video and play the alpha, which has just been translated into English.

Team: Sergey Mohov (game design, programming), Fabian Bodet (graphics, art direction), Matthieu Bonneau (music, sound design), Michèle Kopff (music).

The game is about not belonging. You are the bad guy, you are killing everything you touch. The world you are in is beautiful and green, but the moment you get into it, you start infecting everything, and the world starts decaying, until it eventually ceases to exist. You can choose to exit the world, and then it will heal itself, but then you don’t get to enjoy it of course, because you’re not there any more.

Here are download links to the latest version of the game.

Mac: http://www.mediafire.com/?wag8ujuu0abbn4t (+ Mirror)

Windows x32: http://www.mediafire.com/?vklqdj3m7i9azag (+ Mirror)

Windows x64: http://www.mediafire.com/?96sl785is0fswsb (+ Mirror)

Update: Linux Universal:  http://www.mediafire.com/?j1cvxhrdygadgyd

(if you don’t know which type of Windows you have, just download the Win32 version of the game, it works on most PCs)

Download screenshots: http://www.mediafire.com/?m76z1c2kvcmzz3k

People have been requesting the soundtrack from the game, so here it is, straight from Matthieu’s SoundCloud. The first one is the clean version, the second one is infected. Enjoy!

Game Announcements | 42 Comments | Trackback

Categories

Find:

Links