'RTS Camera' trouble!

G'day guys, second question post. I'll get right down to it, it's quite a dilema.

My scene contains a camera, controlled with the below script. The script allows the camera to be panned forward, backward, left and right with the keyboard, and by moving the mouse within 25px of a screen edge.

Here's the problem.

The camera is angled down by 45 degrees, which made it necessary to add Space.World to the end of the two lines of script that moved the camera forward or backward, to prevent it using it's own downard-facing Y axis. Now I'm trying to implement camera rotation (initially using the left and right mouse buttons for simplicity), the camera moves forward or backwards according to the global Y axis, meaning you can rotate the camera all you like, but you're always going the same direction.

I suppose an adequate mental aid might be imagining you are a tank that can rotate the turret, but can't change the direction.

You can move and rotate fine left and right of course, the X axis is 'self'.

I've been stuck on this for quite a while now. If I could fix it, I'd move on to replace mouse-button rotation with movement of the mouse while the right mouse is pressed. I suspect the real fix would involve finding a way to avoid using Space.World.

Sorry for a long post, but it's a real mongrel. Here's the code thus far.

private var myTransform : Transform;
private var scrollArea = 25;
private var scrollSpeed = 50;

function Update () {
    myTransform = Camera.main.transform;
    var mPosX = Input.mousePosition.x;
    var mPosY = Input.mousePosition.y;

    //Move camera with the arrow keys
    transform.Translate(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"), Space.World);

    //Move camera by moving the mouse to the edge of the screen, RTS-Style
    if (mPosX < scrollArea) {myTransform.Translate(Vector3.right * -scrollSpeed * Time.deltaTime);}
    if (mPosX >= Screen.width-scrollArea) {myTransform.Translate(Vector3.right * scrollSpeed * Time.deltaTime);}
    if (mPosY < scrollArea) {myTransform.Translate(Vector3.forward * -scrollSpeed * Time.deltaTime, Space.World);}
    if (mPosY >= Screen.height-scrollArea) {myTransform.Translate(Vector3.forward * scrollSpeed * Time.deltaTime, Space.World);}

    //Rotate Camera left with LMB 
    if(Input.GetMouseButton(0)) 
    transform.Rotate(0, 2.5, 0, Space.World);

    //Rotate Camera left with RMB
    if(Input.GetMouseButton(1)) 
    transform.Rotate(0, -2.5, 0, Space.World);

}

Hi Ozale,

If manipulating one transform proves difficult for panning and rotating, you simply need to cut down the problem.

1: create an empty gameObject called "CameraPlatform", and attach the camera to it so that the camera transform is 0,0,0

2: make a panning script for the "cameraPlatform" itself

3: make a rotating script for the "camera" that rotate just the camera

alternatively you can combine all in one script, but that's not the point here.

the benefice is clear, you separate the features for way easier transform manip and maths, and you gain extra control, for example if you want the camera to shake or have additionnal movement that are independant of the actual view where the user wants to be.

Hope it's clear,

Bye,

Jean

If I'm understanding you, the effect you want is that when you press the Forward button, the camera moves forward relative to the direction it's currently facing.

One way to do it is to change ALL the Translate's in your code to be relative to Space.Self.

This leaves you with one problem: moving forward pushes the camera in the direction it's facing, down, when you want to glide forward over the surface. Instead of moving in the direction of Vector3.Forward, you could calculate the correct vector ALONG the plane, by projecting the camera's forward vector onto the plane that represents your world's surface. However, I used a simple hack instead: after moving the camera forward and down, I reset the y position to what it was before. I'm not proud of it but it works like a charm. :-)

(A downside to the hack is that forward movement is a little slower than sideways movement, but you can easily compensate for that if you want.)

function Update () {
    myTransform = Camera.main.transform;
    var mPosX = Input.mousePosition.x;
    var mPosY = Input.mousePosition.y;
    var restoreY = myTransform.position.y;

    //Move camera with the arrow keys
    transform.Translate(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"), Space.Self);

    //Move camera by moving the mouse to the edge of the screen, RTS-Style
    if (mPosX < scrollArea) {myTransform.Translate(Vector3.right * -scrollSpeed * Time.deltaTime, Space.Self);}
    if (mPosX >= Screen.width-scrollArea) {myTransform.Translate(Vector3.right * scrollSpeed * Time.deltaTime, Space.Self);}
    if (mPosY < scrollArea) {myTransform.Translate(Vector3.forward * -scrollSpeed * Time.deltaTime, Space.Self);}
    if (mPosY >= Screen.height-scrollArea) {myTransform.Translate(Vector3.forward * scrollSpeed * Time.deltaTime, Space.Self);}

    // Restore original camera height
    myTransform.position.y = restoreY;

    //Rotate Camera left with LMB 
    if(Input.GetMouseButton(0)) 
       transform.Rotate(0, 2.5, 0, Space.World);

    //Rotate Camera left with RMB
    if(Input.GetMouseButton(1)) 
       transform.Rotate(0, -2.5, 0, Space.World);
}