RTS Camera - Zoom is not uniform, yet code is?

Hello guys, i have one question. I started working on a RTS title, and first step is to finish off camera code… I ended up with a code that works, but zooming in feels slower then zooming out, yet the code is nearly identical + the same variable ‘zoomSpeed’ is used… I don’t know why this is the case…

    public int scrollSpeed = 25;
    public int zoomSpeed = 25;
    public int zoomMin = 6;
    public int zoomMax = 24;
    public float smooth = 1.3f;
 	private Vector3 velocity = Vector3.zero;
	
    void Update()
    {
 		Vector3 temp = this.transform.position;
		
        if(Input.GetAxis("Mouse ScrollWheel") > 0)
        {
			temp.y -= 100f * zoomSpeed * Time.deltaTime;
        }
		
 		if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
			temp.y += 100f * zoomSpeed * Time.deltaTime;
        }
		
		Debug.Log(temp);
		
		if (temp.y <= zoomMin)
			temp.y = zoomMin;
		if (temp.y >= zoomMax)
			temp.y = zoomMax;

        this.transform.position = Vector3.SmoothDamp(this.transform.position, temp, ref velocity, smooth);
}

Any ideas? Also, bonus points if anyone can point me if something I could have done better/faster…

Thanks!

well, if GetAxis(“Mouse Scrollwheel”) returns 1 or -1, then you can multiply your scroll speed by that and do it all in one line.

void Update()
    {
      Vector3 temp = this.transform.position;
      temp.y += zoomSpeed * Input.GetAxis("Mouse ScrollWheel");

       Debug.Log(temp);

       temp.y = temp.y >= zoomMax ? zoomMax : zoomMin;

       transform.position = Vector3.SmoothDamp(transform.position, temp, ref velocity, smooth);
}

EDIT: Oh…and your camera is zooming at different speeds because you assign two totally different values to temp.y. Namely zoomMin and zoomMax.

The answer is quite simple :wink:

Use a seperate zoom variable. With the scrollwheel you set a target zoom level and the smoothdamp function will smooth it, but you have to remember the target zoom level across frames.

float zoom;
void Start()
{
    zoom = (zoomMin + zoomMax) * 0.5f; //init value
}

void Update()
{
    Vector3 temp = transform.position;
    //Apply the scrollwheel and change the local zoom variable
    zoom -= zoomSpeed * Input.GetAxis("Mouse ScrollWheel");
    // clamp the zoom var to keep it between Min and Max
    zoom = Mathf.Clamp(zoom, zoomMin, zoomMax);
    // create the "target" vector for SmoothDamp
    temp += new Vector3(Input.GetAxis("Horizontal") * scrollSpeed * Time.deltaTime,
                        zoom,
                        Input.GetAxis("Vertical") * scrollSpeed * Time.deltaTime);
    
    // move the camera with moving mouse out of screen bounds
    if (Input.mousePosition.x < ScrollArea)
        temp += Vector3.right * -scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.x >= Screen.width - ScrollArea) 
        temp += Vector3.right * scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.y < ScrollArea)
        temp += Vector3.forward * -scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.y > Screen.height - ScrollArea)
        temp += Vector3.forward * scrollSpeed * Time.deltaTime;
    
    transform.position = Vector3.SmoothDamp(transform.position, temp, ref velocity, smooth);
}

Note: You smooth your movement twice. First you increment the temp vector via delta time which already gives you a smooth progression over time. In Smoothdamp this movement get’s smoothed a second time. This makes it difficult to set a clear independent speed for the movement.

I would probably just use Mathf.SmoothDamp on the y component and set x and z directly (which are already smoothed).

Something like that:

float zoom;
float velocity = 0.0f;

void Start()
{
    zoom = (zoomMin + zoomMax) * 0.5f; //init value
}

void Update()
{
    Vector3 temp = transform.position;
    zoom -= zoomSpeed * Input.GetAxis("Mouse ScrollWheel");
    zoom = Mathf.Clamp(zoom, zoomMin, zoomMax);
    temp.y = Mathf.SmoothDamp (temp.y, zoom, ref velocity, smooth);
    temp += new Vector3(Input.GetAxis("Horizontal") * scrollSpeed * Time.deltaTime,
                        0,
                        Input.GetAxis("Vertical") * scrollSpeed * Time.deltaTime);
    
    // move the camera with moving mouse out of screen bounds
    if (Input.mousePosition.x < ScrollArea)
        temp += Vector3.right * -scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.x >= Screen.width - ScrollArea) 
        temp += Vector3.right * scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.y < ScrollArea)
        temp += Vector3.forward * -scrollSpeed * Time.deltaTime;
    
    if (Input.mousePosition.y > Screen.height - ScrollArea)
        temp += Vector3.forward * scrollSpeed * Time.deltaTime;
    
    transform.position = temp;
}

edit

Btw this is all untested but it should work :wink: