RTS Style Camera Scrolling

I've decided to make a RTS (real time strategy) game. I have a camera set up at the angle I want, and everything is coming along fine. However, I need some method of moving the camera. I suppose I could use the arrow keys, but I'd really rather not. So, deciding to make a camera scroll where you simply move the mouse to the edge of the screen and have the camera scroll in that direction, I started looking around in order to locate something that could help me out. I spent about three hours surfing, and came up with... nothing! So, I thought I'd just ask another question for everybody that's already given up in despair. How would you implement such a feature?

Thanks in advance - Elliot Bonneville

The Update function in the editor script in this example project has code for scrolling. Including the edge of the screen method, arrow keys, and middle mouse button method; pretty much all the RTS games I've played have at least the first two. Not including the public variables for scrolling speed and so on, the relevant code is:

var mPosX = Input.mousePosition.x;
var mPosY = Input.mousePosition.y;

// Do camera movement by mouse position
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.up * -scrollSpeed * Time.deltaTime);}
if (mPosY >= Screen.height-scrollArea) {myTransform.Translate(Vector3.up * scrollSpeed * Time.deltaTime);}

// Do camera movement by keyboard
myTransform.Translate(Vector3(Input.GetAxis("EditorHorizontal") * scrollSpeed * Time.deltaTime,
                              Input.GetAxis("EditorVertical") * scrollSpeed * Time.deltaTime, 0) );

// Do camera movement by holding down option                 or middle mouse button and then moving mouse
if ( (Input.GetKey("left alt") || Input.GetKey("right alt")) || Input.GetMouseButton(2) ) {
    myTransform.Translate(-Vector3(Input.GetAxis("Mouse X")*dragSpeed, Input.GetAxis("Mouse Y")*dragSpeed, 0) );
}

Modified, working example of above code:

var mousePosX = Input.mousePosition.x;
var mousePosY = Input.mousePosition.y;
var scrollDistance : int = 5;
var scrollSpeed : float = 70;

if (mousePosX < scrollDistance)
{ transform.Translate(Vector3.right * -scrollSpeed * Time.deltaTime); }
if (mousePosX >= Screen.width - scrollDistance)
{ transform.Translate(Vector3.right * scrollSpeed * Time.deltaTime); }

if (mousePosY < scrollDistance)
{ transform.Translate(Vector3.up * -scrollSpeed * Time.deltaTime); }
if (mousePosY >= Screen.height - scrollDistance)
{ transform.Translate(Vector3.u) * scrollSpeed * Time.deltaTime); },var mousePosX = Input.mousePosition.x;
var mousePosY = Input.mousePosition.y;
var scrollDistance : int = 5;
var scrollSpeed : float = 70;

if (mousePosX < scrollDistance)
{ transform.Translate(Vector3.right * -scrollSpeed * Time.deltaTime); }
if (mousePosX >= Screen.width - scrollDistance)
{ transform.Translate(Vector3.right * scrollSpeed * Time.deltaTime); }

if (mousePosY < scrollDistance)
{ transform.Translate(Vector3.up * -scrollSpeed * Time.deltaTime); }
if (mousePosY >= Screen.height - scrollDistance)
{ transform.Translate(Vector3.up * scrollSpeed * Time.deltaTime); }

Thanks Feilyne (though you pasted the code twice in a row).

I am doing an iso metric RTS game (with C#). Because of this the Z axis was moving through the terrain (rather than scrolling up).

So to address this I created an empty game object (which was aligned with the terrain). Attached the camera movement script to it, and then nested the main camera inside the empty object.

Also here is the C# code I used (modified from Feilynes)

using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour {

// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

	float mousePosX = Input.mousePosition.x; 
	float mousePosY = Input.mousePosition.y; 
	int scrollDistance = 5; 
	float scrollSpeed = 70;

	if (mousePosX < scrollDistance) 
			{ 
				transform.Translate(Vector3.right * -scrollSpeed * Time.deltaTime); 
			} 
			
	if (mousePosX >= Screen.width - scrollDistance) 
			{ 
				transform.Translate(Vector3.right * scrollSpeed * Time.deltaTime); 
			}
	
	if (mousePosY < scrollDistance) 
			{ 
				transform.Translate(transform.forward * -scrollSpeed * Time.deltaTime); 
			} 
			
	if (mousePosY >= Screen.height - scrollDistance) 
			{ 
				transform.Translate(transform.forward * scrollSpeed * Time.deltaTime); 
			}
	}

}

