Post news Report RSS The Odyssey: Animation test video

I have been working on a test video of the animation system. In this post I explain how the video was built.

Posted by on

For work-related reasons I have been using the Unity engine for the last few months. There are some things I like: it is incredibly easy to set up something and view it live with a few clicks. The editor is very powerful and it is something that I would really like to have for my engine. However, being an incredibly stubborn developer, Unity is not something that I can feel as being “mine”, so I’d rather spend twice as much time (or even more) to build my own engine.

This brings us to the matter at hand. My engine does not (yet?) have a visual editor with which I can script animations and preview them. As you may recall, I implemented animation features for my UI library. I have extended that system to the rest of my Entity-Component-System framework. Using my xml-like language is the next-best thing, if compared to actually writing the code necessary to create the animation objects from scratch. Instead, I can define them with a few lines and the parser will take care of orchestrating everything. I have thus created a Cutscene class that is able to animate all entities in the Scene and is also able to reference other hardcoded animations such as those belonging to UI controls. I need these animation features for two main reasons: first, I’m working on an “announcement” trailer of sorts and second, once I move to the actual ship-to-ship combat part of the game, once you issue an order, it will be visually shown by a contextual cutscene, similar to the way it happens in the recent X-Com game. Here is an example of the Cutscene animation shown in the above video.

<?xml version="1.0" encoding="utf-8" ?>
<Cutscene>
  <Animation Name="FocusOnPath" WrapMode="Loop">
    <BoolCurve TargetName="{Overlay[UserInterface[twLocation]]}" TargetProperty="IsVisible" >
      <BoolKeyFrame Time="0.0" Value="True"/>
      <BoolKeyFrame Time="7.0" Value="False"/>
    </BoolCurve>
    <QuaternionCurve TargetName="{PerspectiveCamera[Rotation]}" TargetProperty="Orientation">
      <QuaternionKeyFrame Time="8" Value="E0,0,0"/>
      <QuaternionKeyFrame Time="10" Value="E90,0,0"/>
    </QuaternionCurve>
    <BoolCurve TargetName="{Overlay[UserInterface[Prompt]]}" TargetProperty="IsVisible" >
      <BoolKeyFrame Time="0.0" Value="False"/>
      <BoolKeyFrame Time="8.0" Value="True"/>
      <BoolKeyFrame Time="20.0" Value="False"/>
    </BoolCurve>
    <BoolCurve TargetName="{Overlay[UserInterface[lVenus]]}" TargetProperty="IsVisible" Function="SquareWave" Options="8">
      <BoolKeyFrame Time="0.0" Value="False"/>
      <BoolKeyFrame Time="12.5" Value="False"/>
      <BoolKeyFrame Time="15.5" Value="True"/>
    </BoolCurve>
    <BoolCurve TargetName="{Overlay[UserInterface[Target]]}" TargetProperty="IsVisible" Function="SquareWave" Options="4">
      <BoolKeyFrame Time="20.0" Value="False"/>
      <BoolKeyFrame Time="23.0" Value="True"/>
    </BoolCurve>
    <BoolCurve TargetName="{Overlay[UserInterface[lCountdown]]}" TargetProperty="IsVisible" >
      <BoolKeyFrame Time="0.0" Value="False"/>
      <BoolKeyFrame Time="20.0" Value="True"/>
    </BoolCurve>
    <FloatCurve TargetName="{Path[PrimitiveReveal]}" TargetProperty="PrimitiveRatio">
      <FloatKeyFrame Time="23" Value="0"/>
      <FloatKeyFrame Time="26" Value="1.0"/>
      <FloatKeyFrame Time="30" Value="1.0"/>
    </FloatCurve>
  </Animation>
  <Commands>
    <PlayAnimationCommand TargetName="{Overlay[UserInterface[twLocation]]}" Time ="2"/>
    <PlayAnimationCommand TargetName="{Overlay[UserInterface[Prompt]]}" Time ="10"/>
  </Commands>
</Cutscene>

The top-level object in my ECS is the Scene, an object containing all entities in the game world. As such it implements an interface that is able to return individual entities by name. So when the parser finds a string value in the TargetName attribute it asks the Scene object to return the correct entity. If the value is in array syntax, the Entity object (which implements the same interface as well) will return the component specified as the index of the array. This can go on for more layers as it can be observed from the boolean curves targeting UI elements. Overlay is the UI entity, while UserInterface is the actual UI component holding a reference to the GUI object; the third index is the name of the individual UI control being referenced. I have also implemented a few functions to avoid generating individual keyframes to approximate some effects, such as the SquareWave function that animates the flickering of the target brackets.

Finally, the Commands section references other animations that are defined elsewhere, either as other cutscenes or as hardcoded animation. In this case those two animations are the built-in animations of the Typewriter effect. This cutscene will activate the first one two seconds into the animation and the other one ten seconds into.

So all things considered, it’s a nice compromise if a visual editor is not available. Now, that typewriter definitely needs some sound effects… Also, I can now work on the animation concerning the Campaing Screen!

Post comment Comments
Shuuny
Shuuny - - 12 comments

You are on the wrong path here. If you are writing your game as a game(!), not using unity engine, you should really use the strengths of this approach, instead of applying Unity design decisions to your work.

- Do you really *need* visual editor for this exact game?
- Is visual editor really the easiest way to manage *this* scene, if your game is custom built, outside generalizations typically made in engines such as Unity?

You will find that well built custom game, without using 'engines' such as Unity or Unreal will actually speed up development for witty programmer, who knows where to use a library and where not. Unity might be good for people who can't code fluently or for teams of multiple people, making generic game, but such engines as Unity are bleak when compared in context of game being written and produced by capable and fluent programmer and especially if the target 'look' and underlying system design is not well expressed using standard generalizations provided by engine.

Don't give in Illusion that what is available and how it's done in some now-days popular engines is really 'top-dog' in what you really need. In fact, a general what-you-see-is-what-you-get editor will more often than not limit yourself in what you imagine as tangible design for game and you will sometimes find fighting with unsuitable abstractions in the editor to get a simple concept done, meanwhile the streamlined graphics engine puts a big stamp over any game made by it, prohibiting it to achieve innovation in graphics design and/or presentation... well... unless you basically just ignore the whole thing, scrape out of Unity what you can and practically write your own rendering code from scratch... That said, Unity is a great tool for developing games where you just don't need any better, like generic 2D game, sort of you would be making in GameMaker, before quite a time.

Reply Good karma Bad karma+1 vote
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: