RTS Camera script

I am working on a non-game mapping project and I have been looking for help in scripting the main camera to function like those in RTS games like C&C, Age of Empires, ETC. I have been looking for a good tutorial or guide on the subject. Any help or direction would be greatly appreciated.

thanks,
Rob

2 Likes

more specific? you could use the arrow keys to move, and the outside of the screen to move also when the mouse is over it.

The camera should be able to pan with the arrow keys, but also be able to rotate around a selected object or the map itself.

the pan should be using translate. more specific about the rotating part?

I’m afraid I don’t know any good tutorials but I worked out how to make one by looking up GetAxis in the Scripting Reference.
Create a GameObject in the Hierarchy viewer
Attach script like this to GameObject

Attach Camera to GameObject at position 0,0,0, rotation 50,0,0
(NOTE: this means the camera will rotate around the bottom of the screen. If you want it to rotate around the center of the screen offset it back from the GameObject slightly. I think… not sure if that’s a great solution but it should work…I think)

I’m afraid I can’t think off the top of my head of a way to rotate around selected object…Do RTS cameras allow that? I haven’t played one in a long time, but it sounds like it would get a bit weird if you select a unit, panned away then tried to rotate the screen, still with the unit as the focal point.

Edit: Btw I came onto the forum with my own question about making an RTS camera and in the process of answering yours I realised a solution to my own. Thanks! :slight_smile:

Hi,
Aron has a wonderful setup for getting started.

Check out his site at: http://www.arongranberg.com/

An example of his camera is here: A* Pathfinding Project

Sorry about the delay in replying. I have downloaded the Pathfinder Project from arongranberg.com and looked at the camera script for it as well as played around with it. It is moving in the right direction, but I think the controls need to be simplified a bit more since the main user for the project I am working on isn’t a gamer.

1 Like

Here’s a simple camera script, which is part of a larger RTS game starter kit I’m working on.

var ScrollSpeed:float = 15;
var ScrollEdge:float = 0.01;

private var HorizontalScroll:int = 1;
private var VerticalScroll:int = 1;
private var DiagonalScroll:int = 1;

var PanSpeed:float = 10;

var ZoomRange:Vector2 = Vector2(-5,5);
var CurrentZoom:float = 0;
var ZoomZpeed:float = 1;
var ZoomRotation:float = 1;

private var InitPos:Vector3;
private var InitRotation:Vector3;



function Start()
{
	//Instantiate(Arrow, Vector3.zero, Quaternion.identity);
	
	InitPos = transform.position;
	InitRotation = transform.eulerAngles;
	
}

function Update () 
{
	//PAN
	if ( Input.GetKey("mouse 2") )
	{
		//(Input.mousePosition.x - Screen.width * 0.5)/(Screen.width * 0.5)
		
		transform.Translate(Vector3.right * Time.deltaTime * PanSpeed * (Input.mousePosition.x - Screen.width * 0.5)/(Screen.width * 0.5), Space.World);
		transform.Translate(Vector3.forward * Time.deltaTime * PanSpeed * (Input.mousePosition.y - Screen.height * 0.5)/(Screen.height * 0.5), Space.World);

	}
	else
	{
		if ( Input.GetKey("d") || Input.mousePosition.x >= Screen.width * (1 - ScrollEdge) )
		{
			transform.Translate(Vector3.right * Time.deltaTime * ScrollSpeed, Space.World);
		}
		else if ( Input.GetKey("a") || Input.mousePosition.x <= Screen.width * ScrollEdge )
		{
			transform.Translate(Vector3.right * Time.deltaTime * -ScrollSpeed, Space.World);
		}
		
		if ( Input.GetKey("w") || Input.mousePosition.y >= Screen.height * (1 - ScrollEdge) )
		{
			transform.Translate(Vector3.forward * Time.deltaTime * ScrollSpeed, Space.World);
		}
		else if ( Input.GetKey("s") || Input.mousePosition.y <= Screen.height * ScrollEdge )
		{
			transform.Translate(Vector3.forward * Time.deltaTime * -ScrollSpeed, Space.World);
		}
	}
	
//ZOOM IN/OUT
	
	CurrentZoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 1000 * ZoomZpeed;
	
	CurrentZoom = Mathf.Clamp(CurrentZoom,ZoomRange.x,ZoomRange.y);
	
	transform.position.y -= (transform.position.y - (InitPos.y + CurrentZoom)) * 0.1;
	transform.eulerAngles.x -= (transform.eulerAngles.x - (InitRotation.x + CurrentZoom * ZoomRotation)) * 0.1;
	
}
  • If you roll the mouse wheel the camera will zoom in/out.
  • If you go to the edges of the screen the camera will scroll.
  • The camera will also scroll if you press W/A/S/D.
  • If you hold the Middle mouse button and move you will pan across the screen.

