Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Camera moves when mouse on edge of screen.

Discussion in 'Scripting' started by Hansuke, May 4, 2007.

  1. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    How to make the camera to move my mouse hit the edge of the screen? (like warcraft camera system)
     
  2. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    It's very simple:

    - Check if the mouse is in one of the borders.
    - Move the camera in the direction of the border.

    So, im assuming you want some classes and functions to investigate?

    - Input.mousePosition
    - Screen.width and Screen.height
    - Transform.right and Transform.up

    The borders will be at:

    - Left: x = 0
    - Right: x = Screen.width
    - Up: y = Screen.height
    - Down: y = 0

    Happy coding!

    Omar Rojo
     
  3. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    Sure.. this script attached to a camera would work on an edge, it's up to you to create the behavior for the other edges.

    Code (csharp):
    1. // Attach to a camera
    2.  
    3. var mDelta = 10; // Pixels. The width border at the edge in which the movement work
    4. var mSpeed = 3.0; // Scale. Speed of the movement
    5.  
    6. private var mRightDirection = Vector3.right; // Direction the camera should move when on the right edge
    7.  
    8. function Update ()
    9. {
    10.     // Check if on the right edge
    11.     if ( Input.mousePosition.x >= Screen.width - mDelta )
    12.     {
    13.         // Move the camera
    14.         transform.position += mRightDirection * Time.deltaTime * mSpeed;
    15.     }
    16. }
    Omar Rojo
     
    rioooooo likes this.
  4. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    sorry omar, i tried applying the code to my main camera..but it seems when i move my mouse to the edge when on test play, it wont move as well...

    here's another script im using besides the one u gave me.

    Code (csharp):
    1.  var target : Transform;
    2. var distance = 5.0;
    3. var xSensitivity = 5.0;
    4. var ySensitivity = 5.0;
    5. var xAngle = 0.0;
    6. var yAngle = 0.0;
    7.  
    8. function LateUpdate ()
    9. {
    10.       // Only if there is a target
    11.    if (target)
    12.  
    13.       {
    14.         if (Input.GetMouseButton(1) )
    15.      
    16.       // Update x, y angle with the mouse delta
    17.       yAngle -= Input.GetAxis ("Mouse Y") * ySensitivity;
    18.      
    19.      
    20.       if (Input.GetMouseButton(1) )
    21.  
    22.      
    23.       xAngle += Input.GetAxis ("Mouse X") * xSensitivity;
    24.  
    25.       yAngle = Mathf.Clamp(yAngle, 0, 90);
    26.  
    27.       // Initialize the position to be distance units along the z axis
    28.       // away from the target
    29.       transform.position = Vector3.forward * distance + target.position;
    30.  
    31.       // Initialize the rotation to look at the target
    32.       transform.LookAt (target.position);
    33.      
    34.       // Rotate around the world up axis by the accumulated delta mouse x
    35.       transform.RotateAround (target.position, Vector3.up, xAngle);
    36.  
    37.       // Rotate around our own right vector by the accumulated delta mouse y
    38.       worldRight = transform.TransformDirection (Vector3.right);
    39.       transform.RotateAround (target.position, worldRight, yAngle);
    40.    }
    41. }
    this script only allows me to move my camera when i click on my right mouse button, and so i included the script you gave me as well but i did not put the codings together in a script. I seperated them, but i think its not the cause of seperating them right?
     
  5. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    In Omar's script, he changes the position of the camera with this line:
    Code (csharp):
    1. transform.position += mRightDirection * Time.deltaTime * mSpeed;
    However, if the "target" variable of your other script is set to something other than "none", it will set the position of the camera relative to that target, completely ignoring any changes that Omar's script made. One of lines that affect the position is this (there are more):
    Code (csharp):
    1. transform.position = Vector3.forward * distance + target.position;
    2.  
    So, to get Omar's script to work, try switching the other script off for now. (There is a checkmark in the inspector where the script is attached to the camera)

    You are probably using the other script, because you want some of the behaviour it has. But you can't have both scripts setting the position to something different and have it work.
     
  6. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    oh, its working. How bout any idea that combine that 2 scripts together ?
    i want to combine them to make a better camera movements.
     
  7. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Depends on what it precisely is you want the camera to do.
    Apparently you do not want the camera's position to be locked to a specific target. So what behaviour from "script B" is it that you want to combine with Omar's script?
     
  8. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    yes...i would like to combine my script with omar's script.
     
  9. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Yes, I understood that, but to do what?

    Since Omar's script does something like:
    "Set position to X"

    and the other script does something like:
    "Set position to Y"

    they cannot just be "mixed"

    Please describe in human terms, how you want the camera to move. It's been a while since I played Warcraft, so I am not clear on what it is you are trying to achieve.
     
  10. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    In my script you can move the camera to whatever position you want by setting the movement vectors correctly, it can even move reverse, or random, or arbitrarily defined directions.

    Try using the camera vectors.

    Code (csharp):
    1. private var mRightDirection = transform.right;
    Changing Vector3 to transform (if attached to a camera) will give you the axes of the camera in World Space. To get the left direction multiply transform.right by -1.

    I did it this way since i don't know what is the "Right direction" of your camera (cameras can be looking at any angle).
     
  11. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    Thanks Omar and Cblarsen!

    Code (csharp):
    1. var mDelta = 10; // Pixels. The width border at the edge in which the movement work
    2. var mSpeed = 3.0; // Scale. Speed of the movement
    3.  
    4. var xSensitivity = 5.0;
    5. var ySensitivity = 5.0;
    6. var xAngle = 0.0;
    7. var yAngle = 0.0;
    8.  
    9.  
    10. private var mForwardDirection : Vector3; // What direction does our camera start looking at
    11. private var mRightDirection : Vector3; // The inital "right" of the camera
    12. private var mUpDirection : Vector3; // The inital "up" of the camera
    13.  
    14. function Start()
    15. {
    16.    mForwardDirection = transform.forward;
    17.    mRightDirection = transform.right;
    18.    mUpDirection = transform.up;
    19. }
    20.  
    21. function LateUpdate ()
    22. {
    23.  
    24.    // Omars "change position part"
    25.    // Check if on the right edge
    26.    if ( Input.mousePosition.x >= Screen.width - mDelta )
    27.    {
    28.       // Move the camera
    29.       transform.position += mRightDirection * Time.deltaTime * mSpeed;
    30.    }
    31.  
    32.  
    33.    if ( Input.mousePosition.x <= 0 + mDelta )
    34.    {
    35.       // Move the camera
    36.       transform.position -= mRightDirection * Time.deltaTime * mSpeed;
    37.    }
    38.  
    39.  
    40.    if ( Input.mousePosition.y >= Screen.width - mDelta )
    41.    {
    42.       // Move the camera
    43.       transform.position += mUpDirection * Time.deltaTime * mSpeed;
    44.    }
    45.  
    46.    if ( Input.mousePosition.y <= 0 + mDelta )
    47.    {
    48.       // Move the camera
    49.       transform.position -= mUpDirection * Time.deltaTime * mSpeed;
    50.    }
    51.  
    52.  
    53.     // Changing an angle, if mouse button is held  
    54.     if (Input.GetMouseButton(1) )
    55.     {
    56.       // Update x, y angle with the mouse delta
    57.       xAngle += Input.GetAxis ("Mouse X") * xSensitivity;
    58.       yAngle -= Input.GetAxis ("Mouse Y") * ySensitivity;
    59.  
    60.       xAngle = Mathf.Clamp(xAngle, -45, 45);
    61.       yAngle = Mathf.Clamp(yAngle, 0, 90);
    62.    
    63.  
    64.       // Initialize the rotation to look in our preferred direction
    65.       transform.rotation = Quaternion.LookRotation( mForwardDirection, mUpDirection);
    66.      
    67.       // Rotate around the current up direction by the accumulated delta mouse x
    68.       transform.RotateAround (transform.position, transform.up, xAngle);
    69.  
    70.       // Rotate around our own right vector by the accumulated delta mouse y
    71.       transform.RotateAround (transform.position, transform.right, yAngle);
    72.    }
    73. }
    When you run the above code, when you rotate the camera you notice that your camera turn in a 45 degree way..how to make it turn straight instead of like slanting view? and also, would like to make it able to look to the sky.

    Secondly,when the mouse are moves to the edge, the camera only move to a limit of space, means when u rotate to the right and u put ur left mouse to the edge, it wont follow the direction of where ur looking at and move left, instead it move left by default view.

    What im looking for is kinda complicated. When the mouse move to the edge of top of screen..it move forward instead of up ( so i could reach to the end of another area) , when i rotate to another view and mouse on edge to move, it moves following the view that the user is. (so its able to move to another area as well). It's more like a free form of viewing camera system.

    Example i can think of is maybe Command Conquer style of camera view. U look on the terrain, move ur mouse cursor on the edge and it move around, and u can rotate ur camera as well to see the environment.

    Thanks
    Ernest.
     
  12. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Point 2 is the easiest to fix. Change the "move" section to this:

    Code (csharp):
    1.    if ( Input.mousePosition.x >= Screen.width - mDelta )
    2.    {
    3.       // Move the camera
    4.       transform.position += transform.right * Time.deltaTime * mSpeed;
    5.    }
    6.  
    7.  
    8.    if ( Input.mousePosition.x <= 0 + mDelta )
    9.    {
    10.       // Move the camera
    11.       transform.position -= transform.right * Time.deltaTime * mSpeed;
    12.    }
    13.  
    14.  
    15.    if ( Input.mousePosition.y >= Screen.width - mDelta )
    16.    {
    17.       // Move the camera
    18.       transform.position += transform.up * Time.deltaTime * mSpeed;
    19.    }
    20.  
    21.    if ( Input.mousePosition.y <= 0 + mDelta )
    22.    {
    23.       // Move the camera
    24.       transform.position -= transform.up * Time.deltaTime * mSpeed;
    25.    }
    About Point 1:
    There are probably two things wrong with the rotation
    - We are rotating around the wrong axes.
    - You seem to want to be able to rotate to any direction regardless of where the "ground" might be, or where the camera started out. Is that correct?

    If yes, I can make a quick rewrite of the script. It will actually be simpler than what it is doing now.
     
  13. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    yes, try making it able to rotate to any direction.
     
  14. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Important - do a "reset" in the inspector, because I changed xSensitivity and ySensitivity a lot, and the script will remember the old values if you don't change them yourself, or reset them.

    If you don't like the rotation, you can experiment with this line:
    Code (csharp):
    1.       transform.rotation = transform.rotation *
    2.         Quaternion.Euler(yAngleChange, 0, xAngleChange);
    3.  
    by changing the order of xAngleChange, 0, and yAngleChange in order to rotate around different axes.


    Code (csharp):
    1.  
    2. var mDelta = 10; // Pixels. The width border at the edge in which the movement work
    3. var mSpeed = 3.0; // Scale. Speed of the movement
    4. var xSensitivity = 100.0;
    5. var ySensitivity = 100.0;
    6.  
    7. function LateUpdate ()
    8. {
    9.  
    10.    // Omars "change position part"
    11.    // Check if on the right edge
    12.    if ( Input.mousePosition.x >= Screen.width - mDelta )
    13.    {
    14.       // Move the camera
    15.       transform.position += transform.right * Time.deltaTime * mSpeed;
    16.    }
    17.  
    18.  
    19.    if ( Input.mousePosition.x <= 0 + mDelta )
    20.    {
    21.       // Move the camera
    22.       transform.position -= transform.right * Time.deltaTime * mSpeed;
    23.    }
    24.  
    25.  
    26.    if ( Input.mousePosition.y >= Screen.height - mDelta )
    27.    {
    28.       // Move the camera
    29.       transform.position += transform.up * Time.deltaTime * mSpeed;
    30.    }
    31.  
    32.    if ( Input.mousePosition.y <= 0 + mDelta )
    33.    {
    34.       // Move the camera
    35.       transform.position -= transform.up * Time.deltaTime * mSpeed;
    36.    }
    37.  
    38.  
    39.     // Changing an angle, if mouse button is held  
    40.     if (Input.GetMouseButton(1) )
    41.     {
    42.       // Update x, y angle with the mouse delta
    43.       xAngleChange = Input.GetAxis ("Mouse X") * xSensitivity * Time.deltaTime;
    44.       yAngleChange = Input.GetAxis ("Mouse Y") * ySensitivity * Time.deltaTime;
    45.  
    46.       // Rotate around the current up direction by the delta mouse x
    47.       transform.rotation = transform.rotation *
    48.         Quaternion.Euler(yAngleChange, 0, xAngleChange);
    49.    }
    50. }
     
  15. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    ok nice, its free form now, but i think i need a little advice on the camera rotation part.

    try on this code, then you will know what type of rotation im looking for.

    Code (csharp):
    1.  var target : Transform;
    2. var distance = 5.0;
    3. var xSensitivity = 5.0;
    4. var ySensitivity = 5.0;
    5. var xAngle = 0.0;
    6. var yAngle = 0.0;
    7.  
    8. function LateUpdate ()
    9. {
    10.       // Only if there is a target
    11.    if (target)
    12.  
    13.       {
    14.         if (Input.GetMouseButton(1) )
    15.      
    16.       // Update x, y angle with the mouse delta
    17.       yAngle -= Input.GetAxis ("Mouse Y") * ySensitivity;
    18.      
    19.      
    20.       if (Input.GetMouseButton(1) )
    21.  
    22.      
    23.       xAngle += Input.GetAxis ("Mouse X") * xSensitivity;
    24.  
    25.       yAngle = Mathf.Clamp(yAngle, 0, 90);
    26.  
    27.       // Initialize the position to be distance units along the z axis
    28.       // away from the target
    29.       transform.position = Vector3.forward * distance + target.position;
    30.  
    31.       // Initialize the rotation to look at the target
    32.       transform.LookAt (target.position);
    33.      
    34.       // Rotate around the world up axis by the accumulated delta mouse x
    35.       transform.RotateAround (target.position, Vector3.up, xAngle);
    36.  
    37.       // Rotate around our own right vector by the accumulated delta mouse y
    38.       worldRight = transform.TransformDirection (Vector3.right);
    39.       transform.RotateAround (target.position, worldRight, yAngle);
    40.    }
    the rotation is not what i want,the code you wrote allow the camera to move (( )) instead of << >>. Example use our head as the camera, when i click and drag to right, ur head turns ) this way, for 45 degree for example, so u see things is like slanting. The exact thing i want is, when u click and drag to right, your head turns right,

    maybe the code above can explain for me (but it only allow for left,right and down, cant look up). Hope it give you a little idea on what im trying to explain. :)
     
  16. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Try changing the last two lines of code to

    Code (csharp):
    1.       transform.rotation = transform.rotation *
    2.         Quaternion.Euler(-yAngleChange, xAngleChange, 0);
    3.  
     
  17. Hansuke

    Hansuke

    Joined:
    Apr 17, 2007
    Posts:
    100
    Great, thanks heaps!
     
  18. slumberus

    slumberus

    Joined:
    Apr 17, 2007
    Posts:
    39
    Hijacking Han's thread with his permission. XD

    Currently the code allows rotation with the pivot point within the camera (like a fps view rotation). Is there a way to dynamically set the pivot point of the camera's rotation to an arbituary point in world space? This is not quite unlike the mouse orbit, but this time there is no target to rotate around.

    edit: also as the camera moves its position, the pivot point will move as well but still remain the same position in relative to the camera.

    Thanks!
    Chris
     
  19. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    Interesting idea. I might use that for something myself.

    Code (csharp):
    1. var mDelta = 10; // Pixels. The width border at the edge in which the movement work
    2. var mSpeed = 3.0; // Scale. Speed of the movement
    3. var xSensitivity = 100.0;
    4. var ySensitivity = 100.0;
    5.  
    6. var initialTarget : Transform;
    7. private var pivotCameraSpace : Vector3 = Vector3.zero;
    8.  
    9.  
    10. function Start()
    11. {
    12.     if (initialTarget)
    13.         SetPivotPoint( initialTarget.position );
    14. }
    15.  
    16. function SetPivotPoint( pivotWorldPos : Vector3 )
    17. {
    18.     // If you do not want the camera to actually look at the pivot point,
    19.     // uncomment the following line
    20.     transform.LookAt( pivotWorldPos, transform.up );
    21.    
    22.     pivotCameraSpace = transform.InverseTransformPoint( pivotWorldPos );
    23. }
    24.  
    25. function LateUpdate ()
    26. {
    27.  
    28.    // Omars "change position part"
    29.    // Check if on the right edge
    30.    if ( Input.mousePosition.x >= Screen.width - mDelta )
    31.    {
    32.       // Move the camera
    33.       transform.position += transform.right * Time.deltaTime * mSpeed;
    34.    }
    35.  
    36.  
    37.    if ( Input.mousePosition.x <= 0 + mDelta )
    38.    {
    39.       // Move the camera
    40.       transform.position -= transform.right * Time.deltaTime * mSpeed;
    41.    }
    42.  
    43.  
    44.    if ( Input.mousePosition.y >= Screen.height - mDelta )
    45.    {
    46.       // Move the camera
    47.       transform.position += transform.up * Time.deltaTime * mSpeed;
    48.    }
    49.  
    50.    if ( Input.mousePosition.y <= 0 + mDelta )
    51.    {
    52.       // Move the camera
    53.       transform.position -= transform.up * Time.deltaTime * mSpeed;
    54.    }
    55.  
    56.  
    57.     // Changing an angle, if mouse button is held  
    58.     if (Input.GetMouseButton(1) )
    59.     {
    60.       // Update x, y angle with the mouse delta
    61.       xAngleChange = Input.GetAxis ("Mouse X") * xSensitivity * Time.deltaTime;
    62.       yAngleChange = Input.GetAxis ("Mouse Y") * ySensitivity * Time.deltaTime;
    63.  
    64.       // rotate
    65.       var pivotWorldPos : Vector3 = transform.TransformPoint( pivotCameraSpace );
    66.      
    67.       transform.rotation = transform.rotation *
    68.         Quaternion.Euler(-yAngleChange, xAngleChange, 0);
    69.       // Adjust position, if the pivotpoint moved relative to us
    70.       transform.position += pivotWorldPos - transform.TransformPoint( pivotCameraSpace );
    71.    }
    72. }
    In Start() i used a transform in order to be able to test the code on something, but you can use whatever position you want.

    Also, since you say you want the pivot point to move along with the camera, you want to fix the position of the pivot in camera space, not world space. So that is what I made.
     
  20. Mr. Animator

    Mr. Animator

    Joined:
    Oct 2, 2005
    Posts:
    193
    I just recently devised an RTS style camera like this using a very different method. It's a little convoluted at first glance, but the end result is straightforward and makes the motion very smooth. I don't have the code or project handy but here's the general idea...

    To detect whether the mouse is on the edge of the screen, I simply have an invisible gui texture that covers everything except the region where I want scrolling to kick in. I use the OnMouseEnter and OnMouseExit functions to switch a variable back and forth between scrolling and not-scrolling. This variable, however, is not a simple 0 or 1 value, but rather a value ranging from 0 to 1. When the mouse exits the gui texture, it quickly adds up to 1 over the course of about a half second. When the mouse re-enters the texture, it quickly decrements back to zero, again over about a half second. I then use this value as a multiplier for whatever movement I apply to the camera. Therefore instead of going from a dead stop to full speed and back again, I get a half second of ease-in and ease-out.

    The way I determine the exact direction the camera should travel is by projecting a ray onto an invisible plane the camera is looking down on. I compare the contact point of that ray to the camera's focal point, determine the normalized vector, and then use that as the camera's movement vector. So if you're mouse is on the edge of the screen at a 2-o-clock position, the camera will scroll in that direction (not merely up/down/left/right).

    Finally, the camera isn't actually being controlled directly by any of this, but rather the camera is parented to an empty game object that represents its focal point. The scripts I've described translate this EGO around. Having the camera then orbit around its focal point is as simple as applying rotation to that EGO.
     
  21. Stick

    Stick

    Joined:
    Dec 14, 2007
    Posts:
    37
    Mr. Animator, I would greatly appreciate getting a working version of your camera code if you can share it. Your way of approaching it makes the most sense to me. Is there any way you can post it or send me an email of it? Please let me know. I am sure many posting and viewing this thread would be grateful for the added resource as well!
     
  22. Mr. Animator

    Mr. Animator

    Joined:
    Oct 2, 2005
    Posts:
    193
    I'll see if I can dig it up. I developed this camera system for a project I've since abandoned, but its probably buried on my drive somewhere.