#FaresFilms Zooming Code

1 messages · Page 1 of 1 (latest)

hoary canyon
#

@dense hound

#

so how do you intend on zooming in and out in your game?

#

is it just a camera that changes its distance when you scroll?

dense hound
#

sorry the internet is really slow

dense hound
hoary canyon
#

makes no difference, the issue here is ScreenToWorldPoint

#

thats for converting a position on the screen into a 3d coordinate

#

sorta like how a crosshair can indicate to someone where a bullet will go in an FPS

dense hound
#

hm

hoary canyon
#

if you zoom out, that distance will increase, naturally

#

and that will then make the next attempt to zoom a bigger change

dense hound
#

so what would I use instead

hoary canyon
#

lets see the full code again so i can get a better look at how to fit a solution into your work

dense hound
#

this is the zoom file (attached to main camera)

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

public class zoom : MonoBehaviour
{

    float zoomValue = 10f;

    // Update is called once per frame
    void Update()
    {
        // if(Camera.main.orthographic) {
        //     Camera.main.orthographicSize -= Input.GetAxis("Mouse ScrollWheel") * zoomValue;
        // } else {
        //     Camera.main.fieldOfView -= Input.GetAxis("Mouse ScrollWheel") * zoomValue;
        // }

        var camera = Camera.main;
        var brain = (camera == null) ? null : camera.GetComponent<CinemachineBrain>();
        var vcam = (brain == null) ? null : brain.ActiveVirtualCamera as CinemachineVirtualCamera;
        if (vcam != null) {
            vcam.m_Lens.OrthographicSize -= Input.GetAxis("Mouse ScrollWheel") * zoomValue;
            print(Camera.main.ScreenToWorldPoint(Input.mousePosition));
        }

    }
}
hoary canyon
#

lets clean this up a bit

#

then work on a fix, var is vague, you are constantly replacing the reference every frame, and ternaries are a bit awkward to read with no performance benefits

dense hound
#

just to explain my thought process, I wanted to zoom in to center, and then use cinemachine to move the camera to the mouse. It didn't work and I have no problems with changing everything