Many thanks for the solution! Could you give me an advise how to include a smoothing method in the camera scrolling? I think that the scrolling effect is a little abrupt/sudden and if possible I would like to smooth/fade in & out the camera movement.

How do I limit mouse movements so that the user can’t scroll too far away from my scene? With the keyboard I was able to use the following code, but I can’t seem to find the equivalent with the mouse.

` private float leftSide = -100f;
private float rightSide = -80f;
private float topSide = -80f;
private float bottomSide = -100f;

// Update is called once per frame
void Update () 
{

	/////////////////////
	//keyboard scrolling		
	float translationX = Input.GetAxis("Horizontal");
	float translationZ = Input.GetAxis("Vertical");
		
	float toX = translationX + translationZ;			
	if (transform.position.x + toX < leftSide)
	{
		toX = 0;
	}
	if (transform.position.x + toX > rightSide)
	{
		toX = 0;
	}
	float toZ = translationZ - translationX;			
	if (transform.position.z + toZ > topSide)
	{
		toZ = 0;
	}
	if (transform.position.z + toZ < bottomSide)
	{
		toZ = 0;
	}
	transform.Translate(toX, 0, toZ); 
	
	
	////////////////////
	//mouse scrolling	
	float mousePosX = Input.mousePosition.x;
	float mousePosY = Input.mousePosition.y;
	int scrollDistance = 1;
	float scrollSpeed = 70;
	
	//Horizontal camera movement
	//horizontal, left
	if (mousePosX < scrollDistance)
	{ 
		transform.Translate(-1, 0, 1);
	} 
	//horizontal, right
	if (mousePosX >= Screen.width - scrollDistance)
	{ 
		transform.Translate(1, 0, -1);
	} 
	
	//Vertical camera movement
	//scrolling down
	if (mousePosY < scrollDistance)
	{
		transform.Translate(-1, 0, -1);
	} 
	//scrolling up
	if (mousePosY >= Screen.height - scrollDistance)
	{
		transform.Translate(1, 0, 1);
	}

}`

Hello, I was messing with RTS cameras and used some of the code here, My camera stops after a certain distance from the center, has zoom using the mouse wheel and also has keyboard controls for arrow keys to use the camera.

On top of these features, zooming really far out no longer slows the cameras movement or zooming (when zoomed out, trying to scroll in any direction or zoom back in was really slow).

Also! And this ones a big one~ the camera moves in world space, so all you need to do is move the camera how high you want it and what angle you want it (could be isometric) and it wont move into the terrain. I //commented some things so people dont get lost. Code below is in C#

  using UnityEngine;
    using System.Collections;
    
    public class RTSCamera : MonoBehaviour
    {
    
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    
        float mousePosX = Input.mousePosition.x; 
        float mousePosY = Input.mousePosition.y; 
        int scrollDistance = 5; 
        float scrollSpeed = 2 * Camera.main.orthographicSize + 2;
    	Vector3 aPosition = new Vector3(0, 0, 0);
    	float ScrollAmount = scrollSpeed *Time.deltaTime;
    	const float orthographicSizeMin = 15f;
        const float orthographicSizeMax = 256f;
    		
    
    		//mouse left
        if ((mousePosX < scrollDistance) && (transform.position.x > -240))
             { 
              transform.Translate (-ScrollAmount,0,0, Space.World); 
             } 
    		//mouse right
        if ((mousePosX >= Screen.width - scrollDistance) && (transform.position.x < 240))
             { 
               transform.Translate (ScrollAmount,0,0, Space.World);  
             }
    		//mouse down
        if ((mousePosY < scrollDistance) && (transform.position.z > -240))
             { 
              transform.Translate (0,0,-ScrollAmount, Space.World); 
             } 
    		//mouse up
        if ((mousePosY >= Screen.height - scrollDistance) && (transform.position.z < 240))
             { 
              transform.Translate (0,0,ScrollAmount, Space.World); ; 
             }
    		//Keyboard controls 
    	if ((Input.GetKey(KeyCode.UpArrow)) && (transform.position.z < 240))
             { 
              transform.Translate (0,0,ScrollAmount, Space.World); ; 
             } 
    	if ((Input.GetKey(KeyCode.DownArrow)) && (transform.position.z > -240))
             { 
              transform.Translate (0,0,-ScrollAmount, Space.World);
             }
    	if ((Input.GetKey(KeyCode.LeftArrow)) && (transform.position.x > -240))
             { 
              transform.Translate (-ScrollAmount,0,0, Space.World);  
             } 
    	if ((Input.GetKey(KeyCode.RightArrow)) && (transform.position.x < 240))
             { 
              transform.Translate (ScrollAmount,0,0, Space.World); 
             }
    		//Scrolling Zoom
      	if (Input.GetAxis("Mouse ScrollWheel") < -0) // forward
       		 {
           Camera.main.orthographicSize *= 1.1f;
       		 }
        if (Input.GetAxis("Mouse ScrollWheel") > -0) // back
        	{
           Camera.main.orthographicSize *= 0.9f;
       		 }
    
        Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize, orthographicSizeMin, orthographicSizeMax );
    }
    }