Attach this to a camera ( The camera I had was rotated to 60 in the X axis ). You can tweak the values from the inspector.

Tell me how it goes for you.

Sorry about the delay. I tested out the script you posted and it works for the most part. The only problems with the script is a lack of rotation on the Y axis and the camera tests to act very strange when it goes below the ground plane. This is corrected by changing the Zoom Range x variable to 0. I will work with the script some more this week along with our web programmer to see how it works for us overall.

Thanks,
Rob

I have been working with the script kindly provided by Puppeteer with the focus on adding a rotation component to the camera using the left mouse button plus the control key. However, since I am only a noob in programming, I seem to be having a problem figuring out the right script/input to get the camera to rotate on the Y axis. Here is the code I have added to the camera script:

var ScrollSpeed:float = 15;
var ScrollEdge:float = 0.01;

private var HorizontalScroll:int = 1;
private var VerticalScroll:int = 1;
private var DiagonalScroll:int = 1;

var PanSpeed:float = 10;

var ZoomRange:Vector2 = Vector2(0,10);
var CurrentZoom:float = 0;
var ZoomZpeed:float = 1;
var ZoomRotation:float = 1;

//camera rotation on Y axis
var RotationSpeed : float = 1;
var CamRotY : Vector3;

private var InitPos:Vector3;
private var InitRotation:Vector3;



function Start()
{
	//Instantiate(Arrow, Vector3.zero, Quaternion.identity);
	
	InitPos = transform.position;
	InitRotation = transform.eulerAngles;
	
}

function Update () 
{
	//PAN
	if ( Input.GetKey("mouse 2") )
	{
		//(Input.mousePosition.x - Screen.width * 0.5)/(Screen.width * 0.5)
		
		transform.Translate(Vector3.right * Time.deltaTime * PanSpeed * (Input.mousePosition.x - Screen.width * 0.5)/(Screen.width * 0.5), Space.World);
		transform.Translate(Vector3.forward * Time.deltaTime * PanSpeed * (Input.mousePosition.y - Screen.height * 0.5)/(Screen.height * 0.5), Space.World);

	}
	else
	{
		if ( Input.GetKey("d") || Input.mousePosition.x >= Screen.width * (1 - ScrollEdge) )
		{
			transform.Translate(Vector3.right * Time.deltaTime * ScrollSpeed, Space.World);
		}
		else if ( Input.GetKey("a") || Input.mousePosition.x <= Screen.width * ScrollEdge )
		{
			transform.Translate(Vector3.right * Time.deltaTime * -ScrollSpeed, Space.World);
		}
		
		if ( Input.GetKey("w") || Input.mousePosition.y >= Screen.height * (1 - ScrollEdge) )
		{
			transform.Translate(Vector3.forward * Time.deltaTime * ScrollSpeed, Space.World);
		}
		else if ( Input.GetKey("s") || Input.mousePosition.y <= Screen.height * ScrollEdge )
		{
			transform.Translate(Vector3.forward * Time.deltaTime * -ScrollSpeed, Space.World);
		}
	}
	
//ZOOM IN/OUT
	
	CurrentZoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 1000 * ZoomZpeed;
	
	CurrentZoom = Mathf.Clamp(CurrentZoom,ZoomRange.x,ZoomRange.y);
	
	transform.position.y -= (transform.position.y - (InitPos.y + CurrentZoom)) * 0.1;
	transform.eulerAngles.x -= (transform.eulerAngles.x - (InitRotation.x + CurrentZoom * ZoomRotation)) * 0.1;

//ROTATION
	//Use Mouse 1 + Ctrl key to rotate the camera around the Y axis
	if (Input.GetAxis ("mouse 1")  Input.GetKey ("CTRL")){
		transform.Rotate (CamRotY, RotationSpeed * Time.deltaTime, Space.World);
	}
}

