Aurora Combat Part 2 — Getting cubes to swing a sword
Posted on August 4th, 2012 at 12:24 pm
Alright, as I stated in my first post, I’m working on a (rather ambitious) combat engine that will let me play around with various control schemes and relationships painlessly and easily.
But first we need a guy to swing a sword.
Meet Rob. He’s going to be our testing character, likely for a good long while. Rob is built out of a collection of Unity GameObjects (the base in-game entity of Unity) in a specific hierarchy. Though there are significantly fewer points, the structure of Rob is loosely based on the animation rig of a standard bipedal creature. Thus, there is a single root object, to which the shoulders are attached, and then the hands. At some point in the far future, I want to be able to attach this system to a standard rigged character. If I’m thinking in terms of this structure now, I hopefully won’t have to deel with too many horrid surprises later on.
Rob’s sword was a free asset from the Unity Asset Store, made by Alexej Bodemer. The Asset Store is just another reason why Unity is such a good prototyping tool. While there aren’t scads of free assets, there are plenty to elevate an assortment of cubes into something more closely resembling what you’re developing.
Swinging A Sword
At this point in the project, I fully expect most of this code to be tossed out once I actually start building the system. What this phase does is ascertain precisely what variables and controls I will want to have.
At the moment, Rob’s hand is being moved directly from a start to ending position in code, with the sword attached. As I don’t necessarily know how many bones (or levels of hierarchy) there are going to be beween the character’s hand and his root, I’m setting the hand’s position as relative to the character’s root.
There were two significant challenges in getting the sword to swing correctly: getting the rotation to tween correctly and getting the position of the sword to be offset from the body.
Unity uses Quaternions for the rotations of objects. If you don’t know how they work, that’s okay, because unless you know your matrix math, they’re essentially black magic. In any case, I had a start rotation, or the orientation of the sword when Rob starts his swing, and an ending rotation, the orientation of the sword when the swing ends. Using the Quaternion object’s lerp() function, it’s quite easy to rotate the object smoothly from one to the other by the shortest path. The problem that immediately cropped up was that the sword did just that, by rotating through poor Rob’s body.
Here’s what was happening. The start and end orientations are such that the “shortest” distance between them (in terms of rotation) is actually the opposite of what I wanted.
My solution was to add an optional third “middle” rotation. For the first half of the swing, the sword rotates from the starting rotation to the middle rotation, and then from the middle to end in the second half. With this addition, the shortest rotation between each of the three points is the direction that I want it to rotate. This actually works better than I expected it to.
Without an offset from the body, a sword swing will look rather silly as it moves through the body in a line between start and finish. Some internet searching found two very effective equations for computing three dimensional bezier curves using either one or two control points.
Unity has great visual debug commands that let you trace lines, shapes, and control points to the screen, making the visualization of paths and the setting of positions and rotations very easy.
This is attached to a custom object editor that I created specifically for this bit of the project.
The object editor lets me set the positions and rotations for the starting, ending and middle points in the swing. It’s as easy as clicking a button, moving a control point in the Unity editor, and then clicking “done.” The slider lets me scrub to any point in that swing to see exactly how it looks. The editor also activates the controls for the bezier curve.
The code that was written for this was purely exploratory, and basically everything is going to be rewritten. That doesn’t mean it wasn’t useful though.
For example, I now know that for every independent body part that I want directly controlled by a sword swing, I’m going to need the following:
- Stance position and rotation
- Starting position and rotation
- Ending position and rotation
- Midpoint rotation
- One or two bezier control points
- How long it takes to go from the stance position to the start position
- How long it takes to go from the start position to the end position
- How long it takes to go from the end position back to the stance position
That’s a decent amount of information. I’m planning on breaking up each section of the swing (to start, slice, to stance) into separate “movement objects” that will each have the ability to have parabolic motion, halfway rotations, and individual times. That way, I can re-use the code when I go to make new motions such as blocking, punching, or kicking.
The next phase of the project is going to consist of mostly internal components that are going to be driving Rob’s motions and their respective editors. With any luck, I’ll be able to get it nearly to this same point soon, but with a more comprehensive backend, editors, and settings that don’t rely on values saved inside of a Unity level.