Third Person Controller vector Problem

Hey,

So I am making a C# version of the third person controller included in the Lerpz tutorial pack, and I am running into a slight problem where when moving forward/right/left, a small error is introduced into the movement vector, creating a curved movement, when all I want is a straight-ahead movement. Interestingly, no error is introduced when moving backwards. What would cause this slight error in the movement vectors? Any help would be appreciated!

Edit:

After some further testing, I believe the SpringFollowing Camera is introducing the error (passed as the cameraTransform in UpdateSmoothedMovementDirection in the ThirdPersonController), as whenever I hold down “fire2” to snap the camera (snapping every update), the character moves in the correct direction. This leads me to believe that the ApplyPositionDamping function is what is causing the error, as it is called only when ApplySnapping is not called. Script below

using UnityEngine;

using System.Collections;

[AddComponentMenu(“Third Person Camera/Spring Follow Camera”)]

public class SpringFollowCamera : MonoBehaviour

{

public Transform target;

public float distance = 4.0f;

public float height = 1.0f;

public float smoothLag = 0.2f;

public float maxSpeed = 10.0f;

public float snapLag = 0.3f;

public float clampHeadPositionScreenSpace = 0.75f;

public LayerMask lineOfSightMask = 0;



private bool isSnapping = false;

private Vector3 headOffset = Vector3.zero;

private Vector3 centerOffset = Vector3.zero;

private ThirdPersonController controller;

private Vector3 velocity = Vector3.zero;

private float targetHeight = 100000.0f;

void Awake()

{

	CharacterController characterController = (CharacterController)target.collider;

	if(characterController)

	{

		centerOffset = characterController.bounds.center - target.position;

		headOffset = centerOffset;

		headOffset.y = characterController.bounds.max.y - target.position.y;

	}

	if(target)

	{

		controller = target.GetComponent<ThirdPersonController>();

	}

	if(!controller)

	{

		Debug.Log("Assing a target to the camera with a Third person Controller");

	}

}

void LateUpdate()

{

	Vector3 targetCenter = target.position + centerOffset;

	Vector3 targetHead = target.position + headOffset;

	

	if(controller.IsJumping())

	{

		//Only move the camera upwards if the target is very high

		float newTargetHeight = targetCenter.y + height;

		if((newTargetHeight < targetHeight) || (newTargetHeight - targetHeight >5))

		{

			targetHeight = targetCenter.y + height;

		}

	}

	

	//Always update target height while walking

	else

	{

		targetHeight = targetCenter.y + height;

	}

	

	//Snap when user presses Fire2

	if(Input.GetButton("Fire2") && !isSnapping)

	{

		velocity = Vector3.zero;

		isSnapping = true;

	}

	

	if(isSnapping)

	{

		ApplySnapping(targetCenter);

	}

	else

	{

		ApplyPositionDamping(new Vector3(targetCenter.x, targetHeight, targetCenter.z));

	}

	SetUpRotation(targetCenter, targetHead);

}

void ApplySnapping(Vector3 targetCenter)

{

	Vector3 position = transform.position;

	Vector3 offset = position - targetCenter;

	

	offset.y = 0;

	float currentDistance = offset.magnitude;

	

	float targetAngle = target.eulerAngles.y;

	float currentAngle = transform.eulerAngles.y;

	

	currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle,ref velocity.x, snapLag);

	currentDistance = Mathf.SmoothDamp(currentDistance, distance,ref velocity.z, snapLag);

	

	Vector3 newPosition = targetCenter;

	newPosition += Quaternion.Euler(0, currentAngle, 0) * Vector3.back * currentDistance;

	

	newPosition.y = Mathf.SmoothDamp(position.y, targetCenter.y + height,ref velocity.y, smoothLag, maxSpeed);

	

	newPosition = AdjustLineOfSight(newPosition, targetCenter);

	

	transform.position = newPosition;

	

	//Stop snapping, close to target

	if(AngleDistance(currentAngle, targetAngle) < 3.0f)

	{

		isSnapping = false;

		velocity = Vector3.zero;

	}

}

public Vector3 AdjustLineOfSight(Vector3 newPosition, Vector3 target)

{

	RaycastHit hit;

	if(Physics.Linecast(target, newPosition,out hit, lineOfSightMask.value))

	{

		velocity = Vector3.zero;

		return hit.point;

	}

	

	return newPosition;

}

void ApplyPositionDamping(Vector3 targetCenter)

{

	//Attempt to maintain a constant distance on x-z plane

	//Y position is handled with separate sping

	Vector3 position = transform.position;

	Vector3 offset = position - targetCenter;

	offset.y = 0;

	Vector3 newTargetPos = offset.normalized * distance + targetCenter;

	

	Vector3 newPosition;

	

	newPosition.x = Mathf.SmoothDamp(position.x, newTargetPos.x, ref velocity.x, smoothLag, maxSpeed);

	newPosition.y = Mathf.SmoothDamp(position.y, targetCenter.y, ref velocity.y, smoothLag, maxSpeed);

	newPosition.z = Mathf.SmoothDamp(position.z, newTargetPos.z, ref velocity.z, smoothLag, maxSpeed);

		

	newPosition = AdjustLineOfSight(newPosition, targetCenter);

	

	Debug.Log("New Position:" + newPosition);

	transform.position = newPosition;		

}

void SetUpRotation(Vector3 centerPos, Vector3 headPos)

{

	//Find the rotation around the y axis. 

	//When grounded, center camera

	//When jumping, keep the camera rotation, but rotate the camera if character out of view

	//When landing, smoothly interpolate towards centering character

	Vector3 cameraPos = transform.position;

	Vector3 offsetToCenter = centerPos-cameraPos;

	

	//Generate rotation around y axis

	Quaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));

	

	Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;

	transform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);

	

	//Calculate the projected center position and top position

	Ray centerRay = camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 1));

	Ray topRay = camera.ViewportPointToRay(new Vector3(0.5f, clampHeadPositionScreenSpace, 1));

	

	Vector3 centerRayPos = centerRay.GetPoint(distance);

	Vector3 topRayPos = topRay.GetPoint(distance);

	

	float centerToTopAngle = Vector3.Angle(centerRay.direction, topRay.direction);

	

	float heightToAngle = centerToTopAngle / (centerRayPos.y - topRayPos.y);

	

	float extraLookAngle = heightToAngle * (centerRayPos.y - centerPos.y);

	if(extraLookAngle < centerToTopAngle)

	{

		extraLookAngle = 0;

	}

	else 

	{

		extraLookAngle = extraLookAngle - centerToTopAngle;

		transform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0);

	}

}

float AngleDistance(float a, float b)

{

	a = Mathf.Repeat(a, 360f);

	b = Mathf.Repeat(b, 360f);

	

	return Mathf.Abs(b - a);

}

}

//If slow, snap to target direction

     if(moveSpeed < walkSpeed * 0.9f && grounded)

     {

      moveDirection = targetDirection.normalized;

     }

     //Otherwise smoothly turn towards it

     else

     {

      moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);

      moveDirection = moveDirection.normalized;

     }

Have it “snap” every time. Remove the if else, just have it always execute the first part of the code.