Wednesday, March 21, 2012

Hey! [Insert obligatory first post statement here]

I've been messing around with Unity3d for the past week or so, and I have to say, it's very fun and simple to use.

That said, one of the first things that I thought to do after watching a bunch of tutorials and reading into various sample scripts was to implement an intuitive third person camera interface. I've seen several tutorials regarding how to move around using the WASD keys and the like, but not much regarding how to piece together a nice third person camera system. So, I decided to go ahead and make one. 

Please keep in mind that I am a beginnerThere may be code issues here when things start getting more complicated, but this does work fine with a character on a flat plane (and should work for inclines mostly). This covers camera panning and zooming, as well as character movement with respect to the camera.
The first thing that we need to do is handle panning around the player character. I created a sphere object (as our player character), gave it the Rigidbody property, and created a basic floor out of a cube for  our player to run around on. I gave the scene a Point Light object to see everything better, and then started the scripting.

Luckily, Unity3d has a standard asset script that gives us basic mouse-based camera control. The script is called MouseOrbit.js, and can be found by searching through the Standard Assets or at Standard Assets > Scripts > Camera Scripts > MouseOrbit. This script basically takes a target as a parameter (in our case, the sphere), and circles around that target based on mouse controls. 

I thought that this should be tweaked in a couple of ways, so here's what I changed about it:

1. Only rotate around the target object when the right mouse is held down ( this seems to be how most third-person RPGs do things these days ).

2. Implement a zoom function using the mouse wheel!

I won't get into the details of how I did this, I'll just post my modified MouseOrbit.js file. It should be rather easy to follow:

With that script attached to our Main Camera object, we should be able to perform all of our cool new functions. Zooming can be done by scrolling in and out, and circular panning around our sphere (assuming that the sphere is attached to the script as the target) will only happen if the Right Mouse button is held down.

Now that that is working, the obvious next step would be to be able to move our character around, so that's exactly what I decided to do!

We can create a new javascript (I named mine MoveCharacter.js) to attach to our character to perform movement relative to the camera.

Moving our object with respect to the camera is a bit tricky, as you'll see. Initially I thought this would be as simple as adding to Z to move forward, subtracting from Z to move backward, and so on. However, this will only move our character in one direction, regardless of the camera's position. This means that, even if our camera is facing west, our character  will still only move north when we press the 'w' key. This is clearly a problem (but we'll fix it)!

We need to perform a little trigonometry to get our sphere moving in the proper direction. I had a little bit of help from the community over at Stack Overflow with this one. As it turns out, moving forward in space can be done like so:

 First, we take the x and z coordinates of our object with the Sin and Cos values of our current rotation and place them into a new vector (Sin(rotation), 0, Cos(rotation) ). This is our displacement vector, which adjusts for the rotation of our object.

Second, we take this displacement vector and perform our movement functions on it -- In our case, we want to multiply it by our speed value and adjust it for slower computers using our delta time

Lastly, we take this new displacement vector, adjusted for rotation and applied speed, and we add it to our position in space.

The resultant code for moving forward using the 'w' key can be implemented inside of our update function as follows:

Note: the xDisplacement, yDisplacement, and displacement variables must be defined before we can use them!

Moving backwards is basically the same, except we want to subtract our displacement instead of adding it. The code for moving backwards is as simple as mapping our input key to "s" instead of "w" and replacing line 7 in the above code with:

transform.position -= displacement;

Moving left and right, however, is a little bit more tricky, but it's nothing unmanageable. Basically all that we need to do is add 90 degrees to our angle, and follow the same basic instructions as before. If you look at a Cartesian plane and assess what we're doing so far, this makes perfect sense. What we're essentially doing is pretending that our object is actually facing directly to the right of its actual orientation, and moving forward and backward based on that rotation. This moves our character left and right. 

That's basically everything that this script does (there are different speeds for moving in different directions, but that's easy to grasp in the code), so I'll just go ahead and post the full MoveCharacter.js script for you here:

Attaching this script to your main character object (whatever it may be) will allow movement based upon its rotation. 

Hope you enjoyed this! If you have any questions or suggestions or anything, just post a comment!