Any ideas or help would be greatly appreciated.

Hi,
great work BUT I have just 2d top down game camera i rotated 90 on X and is orthographic. How can I set zoom in/out just on one axis(+/- Y axis)?
Thank you for help.

Now if we want to add rotation - to the left pressing ā€œQā€ button and to the right pressing ā€œEā€ button adding to the code something like this:

........
else if ( Input.GetKey("q"))

        {

            transform.Rotate(Vector3.up * Time.deltaTime * -ScrollSpeed, Space.World);

        }
        
        else if ( Input.GetKey("e"))

        {

            transform.Rotate(Vector3.down * Time.deltaTime * -ScrollSpeed, Space.World);

        }
...................

We have now rotation but when we move by W/A/S/D it will follow the axis original cordinates not the actual view coordinates:

If I rotate the view to the right at 90 degrees by pressing ā€˜E’ button and then press ā€˜W’ button, the camera will move to the left now!! and not forward accordingly to my view…

So I want to rotate my camera transform.Rotate(Vector3.up * Time.deltaTime * -ScrollSpeed, Space.World);
and move accordingly actual view…(like in Wasteland2)
Exactly what I mean

Some suggestions???

I took the Javascript version and adapted it a bit for my needs and converted it to C#. It uses the added Q/E for rotation, makes the panning work when the camera is rotated. It also changes so that the camera rotates near the left/right edges instead of panning. For my needs the camera needs to zoom out much higher, so the zoomRange is larger. Also added a max zoom angle so that the camera doesn’t flip around when it looks straight down.

public class RTSCamera : MonoBehaviour {

	
	public float ScrollSpeed = 15;
	
	public float ScrollEdge = 0.1f;
	
	public float PanSpeed = 10;
	
	public Vector2 zoomRange = new Vector2( -10, 100 );
	
	public float CurrentZoom = 0;
	
	public float ZoomZpeed = 1;
	
	public float ZoomRotation = 1;

	public Vector2 zoomAngleRange = new Vector2( 20, 70 );

	public float rotateSpeed = 10;

	private Vector3 initialPosition;
	
	private Vector3 initialRotation;
	

	void Start () {
		initialPosition = transform.position;		
		initialRotation = transform.eulerAngles;
	}
	