It’s an old post but I will answer anyways!!!
You can use this script I bought and I use. It’s pretty good and costs only 3€ for both commercial and indie use.

RTS Camera Script

Here’s a script I came up with:

var speed = 3;     //MUST BE INTEGER!!!
var size = 100;    //cursor to edge tweaker

function Update () {

    var mousePos = Input.mousePosition;
       
    if(mousePos.x <= size)
    transform.position += new Vector3(-speed,0,0);

    if(mousePos.x >= Screen.width - size)
    transform.position += new Vector3(speed,0,0);

    if(mousePos.y <= size)
    transform.position += new Vector3(0,0,-speed);

    if(mousePos.y >= Screen.height - size)
    transform.position += new Vector3(0,0,speed);

    if (Input.GetAxis("Mouse ScrollWheel") < 0)
    transform.position += new Vector3(0,speed,-speed);   

    if (Input.GetAxis("Mouse ScrollWheel") > 0)
    transform.position += new Vector3(0,-speed,speed);    
}

I know the thread is from the stone age, but I felt like I should post here.

Should be easy to understand and is short in line numbers, hope this helps anybody trying to make a rts game camera

god, had to edit about 10000 times X.X

Thank you the great lizard king, I improved it more, because yours doesn’t move in the direction the camera is facing if you rotate. I edited your script so:

  1. Camera pans, meaning you can look around by holding right mouse button

  2. You can enable disable screen edge scrolling

  3. You can use WASD

  4. The camera moves where it is looking but its Y position is locked and can be changed only by “zooming” or scrolling

To setup, you:

  1. attached this script to camera

  2. create EmptyObject (name it however you like), the object should NOT be child of camera

  3. attach the object to the script, what it does is that it copies the Y rotation of the camera, so you can actually go forward and backwards but on the same Y position.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class CameraMovement : MonoBehaviour
    {

      public int speed = 3;     //MUST BE INTEGER!!!
      public int sizeEdge = 100;    //adjusts the size of how big the trigger cursor area is
      public bool ScreenScrolling = false; //enable disable edge screen scrolling
      Vector3 lastMousePosition;
      public float rotateSpeed = 10;
      
      bool wKeyDown = false;
      bool aKeyDown = false;
      bool sKeyDown = false;
      bool dKeyDown = false;
      bool qKeyDown = false;
      bool eKeyDown = false;
      
      public GameObject EmptyObject; //create empty object outside camera, this object has zero X,Z rotation so our camera doesnt fly up/down 
    
      
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
     
    
    
    
    void Update () 
    {
      
      wKeyDown = Input.GetKey(KeyCode.W); // buttons
      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);
     
     Vector3 mousePos = Input.mousePosition;
        
     if(mousePos.x <= sizeEdge && ScreenScrolling || aKeyDown && !dKeyDown) // move left
     transform.position += -transform.right;
    
     if(mousePos.x >= Screen.width - sizeEdge && ScreenScrolling || dKeyDown && !aKeyDown) // move right
     transform.position += transform.right;
    
     if(mousePos.y <= sizeEdge && ScreenScrolling || sKeyDown && !wKeyDown) // move backward by using the empty object's zero X,Z rotation so we cannot move up/down
     transform.position += EmptyObject.transform.forward * -1;
     
     if(mousePos.y >= Screen.height - sizeEdge && ScreenScrolling || wKeyDown && !sKeyDown) // move forward by using the empty object's zero X,Z rotation so we cannot move up/down
     transform.position += EmptyObject.transform.forward;
    
    
     
     if (Input.GetAxis("Mouse ScrollWheel") < 0 ) // move up/down by "zooming"
     transform.position += new Vector3(0,speed,0);   
    
     if (Input.GetAxis("Mouse ScrollWheel") > 0)
     transform.position += new Vector3(0,-speed,0);   
    
    if (Input.GetMouseButton(1)) // panning/looking around by holding right mouse button
            {
                // 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;
    
    	EmptyObject.transform.localEulerAngles = new Vector3(0.0f,transform.localEulerAngles.y, 0.0f); 
    }
    

    }