hoary canyon
#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class zoom : MonoBehaviour
{
    private Camera MyCamera;
    private CinemachineBrain MyBrain;
    private CinemachineVirtualCamera MyVCam;
    float zoomValue = 10f;
    void Start()
    {
      MyCamera = Camera.main;
      MyBrain = MyCamera.GetComponent<CinemachineBrain>();
      MyVCam = MyBrain.ActiveVirtualCamera as CinemachineVirtualCamera;
    }
    // Update is called once per frame
    void Update()
    {
        if (MyVCam) 
        {
            MyVCam.m_Lens.OrthographicSize -= Input.GetAxis("Mouse ScrollWheel") * zoomValue;
            print(Camera.main.ScreenToWorldPoint(Input.mousePosition));
        }
    }
}```
#

okay so its a little cleaner now

#

no need to constantly check if things exist, ideally, let them exist or cause a bug, handle the bug itself, rather than prepare for one every single frame

dense hound
#

alright

hoary canyon
#

now, in the update method, it seems you arent even using the screenworld to point thingy any more

#

but you are printing it

dense hound
#

yeah I asked elsewhere, and some suggestion were made and I removed it

hoary canyon
#

so when you scroll, what do you want it to do?

#

just get closer and further away yeah?

dense hound
#

yes

hoary canyon
#

okay, so that code is already pretty close to perfect

#

now for moving the camera to the mouse position, thats an interesting one

dense hound
hoary canyon
#

oh so zooming at a certain location?

dense hound
#

yes

hoary canyon
#

thats not something ive tried, interesting

dense hound
#

maybe thats why I couldn't find many tutorials on this exactly

hoary canyon
#

just trying to think this through, havent ditched you dw

#

wherever the mouse IS, the camera seems to center around it

#

as if the map itself is moving and the camera is moving in the opposite direction to make up for it

#

odd

#

its odd how hard this is to think through, never really considered this before, wow

dense hound
#

I've done this before, and from what I could remember:

  • you zoom in (already works)
  • you get the mouse postion before scaling and after scaling and subtract
  • Add that offset to the camera's pos
#

actually lemme look in my files I might find something

hoary canyon
#

good shout

dense hound
#

I found this which someone gave me which I believe originated from a stackoverflow question. The steps to zooming in with the center of the zoom being the mouse

  1. Convert the mouse coordinate from screen space to world space
  2. Change the zoom level
  3. Convert the mouse coordinate from screen space to world space again (since zoom is part of that equation, we get a different result)
  4. Move the camera's position the difference between the answer we get for 1 and 3
  5. When you draw something make sure to convert that object's position from world space coordinates to screen space coordinates
#

I think 5 is irrelevant here

#

and I think this was in the context of a no engine game

hoary canyon
#

so is the world not moving at all?

#

you could, on zoom, lerp / pan the camera towards the mouse position converted to a world position

dense hound
#

right now, it is, just the movement is really fast like i showed

hoary canyon
#

for zooming out, im not entirely sure

#

oh wait is that your own video?

dense hound
hoary canyon
#

ah

dense hound
#

the one I sent in the server is

#

if it was mine then problem solved😄

hoary canyon
#

could you link that video in here?

#

of your own game that is

dense hound
hoary canyon
#

it seems to work but its scaled weird

#

can you try the new code and get a video of that?

dense hound
#

alright

hoary canyon
#

definitely worth seeing how things shape up

dense hound
#

mostly I was zoom in and out alternatingly

hoary canyon
#

so how is the new script moving the camera?

#

theres no movement code in there?

dense hound
#

so its a good example

hoary canyon
#

also whats the object called followMouse doing?

#

bc i think of it like this

dense hound
# hoary canyon also whats the object called followMouse doing?

so in cinemachine, you can only track gameobjects, so I made a empty object with the script

public class followMouse : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        if(Input.mouseScrollDelta.y != 0) {
            transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
    }
}

Just to track the mouse

hoary canyon
#

if you wanna half the scale of the camera, you find the difference between the middle of the camera and the mouse position, and also half that

#

so theres another object adding more behaviors to the camera?

dense hound
#

oh...

hoary canyon
#

this is causing issues for debugging

dense hound
#

my bad

#

removing that makes zoom in fixed only at the center of the screen

hoary canyon
#

id disable that, lets work on this single script for the camera that youve got and make it into a generic pan zoom script

hoary canyon
#

now we can focus on mouse position and all

#

okay so lets figure out the relative distance in WORLD units that the mouse is from the center of the camera

#

the black box is the camera, the triangle is the mouse

#

we need to know the exact length of the blue line in world units

dense hound
#

is the center just camera pos?

hoary canyon
#

yep!

dense hound
#

alright good

hoary canyon
#

so if the camera is at (-10,-10) in the world, and the mouse is at (5,5), whats the difference?

dense hound
#

15, 15?

hoary canyon
#

actually i have a better way of solving this

#

i made this image in paint

#

bottom left, this exists

dense hound
#

huh

hoary canyon
#

we can use this as a guide to make sure we use the same math that paint does, as its coordinate system works fine

#

pro tip. MS paint always comes to the rescue!

dense hound
#

lol

hoary canyon
#

okay so the camera is placed at

#

and the mouse is at

dense hound
#

just estimate since you probably won't get exact numbers

#

with mouse

hoary canyon
#

yeah i guess, its just faster to know a rough guess

#

so up and right is -y and +x

#

the difference between those numbers is probably then as simple as subtracting one from the other

dense hound
hoary canyon
#

so camera position - ScreenToWorldPoint(MousePosition)

hoary canyon
dense hound
#

both?

hoary canyon
#

yup, its just a 2d coordinate at the end of the day

dense hound
#

since when I made a game in pygame it was 0, 0 at topleft

hoary canyon
#

whats different in unity?

#

00 in the middle of the world right?

dense hound
#

I was used to it being at the top left, not the center

hoary canyon
#

thats a world space, screen space is usually 00 at the top left

dense hound
#

alright

hoary canyon
#

world space doesnt have a "top left"

#

its just an infinitely big space, so it makes sense to use 00 as the middle bc you can move as far negative as you can positive, but in screen space, there are no negative pixels, make sense?

dense hound
#

ah yes

hoary canyon
#

okay so im gonna sudocode this, it might well be wrong, but its worth a try

#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class zoom : MonoBehaviour
{
    private Camera MyCamera;
    private CinemachineBrain MyBrain;
    private CinemachineVirtualCamera MyVCam;
    // NEW CODE HERE:
    public Vector2 MouseOffset;

    float zoomValue = 10f;
    void Start()
    {
      MyCamera = Camera.main;
      MyBrain = MyCamera.GetComponent<CinemachineBrain>();
      MyVCam = MyBrain.ActiveVirtualCamera as CinemachineVirtualCamera;
    }
    // Update is called once per frame
    void Update()
    {
        //  NEW CODE HERE:
        MouseOffset = MyCamera.Transform.Position - MyCamera.ScreenToWorldPoint(Input.MousePosition);
        // OLDER CODE HERE:
        if (MyVCam) 
        {
            MyVCam.m_Lens.OrthographicSize -= Input.GetAxis("Mouse ScrollWheel") * zoomValue;
            print(Camera.main.ScreenToWorldPoint(Input.mousePosition));
        }
    }
}```
#

