Third Person Camera 90% complete

After a lot of trial and error I have a working Third Person camera that takes the inputs from the left onscreen joystick. You will notice two problems

  1. The animation does not work
  2. The character does not turn to the appropriate direction, and just strafes around always facing the same way.

Attached is the exported project, its pretty much just lerpz as the character and a plane to walk around on, should run fine on your iPhone.
If anyone can give me some help on solving these two issues I would be very gratefull!

111021–4259–$thirdpersonview_202.unitypackage (6.51 MB)

Haven’t looked at your code yet but this is what I’m using for stub AI in my current project.

function FixedUpdate()
{
   MoveToward(Camera.main.transform.position);
}


//------------------------------------------------------
// Rotate Toward and Move to Target
//------------------------------------------------------
function MoveToward(pos : Vector3) 
{
      var targetRotation = Quaternion.LookRotation(pos - transform.position, Vector3.up);
      targetRotation.x = 0;
      targetRotation.z = 0;
      transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .05);
      moveDirection = transform.TransformDirection(0, 0, speed);
      rigidbody.MovePosition(rigidbody.position + moveDirection);
}

Oh I’m sorry. The code I just gave you was for enemy AI. I read your post too quickly.

I just looked at your project and now understand what you are asking. Let me look again.

You animation works but it’s just not set to loop.

Select Lerpz, then animation and set the Wrap Mode to Loop. Now he walks.

My camera works like MySims:

  • Zoom in or out while focusing on the player
  • Rotate around the player
  • Move left/right/up/down/diagonally relative to camera

The problem I had was making the camera rotate around the player while being able to rotate the player relative to the camera

To solve this problem, I created a player object and attached the camera to that. I fixed the object’s rotation and then attached a player model as a separate object next to the camera.

Using a separate variable to keep track of the current rotation angle of the camera, I was able to calculate the relative direction to move the object irrespective of what angle the camera is and using the camera look direction I was able to determine the relative direction to rotate the player model to to make it look like it is moving toward/ away from the camera…

It took a lot of work, but it works fine.
Unfortunately I cannot show you the code as the way I work I had to split the code into separate files that combine with other work so to extract all the needed stuff would take forever…

At least this should give you a starting point…

static var instance : InputManager;
instance =  FindObjectOfType(InputManager);

var speed = 6.0;
var jumpSpeed = 8.0;
var gravity = 20.0;
var theCam					: Camera;
var avatar					: Transform;
var avatarMesh				: Transform;
var PCPrefab				: CharacterController = null;

private var theMenu			: MenuDisplay;

private var angles			= new Array(0, 45, 90, 135, 180, 225, 270, 315);
private var moveDirection	= Vector3.zero;
var grounded				: boolean = true;
var camRotSpeed				: float = 1.0;
private var	newAngle		: float = 0;

var isJumping				: boolean = false;
private var isDoubleJumping	: boolean = false;

function SetActiveCam()
{
	Globals.activeCam = (Globals.camMode == eCamMode.FP) ?Globals.PC.Find("FPCam").camera : Globals.PC.Find("TPCam").camera;
}

function testForCamChange()
{
	if (Input.GetButtonDown("ToggleView"))
	{
		Globals.camMode = (Globals.camMode == eCamMode.TP) ? eCamMode.FP : eCamMode.TP;
		SetActiveCam();
		Globals.PC.Find("FPCam").camera.enabled = Globals.camMode == eCamMode.FP;
		Globals.PC.Find("TPCam").camera.enabled = Globals.camMode == eCamMode.TP;

		ML  = Globals.PC.GetComponent("MouseLook");
		
		if (Globals.camMode == eCamMode.FP)
		{
			ML.enabled = true;
			ML.originalRotation = avatar.localRotation;				
			transform.rotation = avatar.localRotation;
			avatar.localRotation = Quaternion.identity;
		} else
		{
			ML.enabled = false;
			avatar.localRotation = transform.rotation;
			transform.rotation = Quaternion.identity;
		}
	}
}

