Making a camera that follows a rigidbodied sphere.

Okay, last question before I get my game going. I need to make a script that allows a camera to follow and rotate around the ball that I am controlling. See my other posts:

http://answers.unity3d.com/questions/140150/rigidbodyaddtorqueaddforce-question.html?viewedQuestions=139967

http://answers.unity3d.com/questions/139967/create-a-quotfreequot-rolling-ball-controlled-by-p.html?viewedQuestions=136012

I tried the preloaded smoothfollow script. But when I apply it, the camera seems to not be pointed straight, it looks about 90 degrees off of the correct placement. So if I was to control it to go forward, it would look like it’s going to the left, not forward. Not to mention, when I do use it, the camera skips around while rotating, almost like it’s jumping from a point to another point. Here is the code for the ball:

function FixedUpdate () {
if (Input.GetButton("W"))
{
rigidbody.AddTorque (Vector3.forward * 2);
rigidbody.AddForce (Vector3.forward * 2);
}


if (Input.GetButton("S"))
{

rigidbody.AddTorque (-Vector3.forward * 2);
rigidbody.AddForce (-Vector3.forward * 2);
}

if (Input.GetButton("A"))
{
rigidbody.AddTorque (Vector3.left * 2);
rigidbody.AddForce (Vector3.left * 2);
}


if (Input.GetButton("D"))
{
rigidbody.AddTorque (Vector3.right * 2);
rigidbody.AddForce (Vector3.right * 2);
}
}

And here is the code for the Smoothfollow script that I tried before. Although most of everyone should already have it:

/*
This camera smoothes out rotation around the y-axis and height.
Horizontal Distance to the target is always fixed.

There are many different ways to smooth the rotation but doing it this way gives you a lot of control over how the camera behaves.

For every of those smoothed values we calculate the wanted value and the current value.
Then we smooth it using the Lerp function.
Then we apply the smoothed values to the transform's position.
*/

// The target we are following
var target : Transform;
// The distance in the x-z plane to the target
var distance = 10.0;
// the height we want the camera to be above the target
var height = 5.0;
// How much we 
var heightDamping = 2.0;
var rotationDamping = 3.0;

// Place the script in the Camera-Control group in the component menu
@script AddComponentMenu("Camera-Control/Smooth Follow")


function LateUpdate () {
	// Early out if we don't have a target
	if (!target)
		return;
	
	// Calculate the current rotation angles
	wantedRotationAngle = target.eulerAngles.y;
	wantedHeight = target.position.y + height;
		
	currentRotationAngle = transform.eulerAngles.y;
	currentHeight = transform.position.y;
	
	// Damp the rotation around the y-axis
	
	// Damp the height
	currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);

	// Convert the angle into a rotation
	currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
	
	// Set the position of the camera on the x-z plane to:
	// distance meters behind the target
	transform.position = target.position;
	transform.position -= currentRotation * Vector3.forward * distance;

	// Set the height of the camera
	transform.position.y = currentHeight;
	
	// Always look at the target
	transform.LookAt (target);
}

Thanks for the help ahead of time UnityAnswers!

The problem is that the script assumes you are an upright person, with your Y-axis straight up, so all of your turning is on that Y-axis with the blue arrow (z) the way you are moving.

But, the ball is a chaotic swirling, with Y not even close to the way you are facing (start moving and switch to scene view – Y will be tumbling head over heels. Imagine the camera trying to put itself the way the blue (forwards) arrow is smashing around.

A fix is to align the camera on the way the ball is moving (code has been tested):

currentRotationAngle = transform.eulerAngles.y; // need to move this line up

// Calculate the current rotation angles
//wantedRotationAngle = target.eulerAngles.y; <-- old line
MV = target.rigidbody.velocity; MV.y = 0; // "flat" speed of ball
if(MV==Vector3.zero) wantedRotationAngle = currentRotationAngle;
else // get the Y-spin of ball's speed:
  wantedRotationAngle = Quaternion.LookRotation(MV).eulerAngles.y;

This stays “behind” the ball, but makes a new problem. It’s hard to steer with ASDW (A isn’t left – it’s West.) You’d need to rewrite Ballmove to apply local thrust instead of global (drive around with a fixed cam and you’ll see the problem.)

It might be better to just always put the camera 10 south of the ball, and forget the fancy “behind” stuff.

I don’t know if this is what you’re looking for, but there it goes: with this script, the camera follows the target object while it moves on the ZX plane as if both were tied by a rope of distance length. The movement smoothness is controlled by damp, and the camera is kept at a maximum 45 degrees angle from the ground:

var target: Transform;
var damp: float = 0.2;
var distance: float = 50;

function Update(){

	damp = Mathf.Clamp(damp, 0.01, 10); // clamps damping factor
	var pCam = transform.position;
	var pTarget = target.position;
	var diff: Vector3 = pTarget - pCam;  // diff = difference between positions
	var dist = diff.magnitude;  // dist = distance between them
	if (Mathf.Abs(diff.y) < 0.7*distance){
		diff.y = 0;  // doesn't modify camera height unless angle > 45
	} 
	if (dist>distance){ // if distance too big...
		diff *= 1-distance/dist; // diff = position error
		// move a FPS independent little step towards the ideal position
		transform.position = pCam + diff * Time.deltaTime/damp;
	}
	transform.LookAt(pTarget);
}