okay so ive added an offset checker, update the script to match that

#

in your inspector, it should show you the difference between your camera and mouse now, if it looks weird, ive got the subtraction the wrong way around

#

i think its correct tho

#

if its a metre to the top right, it should spit out a [1, -1] in the inspector, roughly

dense hound
#

so
I started by moving the mouse slightly, then zoom in and out for a bit, then at the very end move the mouse

hoary canyon
#

no no

#

thats the print

#

we dont need that

#

inspector, where the variables go

dense hound
#

oh

#

ah my bad

hoary canyon
#

public Vector2 MouseOffset;

#

this is public so we can keep an eye on it

#

when you move the mouse around, a value will change over here ish

#

make sense?

dense hound
#

yeah

hoary canyon
#

is it working?

dense hound
#

its always negative, until I zoom in fully

hoary canyon
#

okay but where is the camera position

dense hound
#

that flip at the end I believe is zooming past the thing

hoary canyon
#

yeah an inversion of the camera entirely

#

that does seem to be working though, is the camera at 00?

#

try putting the camera at 00 first, so its easier to read the values

dense hound
#

at the start its not

hoary canyon
#

nor at runtime either

#

but, we know now that the zoom level does adjust the difference between the mouse and the camera perfectly

#

because the further we zoom out, the bigger the distance can be

dense hound
#

I set it to 0, 0

#

I think the offset works

hoary canyon
#
    // Update is called once per frame
    void Update()
    {
        //  NEW CODE HERE:
        MouseOffset = MyCamera.Transform.Position - MyCamera.ScreenToWorldPoint(Input.MousePosition);
        float _zoomAmount = Input.GetAxis("Mouse ScrollWheel") * zoomValue;
        // OLDER CODE HERE:
        MyVCam.m_Lens.OrthographicSize -= _zoomAmount;
        MyVCam.Transform.Position += (MouseOffset * _zoomAmount);
    }
#

lets try updating the ... update method to this

dense hound
#

I had to fix some thing with the code (like capitalization and changing last line to vector3)


    void Update()
    {
        //  NEW CODE HERE:
        MouseOffset = MyCamera.transform.position - MyCamera.ScreenToWorldPoint(Input.mousePosition);
        float _zoomAmount = Input.GetAxis("Mouse ScrollWheel") * zoomValue;
        // OLDER CODE HERE:
        MyVCam.m_Lens.OrthographicSize -= _zoomAmount;
        MyVCam.transform.position += (Vector3)(MouseOffset * _zoomAmount);
    }
#

and lemme send the vid one sec

hoary canyon
#

thats casting from one type to another

#

lets not do that

dense hound
hoary canyon
#

lets be explicit here, MyVCam.transform.position += new Vector3(MouseOffset.x, MouseOffset.y, 0) * _zoomAmount

#

looks like its going the wrong direction

dense hound
#

yeah

hoary canyon
#

change that += to a -=

dense hound
hoary canyon
#

thats looking like its working to me

dense hound
#

should I send the project so you can test more easily?

dense hound
#

zooming once (or like one mouse wheel increment) is way too much

hoary canyon
#

make ZoomValue public

#

then you can play with the value in the inspector while its running

#

youve got it set to 10f at the moment, thats the only issue

#

one trick i like to use is this

#

[Range(0f, 10f)] public float ZoomValue;

#

dont declare a value for it, but specify a range

#

in unity, a slider will appear and you can change the zoom strength with that instead if hard coded values

dense hound
#

I can't really explain lemme record

hoary canyon
#

like here, i manage deadzones with ranges

hoary canyon
dense hound
hoary canyon
#

ahaa

#

we need to have different code for zooming in and zooming out then

dense hound
#

huh

hoary canyon
#

thats not a problem

#
    void Update()
    {
        //  NEW CODE HERE:
        MouseOffset = MyCamera.transform.position - MyCamera.ScreenToWorldPoint(Input.mousePosition);
        float _zoomAmount = Input.GetAxis("Mouse ScrollWheel") * zoomValue;
        MyVCam.m_Lens.OrthographicSize -= _zoomAmount;
        if(_zoomAmount > 0)
          MyVCam.transform.position += (Vector3)(MouseOffset * _zoomAmount);
        else if (_zoomAmount < 0)
          MyVCam.transform.position -= (Vector3)(MouseOffset * _zoomAmount);
    }
#

if we zoom in, add the offset distance, if we zoom out, subtract it

#

if this goes tits up, i probably got the + and - the wrong way around lol

dense hound
#

I’ll take a break my back hurts

hoary canyon
#

yeah np, dm me when youre back

dense hound
#

I'm back

dense hound
dense hound
#

And btw this video is me zooming in and out alternatingly