function UpdateAvatarRotation()
{
		avatarDirection = theCam.transform.eulerAngles;
		if (Input.GetAxis("Horizontal") < 0)
		{
			if (Input.GetAxis("Vertical") < 0)
				avatarAngle = 5; else
			if (Input.GetAxis("Vertical") > 0)
				avatarAngle = 7; else
				avatarAngle = 6;
		} else
		if (Input.GetAxis("Horizontal") > 0)
		{
			if (Input.GetAxis("Vertical") < 0)
				avatarAngle = 3; else
			if (Input.GetAxis("Vertical") > 0)
				avatarAngle = 1; else
				avatarAngle = 2;
		} else
		{
			if (Input.GetAxis("Vertical") < 0)
				avatarAngle = 4; else
				avatarAngle = 0;
		}
		newAngle = avatarDirection.y + angles[avatarAngle];
		if ( newAngle > 360)
			newAngle -= 360; else
		if ( newAngle < 0)
			newAngle += 360;

		bla = avatar.eulerAngles;
		bla.y = newAngle;
		avatar.eulerAngles = bla;
}

function handleWalkingKeys()
{
	if (grounded)
	{
		if (!Globals.activeCam)
			SetActiveCam();
			
		// We are grounded, so recalculate movedirection directly from axes
		moveDirection = Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
		moveDirection = Globals.activeCam.transform.TransformDirection(moveDirection) * speed;
//		moveDirection = theCam.transform.TransformDirection(moveDirection) * speed;
		moveDirection.y = 0;

		if (Input.GetButton ("Jump")  grounded)
		{
			moveDirection.y = jumpSpeed;
			Globals.playerAnim.animState = eAnimState.Jumping;
			isJumping = true;
		}

		if ( Input.GetButton("Horizontal") || Input.GetButton("Vertical") )
		{
			UpdateAvatarRotation();		
			Globals.playerAnim.animState = eAnimState.Walking;
		} else
		{
			Globals.playerAnim.animState = eAnimState.Idle;
		}
	}
		
	moveDirection.y -= gravity * Time.deltaTime;
	var flags = PCPrefab.Move(moveDirection * Time.deltaTime);
	grounded = (flags  CollisionFlags.CollidedBelow) != 0;

//	PCPrefab.transform.position.y = Globals.terrain.GetInterpolatedHeight(target.transform.position.x / Globals.terrain.size.x, target.transform.position.z / Globals.terrain.size.z);
}

function handleJumpingKeys()
{
	if (Input.GetButton ("Jump")  grounded)
	{
		moveDirection.y = jumpSpeed;
	}

	moveDirection.y -= gravity * Time.deltaTime;

	// Move the controller	
	var flags = PCPrefab.Move(moveDirection * Time.deltaTime);
	grounded = (flags  CollisionFlags.CollidedBelow) != 0;
	isJumping = grounded;
}

private var rot		: Vector3;
var distance 		= 4.0;
var minDistance 	= 2.0;
var maxDistance 	= 10.0;

var xSpeed			= 3.0;
var zoomSpeed		= 12.0;

function handleCameraKeys()
{
    rot.x += Input.GetAxis("CamRotate") * xSpeed * 0.5;
    distance -= Input.GetAxis("CamZoom") * zoomSpeed * 0.5;
		
	distance = globalFunctions.ClampAngle(distance, minDistance, maxDistance);
 	height = distance * 0.7;

    var rotation = Quaternion.Euler(0, rot.x, 0);
    var position = rotation * Vector3(0.0, height, -distance) + avatarMesh.position;
    
    theCam.transform.position = position;
    theCam.transform.LookAt(avatarMesh.position + Vector3(0,2,0));
}

//keys used for once off pressing
function Update()
{
	switch(Globals._mode)
	{
		case ePlaymode.Playing:
			testForCamChange();
			TestForMenu();
			TestForSpawnPointKeys();
			TestForBattleMode();
			break;
	}
}

//keys used with motion
var lastmode : ePlaymode;
function FixedUpdate()
{
	switch(Globals._mode)
	{
		case ePlaymode.Playing:
			handleWalkingKeys();
			if (Globals.camMode == eCamMode.TP)
				handleCameraKeys();
			break;
	}
}