	void Update () {
		// panning		
		if ( Input.GetMouseButton( 0 ) ) {
			transform.Translate(Vector3.right * Time.deltaTime * PanSpeed * (Input.mousePosition.x - Screen.width * 0.5f) / (Screen.width * 0.5f), Space.World);
			transform.Translate(Vector3.forward * Time.deltaTime * PanSpeed * (Input.mousePosition.y - Screen.height * 0.5f) / (Screen.height * 0.5f), Space.World);
		}
		
		else {
			if ( Input.GetKey("d") ) {				
				transform.Translate(Vector3.right * Time.deltaTime * PanSpeed, Space.Self );	
			}
			else if ( Input.GetKey("a") ) {				
				transform.Translate(Vector3.right * Time.deltaTime * -PanSpeed, Space.Self );				
			}

			if ( Input.GetKey("w") || Input.mousePosition.y >= Screen.height * (1 - ScrollEdge) ) {				
				transform.Translate(Vector3.forward * Time.deltaTime * PanSpeed, Space.Self );				
			}
			else if ( Input.GetKey("s") || Input.mousePosition.y <= Screen.height * ScrollEdge ) {			
				transform.Translate(Vector3.forward * Time.deltaTime * -PanSpeed, Space.Self );				
			}	

			if ( Input.GetKey("q") || Input.mousePosition.x <= Screen.width * ScrollEdge ) {
				transform.Rotate(Vector3.up * Time.deltaTime * -rotateSpeed, Space.World);
			}
			else if ( Input.GetKey("e") || Input.mousePosition.x >= Screen.width * (1 - ScrollEdge) ) {
				transform.Rotate(Vector3.up * Time.deltaTime * rotateSpeed, Space.World);
			}
		}

		// zoom in/out
		CurrentZoom -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 1000 * ZoomZpeed;

		CurrentZoom = Mathf.Clamp( CurrentZoom, zoomRange.x, zoomRange.y );

		transform.position = new Vector3( transform.position.x, transform.position.y - (transform.position.y - (initialPosition.y + CurrentZoom)) * 0.1f, transform.position.z );

		float x = transform.eulerAngles.x - (transform.eulerAngles.x - (initialRotation.x + CurrentZoom * ZoomRotation)) * 0.1f;
		x = Mathf.Clamp( x, zoomAngleRange.x, zoomAngleRange.y );

		transform.eulerAngles = new Vector3( x, transform.eulerAngles.y, transform.eulerAngles.z );
	}
}
1 Like

Thx saved me alot of time (shame unity don’t have RTS camera by default script)

Here’s another one that more closely emulates the scene view RTS

  • has a quadratic panspeed curve.
  • ā€˜a’ and ā€˜d’ translate instead of rotate the camera
  • scrollwheel zoom affects the camera’s field of view instead of the the camera’s translation
/*
* Copyright (c) 2014, Roger Lew (rogerlew.gmail.com)
* Date: 5/12/2015
* License: BSD (3-clause license)
*
* The project described was supported by NSF award number IIA-1301792
* from the NSF Idaho EPSCoR Program and by the National Science Foundation.
*
*/

using UnityEngine;
using System.Collections;

namespace VTL.RTSCamera
{
    public class RTSCamera : MonoBehaviour
    {
        // WASDQE Panning
        public float minPanSpeed = 0.1f;    // Starting panning speed
        public float maxPanSpeed = 1000f;   // Max panning speed
        public float panTimeConstant = 20f; // Time to reach max panning speed

        // Mouse right-down rotation
        public float rotateSpeed = 10; // mouse down rotation speed about x and y axes
        public float zoomSpeed = 2;    // zoom speed

        float panT = 0;
        float panSpeed = 10;
        Vector3 panTranslation;
        bool wKeyDown = false;
        bool aKeyDown = false;
        bool sKeyDown = false;
        bool dKeyDown = false;
        bool qKeyDown = false;
        bool eKeyDown = false;
      
        Vector3 lastMousePosition;
        new Camera camera;

        void Start()
        {
            camera = GetComponent<Camera>();
        }

