Search Unity

Move RTS Camera along local axes

Discussion in 'Scripting' started by megisto, Aug 25, 2016.

  1. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    Hello,

    I have a camera, child of a rotated Null. This code makes the null move when mouse is on border of the screen.
    Script is on the Camera.
    My problem is that movement is always world relatives and I don't know how to make it move relatively to the null rotation (or screen coordinates?).

    Code (CSharp):
    1.  
    2. public class RTSCamera : MonoBehaviour {
    3.  
    4.     public float scrollZone = 30;
    5.     public float scrollSpeed = 5;
    6.  
    7.     public float xMax = 8;
    8.     public float xMin = 0;
    9.     public float zMax = 8;
    10.     public float zMin = 0;
    11.  
    12.     private Vector3 desiredPosition;
    13.  
    14.     private void Start () {
    15.         desiredPosition = transform.parent.position;
    16.    
    17.     }
    18.    
    19.     private void Update () {
    20.         {
    21.             //------------------------------x, z movement
    22.             float x = 0, y = 0, z = 0;
    23.             float speed = scrollZone * Time.deltaTime;
    24.  
    25.             if (Input.mousePosition.x < scrollZone)
    26.                 x -= speed;
    27.             else if (Input.mousePosition.x > Screen.width - scrollZone)
    28.                 x += speed;
    29.  
    30.             if (Input.mousePosition.y < scrollZone)
    31.                 z -= speed;
    32.             else if (Input.mousePosition.y > Screen.height - scrollZone)
    33.                 z += speed;
    34.  
    35.  
    36.             Vector3 move = new Vector3 (x, y, z) + desiredPosition;
    37.  
    38.             move.x = Mathf.Clamp (move.x, xMin, xMax);
    39.             move.z = Mathf.Clamp (move.z, zMin, zMax);
    40.             desiredPosition = move;
    41.             transform.parent.position = Vector3.Lerp (transform.parent.position, desiredPosition, 0.2f);
    42.         }
    43.     }
    44. }
    Thank you
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    That's not the only problem — you're also abusing Lerp.

    Anyway, there are several ways to solve this, but the easiest is probably to think of it this way: calculate the world position under the mouse cursor (by casting a ray, or doing a ray/plane intersection). Also calculate the world position several pixels "inward" (away from the edge of the screen). Find the difference between these two positions, and that's how you want to move the camera.

    HTH,
    - Joe
     
  3. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    What I want to move is the null, parent of the camera.

    Basically I want to move it on its local coordinates. I am not sure that calculate world position etc. under mouse cursor is the way to do so, are you sure?

    I think i should deal with quaternions, but it only gave me headhache so far...

    Thank you for the Lerp advise, i'll take a look at it.
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, I've done it this way before. There are other ways to do it (though none of them involving quaternions much), but this is the most direct. You're just saying: What is this place I'm pointing at? And where would it be if it were moved this way a little bit? OK, so move it that way.
     
  5. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    Ok, I think I got the point. I'll do some test with it, thx!
     
  6. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    usually they're referred to as an "empty", null means nothing which is a little confusing :confused:, especially if you run into a situation where you're describing "a null reference error on the null" o_O

    An "empty" is just a gameobject/transform without any other components and the terminology is taken from the text used in the creation drop down :D
     
    JoeStrout likes this.
  7. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    You are right. I was using Lightwave 3D terminology :)
     
    LeftyRighty likes this.
  8. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    Solved using transform.Translate.

    Thank you.
     
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You don't have to raycast at all. Just check if you're close to a screen edge (comparing mouse position X and Y to 0 and screen width/height) and move in that direction using the local forward and right.

    Code (csharp):
    1.  
    2. float x, y;
    3. if (mousePos.x < 10)
    4.     x = -10;
    5. else if (mousePos.x > Screen.width - 10)
    6.     x = 10;
    7.  
    8. if (mousePos.y < 10)
    9.     y = -10;
    10. else if (mousePos.y > Screen.height - 10)
    11.     y = 10;
    12.  
    13. transform.position = (transform.forward * x + transform.right * y) * Time.deltaTime;
    14.  
    If you want to do the right-click camera move then it becomes a bit more complicated because you have to store the initial mouse position and the current in order to calculate a distance delta but you still shouldn't have to do a raycast at all.
     
  10. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    I did it this way:
    Code (CSharp):
    1.         float x = 0, y = 0, z = 0;
    2.        
    3.         if (Input.mousePosition.x < scrollArea)
    4.             x -= scrollSpeed * Time.deltaTime * fov;
    5.         else if (Input.mousePosition.x > Screen.width - scrollArea)
    6.             x += scrollSpeed * Time.deltaTime * fov;
    7.        
    8.         if (Input.mousePosition.y < scrollArea)
    9.             z -= scrollSpeed * Time.deltaTime * fov;
    10.         else if (Input.mousePosition.y > Screen.height - scrollArea)
    11.             z += scrollSpeed * Time.deltaTime * fov;
    12.  
    13.         Vector3 move = new Vector3 (x, y, z);
    14.  
    15.         transform.Translate(move.x, 0, move.z, Space.Self);
    I multiply by fov so the far the camera, the fast the scroll (script contain a dynamic fov too).
     
    KelsoMRK and JoeStrout like this.