- Home /
How to prevent the mouse from moving when the camera does? (zoom to mouse, 2D environment)
I implemented a zoom-to-mouse function in my 2D environment. So you can zoom in and the camera moves towards where the mouse is. However the mouse also moves each time you zoom in, it stays in the same location on the screen, and since the camera moves, the mouse also moves in comparison to the entire world.
How do I resolve this? I tried looking into manually moving the mouse cursor back the same X/Y distance the camera moved. But it does not look like I can set the mouse location in Unity. I also looked into freezing the mouse in it's current world point, moving the camera, then unfreezing it. But screen.LockCursor just freezes it to the middle of the screen.
( I have been through several pages worth of links on google using different phrases to try and find an answer. I'd rather avoid buying a plugin, just to resolve one small function..)
Any suggestions?
Code Snipped involved:
float xDiff;
float yDiff;
mousePos = Camera.main.ScreenToWorldPoint( new Vector3( //Get Mouse world Position
Input.mousePosition.x,
Input.mousePosition.y,
-1f));
camPos = new Vector3( //Get Camera Position (Declared at start of class)
Camera.main.transform.position.x,
Camera.main.transform.position.y,
-1f);
// Zoom in and move to mouse
if (Input.GetAxis ("Mouse ScrollWheel") > 0) { // Forward
if (Camera.main.orthographicSize == ResourceManager.MinCameraHeight){
;} //Purposeful
else {
Camera.main.orthographicSize--;
xDiff = mousePos.x - camPos.x;
yDiff = mousePos.y - camPos.y;
Camera.main.transform.position = new Vector3( (camPos.x + (xDiff)), (camPos.x + (yDiff)), -1f);
The movement is very jagged now, but thats an easy fix. I just need to figure out how to get the mouse to not move with the camera, and instead keep the mouse at the same world point it was at when you started to zoom.
Thanks!
What's the point of keeping the mouse position on the same world point while zoo$$anonymous$$g?
Can the camera move laterally while zoo$$anonymous$$g? If so, you could move the camera to be centered above the point that you are clicking on and then zoom in. That way, your mouse position is 0,0,0 (relatively), so zoo$$anonymous$$g shouldn't be a problem.
I see two choices. First, you could write your zoom so that it preserves the mouse position. If this is route you want to go, I can post some sample code when I get a bit of time. But there is another route. You can simulate the mouse cursor. Typically this is done by hiding the hardware cursor and using a GUITexture. You can use $$anonymous$$ouseX and $$anonymous$$ouseY to move the GUITexture. This gives you the ability to position the 'cursor' wherever you want.
@smnerat As you zoom, the camera will move towards the mouse's worldpoint (mousePos is a worldpoint from "ScreenToWorldPoint"). When the camera moves towards the worldpoint the mouse's location on the screen stays the same, causing the mouses worldpoint to change. In effect each time you zoom, the mouse moves further away from it's original worldpoint by whatever distance the camera moved. (hopefully I used the correct ter$$anonymous$$ology)
@robertbu What I wanted to do was (in this order) store the worldpoint location of the mouse, move the camera, move the mouse to it's previous worldpoint. Which as far as the user is concerned happened fast than they could see and "should" appear as if the mouse never moved. I initially was just going to modify the "Input.mousePosition" till I learned it is readonly. I would prefer to avoid a virtual cursor, since if a user runs at low FPS the mouse will skip as well. I will gladly hear what suggestions or code you have.
Edit: A virtual cursor could work, but my partner thinks it could end up being problematic with skipping.I will listen to anything you have though, I'm open to learn anything.
Answer by robertbu · Oct 04, 2014 at 04:22 AM
The the idea is to 1) get the world position of the mouse, 2) change the orthographicSize, 3) get the new position of the mouse, 4) translate the camera so that the mouse is again over the original world position. Put the following code on a game object in the scene (the camera is fine, but not required). Put a 2D world image on the screen (Quad or Sprite), run the script and use the mouse wheel to scroll. Note this code assumes an Orthographic camera.
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
public float minOrthoSize = 2.0f;
public float maxOrthoSize = 25.0f;
public float zoomSpeed = 0.5f;
void Update () {
float f = Input.GetAxis ("Mouse ScrollWheel");
if ( Mathf.Abs (f) > 0.01f) {
Vector3 v3 = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Camera.main.orthographicSize += zoomSpeed * f;
Camera.main.orthographicSize = Mathf.Clamp (Camera.main.orthographicSize, minOrthoSize, maxOrthoSize);
v3 = v3 - Camera.main.ScreenToWorldPoint (Input.mousePosition);
Camera.main.transform.position += v3;
}
}
}
That is great!
Looking through your script, I ended up taking and using line 16 and line 17. And replacing the rest with what I already have. I really can't believe it was this simple, 2 lines of code and it works.
I'm still going through why line 16 & 17 work. V3 is the previous mouse position, after the orthographic size changes you then subtract the new mouse position from the old one. And then add that onto the current position of the camera.
I think that is correct? Even after picking it apart I don't 100% get how it translates back. I'll have another look in the A.$$anonymous$$. But for now, thank you.
In order to understand, ignore the change in Camera.orthographicSize. Say you had a particular pixel position that corresponded to (1,1) in world space and you want to move the camera so that it was over (3,3) in world space. How far would you move the camera? (3,3) - (1,1) = (2,2). That is all this code is doing. It is calculation the delta between where the current world position of the pixel position and the desired world position and moving the camera that delta.
Note this solution is only simple because the camera is Orthographic, the camera axes aligned, and there is no camera rotation involved in the movement. Change any one of these, and the problem can get pretty ugly.
I see. I had to draw it out to understand but it makes perfect sense now. Thanks, for the help. Now I'm trying to make the zoom and the camera movement smooth, which is turning into it's own unique challenge... may end up posting a question or two on that.
Edit: posted this picture for any future viewers that are trying to do the same thing. It helped me with my understanding of it. Not intentionally trying to bump it.

Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Problems making a smash bros like camera 2 Answers