How do I AddForce in the forward direction of another object?

I am making a ball rolling game, and am working on a decent control system, as it has to be fun to play. I am using an orbit camera to view the scene, but I wanted it to always move forward relative to the camera, so pressing “w” will always make the ball roll in the direction you ware pointing the camera, this is mostly to allow strafing control, so you can point the camera down a hill and use “a” and “d” to avoid obstacles, etc, as well as to turn corners fully, a la Super Monkey Ball et al.

I figured an elegant way to do this would be to create a kind of invisible helper at the point of the ball, which would read the y rotation ONLY from the camera, and update itself to match. The reason for the in between object, and to use y ONLY, is to not try and move INTO the ground if the camera is looking down at the ball from above. After spending, HOOOOUUUURS today trying to get Y rotation ONLY from camera and apply it to Y rotation ONLY on my helper (currently a cube, will be changed to an empty game object, it’s just for visual feedback atm), after many, many problems, including rotating half way before unwinding itself like it was tied with elastic, something to do with quaternion angles, I finally have it. The trick was, to use an in between variable to grab the y euler angle from the camera, and put it into the y euler angle of the helper. Here is the script for that:

var PlayerBall : Transform;
var PlayerCam : GameObject;

var angles;

var Rotation = 0.0;


function Update ()
{   
    transform.position = PlayerBall.transform.position;

    angles = PlayerCam.transform.eulerAngles;
    Rotation = angles.y;
    
    transform.eulerAngles = Vector3(0, Rotation, 0);
}

After all this I am a little bit drained. All I want to do now, is to now use the z axis of the helper cube as the forward direction for AddForce on the ball, but any combination of ideas seem to conflict, such as quaternions and floats and such. current movement script is below. How do I make it camera relative?

var MoveSpeed : float = 100;

var Helper : GameObject;

function Update ()
{
	if(Input.GetKey("w"))
	{
		rigidbody.AddForce (Vector3.forward * MoveSpeed);
	}
	
	if(Input.GetKey("s"))
	{
		rigidbody.AddForce (Vector3.back * MoveSpeed);
	}
	
	if(Input.GetKey("a"))
	{
		rigidbody.AddForce (Vector3.left * MoveSpeed);
	}
	
	if(Input.GetKey("d"))
	{
		rigidbody.AddForce (Vector3.right * MoveSpeed);
	}
}

And whilst I am here, how would I best limit the speed of a physics object such as this? I am currently rolling on a flat surface, but when I get to my downhill rolling game, it doesn’t seem like there is any limit to my top speed, but I wouldn’t know how to control it as it is using physics, and not moving a set amount/rate through script. I would like it to SEEM to be increasingly fast, but I still want decent collision detection etc. How do they do it in games such as Super Monkey Ball, or more recently, Rock of Ages? (love that game!)

Thanks in advance for your help!

-WBC

One way to apply force in the direction the camera is facing, is to bring the camera’s forward position down to the level of the ball. So you would do something like:

var v = PlayerCam.transform.forward;
v.y = transform.position.y;
rigidbody.Addforce(v3.normalized * MoveSpeed * Time.deltaTime);  

This will apply force using the forward of the camera but on the ‘y’ plane of the ball. Note this will not instantly make it go in the direction the camera is facing since there is still a current velocity. It just applies force in the direction the camera is facing. If you need it to quickly or instantly change directions, you will need to do some additional work. Note the addtion of Time.deltaTime to the AddForce() call. It will require you to substantially increase your MoveSpeed value (60x most likely).

I actually managed to figure out a solution last night that met my needs. Basically, I load in the helper object as a variable, then I discovered you can use transform.TransformDirection to find which way is forward in relation to the helper and use that direction for the AddForce function. Code for ball movement below:

var MoveSpeed : float = 100;

var Helper : GameObject;

function Update ()
{
	if(Input.GetKey("w"))
	{
		var HelperForward = Helper.transform.TransformDirection (Vector3.forward);
		
		rigidbody.AddForce (HelperForward * MoveSpeed);
	}
	
	if(Input.GetKey("s"))
	{
		var HelperBack = Helper.transform.TransformDirection (Vector3.back);
		
		rigidbody.AddForce (HelperBack * MoveSpeed);
	}
	
	if(Input.GetKey("a"))
	{
		var HelperLeft = Helper.transform.TransformDirection (Vector3.left);
		
		rigidbody.AddForce (HelperLeft * MoveSpeed);
	}
	
	if(Input.GetKey("d"))
	{
		var HelperRight = Helper.transform.TransformDirection (Vector3.right);
		
		rigidbody.AddForce (HelperRight * MoveSpeed);
	}
}

Combine this with high friction in the physics material, and it barely slides at all, and it has a little bit of bounciness! So far, it is perfect, though it may need tweaking when I actually have a downhill level. Also I will add in a jump, and a couple other mechanics, but as far as a controllable rolling ball goes, you can’t ask for much more than this!