        void Update()
        {
            //
            // WASDQE Panning

            // read key inputs
            wKeyDown = Input.GetKey(KeyCode.W);
            aKeyDown = Input.GetKey(KeyCode.A);
            sKeyDown = Input.GetKey(KeyCode.S);
            dKeyDown = Input.GetKey(KeyCode.D);
            qKeyDown = Input.GetKey(KeyCode.Q);
            eKeyDown = Input.GetKey(KeyCode.E);

            // determine panTranslation
            panTranslation = Vector3.zero;
            if (dKeyDown && !aKeyDown)
                panTranslation += Vector3.right * Time.deltaTime * panSpeed;
            else if (aKeyDown && !dKeyDown)
                panTranslation += Vector3.left * Time.deltaTime * panSpeed;

            if (wKeyDown && !sKeyDown)
                panTranslation += Vector3.forward * Time.deltaTime * panSpeed;
            else if (sKeyDown && !wKeyDown)
                panTranslation += Vector3.back * Time.deltaTime * panSpeed;

            if (qKeyDown && !eKeyDown)
                panTranslation += Vector3.down * Time.deltaTime * panSpeed;
            else if (eKeyDown && !qKeyDown)
                panTranslation += Vector3.up * Time.deltaTime * panSpeed;
            transform.Translate(panTranslation, Space.Self);

            // Update panSpeed
            if (wKeyDown || aKeyDown || sKeyDown ||
                dKeyDown || qKeyDown || eKeyDown)
            {
                panT += Time.deltaTime / panTimeConstant;
                panSpeed = Mathf.Lerp(minPanSpeed, maxPanSpeed, panT * panT);
            }
            else
            {
                panT = 0;
                panSpeed = minPanSpeed;
            }

            //
            // Mouse Rotation
            if (Input.GetMouseButton(1))
            {
                // if the game window is separate from the editor window and the editor
                // window is active then you go to right-click on the game window the
                // rotation jumps if  we don't ignore the mouseDelta for that frame.
                Vector3 mouseDelta;
                if (lastMousePosition.x >= 0 &&
                    lastMousePosition.y >= 0 &&
                    lastMousePosition.x <= Screen.width &&
                    lastMousePosition.y <= Screen.height)
                    mouseDelta = Input.mousePosition - lastMousePosition;
                else
                    mouseDelta = Vector3.zero;

                var rotation = Vector3.up * Time.deltaTime * rotateSpeed * mouseDelta.x;
                rotation += Vector3.left * Time.deltaTime * rotateSpeed * mouseDelta.y;
                transform.Rotate(rotation, Space.Self);

                // Make sure z rotation stays locked
                rotation = transform.rotation.eulerAngles;
                rotation.z = 0;
                transform.rotation = Quaternion.Euler(rotation);
            }

            lastMousePosition = Input.mousePosition;

            //
            // Mouse Zoom
            camera.fieldOfView -= Input.mouseScrollDelta.y * zoomSpeed;
        }
    }
}
1 Like

This is a RTS camera I’have created some time ago. Maybe it can help someone.
[Post]
[Github link]

My requirements were probably a little unusual but since I started from roger_lew’s code, I figured I’d share the results. In my case movement is over a large circular area (2000 unit diameter), so I clamp the camera distance from the origin and the movement speeds are cranked up quite a bit. Altitude is fixed (y=400, again, very large area) so movement is purely in XZ. The game is completely mouse-controlled, so the control scheme is a bit different but it feels natural – left button moves forward, right button moves backwards. You can rotate while moving. Press both buttons to rotate without movement. I also restrict the FOV zoom to min/max.

I know none of this is standard RTS but maybe some of the other features will be useful to somebody.

using UnityEngine;

public class CameraMovement : MonoBehaviour
{
    // Left mouse button: Move forward with rotation
    // Right mouse button: Move backward with rotation
    // Both buttons: Rotate without movement

    // Limits
    float startFOV = 60;
    float minFOV = 15f;
    float maxFOV = 90f;
    float maxDistance = 900f; // from 0,0,0

    // Movement (left/right mouse)
    float minMoveSpeed = 250f;
    float maxMoveSpeed = 700f;
    float moveRampTime = 5f;

    // Rotation (both mouse buttons)
    float rotateSpeed = 6f;

    float zoomSpeed = 3f;

    Camera cam;
    float movementTime = 0;
    float movementSpeed = 10;
    Vector3 lastMousePosition;

    void Awake()
    {
        cam = GetComponent<Camera>();
        cam.fieldOfView = startFOV;
    }

