Unity Tips & Tricks #3: Kratos Controller Part I
Context
Recently, while browsing on Reddit, I came across this post where someone shows of its God of War demo, made in Unity. The whole thing is nice, and given I’d wanted to give a try myself a recreating some of the God of War mechanics, I decided it was time to give it a go !
Modeling/Texturing
I did all the modeling all by myself, using Blender. Given I’ve recently purchased almighty RetopoFlow 2.0, I didn’t follow my old workflow that relied on creating first a skinned mesh, sculpting it and then try to skrinkwrap it as well as possible before patching the wholes with manual retopology. RetopoFlow is really awesome and definitely introduces more freedom.
Here’s the finished model before retopology step:
Afterwards, with textures from Substance Painter:
Changing perspective
My first approach was to go ahead and copy as much as possible the mechanics of the genuine God Of War. But I quickly came to realise that I would very likely get lost. Indeed, managing the combat mechanics, the axe logic, aiming, dodging, impacting, ennemy behaviour, effects was probably too much for a first try. Hence, I thought I’d change my perspective.
I hence came up with the following idea: change the view point. I basically changed the camera from a TPS behaviour (ie. looking over the character’s shoulder) to an isometric setting.
This simply allowed me for various simplification while retaining most of my previous code:
- All the logic behind movement is still effective (rigidbodies movement, computation of direction and so on)
- The only way to shoot the axe would be forward. Hence, I can focus on shooting, recalling and switching weapon logic.
Global setup
Movement insights
While I was working on the skating scene, I was concatenating Quaternions to reach the desired final rotation. In this process, several rotations were involved.
- A rotation that transforms the character’s up vector to the current ground normal vector
- A rotation to face the current velocity vector, projected on the Y-up normal defined plane.
I used a method similar to the second item to improve the way the character turn. Here’s a method comparaison:
Method | Previous | Current |
---|---|---|
Step I | Compute direction based on player’s input and camera position wtr to character | Compute direction based on player’s input and camera position wtr to character |
Step II | Add force to the player. The force is oriented by the player’s forward. Meanwhile, turn the player (Quaternion.Lerp) to face this direction | Add force to the player, based on the desired direction. Rotate the player forwards towards this force. This allows to use the angle value to blend animations |
Axe stuff
Now, let’s cover what has made the last God of War episode so memorable: The Leviathan Axe. My prototype version is currently far from being as efficiant as the one feature in the Santa Monica productio n, so let’s call it the Goldfish Axe for now.
In its current version, the implementation relies on two separate scripts:
GoWAxeControl
that is held by the Kratos characterAxeBehaviour
that belong the the Axe object
My first attempt at this deffered an important axe logic inside of the GoWAxeControl
, which was unwanted because it mixes data and streams and I actually want my modules to be as autonomous as possibl e, so that they can be easily changed and tweaked. Thinking about the future here. I’m now going to present the actual version, available here.
Axe Control
This script has no Update
method, and, as shown in the graph above is mostly controlled by GoWModular
that calls method based on player’s inputs and animation triggers. There’s a button to trigger t he GetAxe animation, where Kratos reaches in his back, another button launches the CallAxe
procedure, where Kratos raises its arm to call the axe. In this case, the animation uses another layer th at has a mask on the shoulder to hand bones (so I still can walk or run). This is slightly messed up and I will later improve it. Anyway, a rather basic script.
Axe Behaviour
More magic happens in the other script. Here, I first had to define some offset parameters, in terms of vectors and quaternions. Indeed, because of frame difference, the axe was not positionned as I was expecting it so, there’s that. Also, I decided to use enums for this part. Given I was going to deal with axe states, enums are particuluarly suited. I have a grand total of five states
- In hand
- In back
- Thrown
- Stuck
- Recalled
I basically use these to determine the corresponding animation states, the current parent, and they also are useful for updating Kratos’s state.
Conclusion and TODOs
Everything is much easier with the right tool. Anyway, next, I’m planning on adding more hits with the axe, so I can quickly get to a point where I can fight ennemies ! Get ready for some troll fight ! Also, I’d like to implement Bezier support for the axe return, so it is more appealing visually.