    void LateUpdate()
    {
        bool b0 = Input.GetMouseButton(0);
        bool b1 = Input.GetMouseButton(1);

        // Movement (Left: forward, Right: backward)
        Vector3 translate = Vector3.zero;
        if(b0 != b1)
        {
            float direction = (b0) ? 1 : -1;
            translate = transform.forward.normalized * direction * Time.deltaTime * movementSpeed;
            translate.y = 0f;
            translate = Vector3.ClampMagnitude(
               new Vector3(transform.position.x, 0f, transform.position.z) + translate,
               maxDistance);
            translate.y = transform.position.y;
            transform.position = translate;

            movementTime += Time.deltaTime / moveRampTime;
            movementSpeed = Mathf.Lerp(minMoveSpeed, maxMoveSpeed, movementTime * movementTime);
        }
        else
        {
            movementTime = 0;
            movementSpeed = minMoveSpeed;
        }

        // Rotation (either button)
        if(b0 || b1)
        {
            // if the game window is separate from the editor window and the editor
            // window is active then you go to right-click on the game window the
            // rotation jumps if  we don't ignore the mouseDelta for that frame.
            Vector3 mouseDelta;
            if(lastMousePosition.x >= 0
                && lastMousePosition.y >= 0 
                && lastMousePosition.x <= Screen.width 
                && lastMousePosition.y <= Screen.height)
                    mouseDelta = Input.mousePosition - lastMousePosition;
            else
                mouseDelta = Vector3.zero;

            Vector3 rotation = Vector3.up * Time.deltaTime * rotateSpeed * mouseDelta.x;
            rotation += Vector3.left * Time.deltaTime * rotateSpeed * mouseDelta.y;
            transform.Rotate(rotation, Space.Self);

            // Make sure z rotation stays locked
            rotation = transform.rotation.eulerAngles;
            rotation.z = 0;
            transform.rotation = Quaternion.Euler(rotation);
        }
        lastMousePosition = Input.mousePosition;

        // Zoom (wheel)
        cam.fieldOfView = Mathf.Clamp(cam.fieldOfView - Input.mouseScrollDelta.y * zoomSpeed, minFOV, maxFOV);
    }
}

Thanks this REALLY Helped the development of my game!

[EDIT] : I fixed the camera so that it doesn’t rely on a frame by frame multiplier (I found it was slowing down the movement of the camera as usage got heavy. It now simply works by making the current rotation the same value as the y-position value, within the bounds you set via the editor. You can of course make it (transform.position.y +/- yourValue) if you think a little offset might look good.

I pasted the new code below, and I’ll leave the old file for reference. The one you want is CameraControlFixed.cs

The only bug is if your panSpeed is so ridiculously high that your camera goes beyond the bounds before a frame can even check it.


For anybody that’s still looking in here, I made this simple Camera Script with limitations and rotation as you go in and out using ā€˜R’ and ā€˜F’.
Pretty much all the necessary fields can be set from within the editor as you play around with it in runtime to figure out what looks good

using UnityEngine;

public class CameraControlFixed : MonoBehaviour
{
 
    public float panSpeed = 30f;
    public float windowEdgeBorder = 10f;
    private float cameraYRot;
    private float cameraZRot;

    [Header("CameraLimits")]
    public float leftLimit = 0f;
    public float rightLimit = 70f;
    public float upLimit = 65f;
    public float downLimit = -4f;
    public float zoomInLimit = 8f;
    public float zoomOutLimit = 55f;
    public float xRotationLowerLimit = 10f;
    public float xRotationUpperLimit = 90f;

    void Start() {
        cameraYRot = transform.rotation.y;
        cameraZRot = transform.rotation.z;
    }


    // Update is called once per frame
    void Update()
    {
        float mouseY = Input.mousePosition.y;
        float mouseX = Input.mousePosition.x;

        /*
            Camera controls in this next condition after we
                check that the mouse is within the window
         */
        if (mouseX >= 0 && mouseX <= Screen.width &&
            mouseY >= 0 && mouseY <= Screen.height)
        {
            /*
                Below we are checking that
                A.) a specific key is pressed
                B.) in some cases (left, right, back, forward) that the mouse is within the
                        edges of the screen via the border and Screen attributes
                C.) the camera's current position is not past the set limits

                Then we Translate that camera toward a certain direction relative to the
                    World Space
             */



            // up with 'w'
            if ((Input.GetKey("w") || mouseY >= Screen.height - windowEdgeBorder) &&
                transform.position.z < upLimit) {
                transform.Translate(Vector3.forward * panSpeed * Time.deltaTime,
                                    Space.World);
            }

            // left with 'a'
            if ((Input.GetKey("a") || mouseX <= windowEdgeBorder) &&
                transform.position.x > leftLimit) {
                transform.Translate(Vector3.left * panSpeed * Time.deltaTime,
                                    Space.World);
            }
       
            // down with 's'
            if ((Input.GetKey("s") || mouseY <= windowEdgeBorder) &&
                transform.position.z > downLimit) {
                transform.Translate(Vector3.back * panSpeed * Time.deltaTime,
                                    Space.World);
            }
       
            // right with 'd'
            if ((Input.GetKey("d") || mouseX >= Screen.width - windowEdgeBorder) &&
                transform.position.x < rightLimit) {
                transform.Translate(Vector3.right * panSpeed * Time.deltaTime,
                                    Space.World);
            }
       
            // zoom in
            if (Input.GetKey("r") && transform.position.y > zoomInLimit) {

                transform.Translate(Vector3.down * panSpeed * Time.deltaTime, Space.World);
                //transform.Rotate(-rotationPivotFactor* rotationSpeedPerFrame, 0f, 0f, Space.Self);
                if (transform.position.y > xRotationLowerLimit && transform.position.y < xRotationUpperLimit)
                    transform.rotation = Quaternion.Euler( transform.position.y, cameraYRot, cameraZRot);
            }
       
            // zoom out
            if (Input.GetKey("f") && transform.position.y < zoomOutLimit) {
                transform.Translate(Vector3.up * panSpeed * Time.deltaTime, Space.World);
                //transform.Rotate(rotationPivotFactor* rotationSpeedPerFrame, 0f, 0f, Space.Self);
                if (transform.position.y > xRotationLowerLimit && transform.position.y < xRotationUpperLimit)
                    transform.rotation = Quaternion.Euler( transform.position.y, cameraYRot, cameraZRot);
            }
        }
    }
}

[EDIT 2] : Looks like I was missing this too. I had it in my project but forgot to upload. Don’t credit me for this though, I forget where I got it… Has to do with Screen Size and how the Camera changes accordingly

using UnityEngine;


[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class ScreenSize : MonoBehaviour
{

    // Set this to the in-world distance between the left & right edges of your scene.
    public float sceneWidth = 10;

    Camera _camera;
    void Start()
    {
        _camera = GetComponent<Camera>();
    }

    // Adjust the camera's height so the desired scene width fits in view
    // even if the screen/window size changes dynamically.
    void Update()
    {
        float unitsPerPixel = sceneWidth / Screen.width;

        float desiredHalfHeight = 0.5f * unitsPerPixel * Screen.height;

        _camera.orthographicSize = desiredHalfHeight;
    }
}

Still new to 3-d programming, from what I can tell it works consistently, but maybe I’m missing something. Although the camera moves on the Y-Axis with Time.deltaTime, the rotation is based on each frame because I figured it would need a consistent multiplier

4586815–427567–CameraControl.cs (3.22 KB)
4586815–432307–CameraControlFixed.cs (3.88 KB)
4586815–432484–ScreenSize.cs (714 Bytes)

1 Like

I made the camera a child of another (empty) gameObject with an offset so that the camera is looking at its parent. I put the cameraScript on the parent. So when the parent turns, the child (the camera) will turn aswell. But instead of the camera turning around its own axis, it turns around the axis of the parent. Thus recreating the RTSCamera style.

Furthermore, if the camera rotates, the movement axis rotate with it. (so after turning 90 degrees to the left, it will now go forward in the camera’s direction (so 90 degrees to the left))

You do need to make sure that when you move your camera (or actually the camera’s parent), the scale is set to the Local scale.
For example:
transform.Translate(Vector3.left * panSpeed * Time.deltaTime, Space.Self);

The Space.Self means that the scale is set to local.