Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

RTS Camera Panning

Discussion in 'Scripting' started by Cloaked_Gamer, Aug 16, 2019.

  1. Cloaked_Gamer

    Cloaked_Gamer

    Joined:
    Jul 22, 2019
    Posts:
    4
    Howdy denizens of Unity, I've begun working on an RTS, but have gotten stuck on the camera panning and movement. I have a script that works just fine, but upon panning, the "WASD" movement doesn't change orientation with the direction the camera is facing. I'm unsure of how to fix this, so any help would be appreciated.

    (For some reason when inserting code, it messes up some of the formatting, so sorry about that.)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InputManager : MonoBehaviour
    6. {
    7.     public float panSpeed;
    8.     public float rotateSpeed;
    9.     public float rotateAmount;
    10.  
    11.     private Quaternion rotation;
    12.  
    13.     private float panDetect = 15f;
    14.     private float minHeight = 10f;
    15.     private float maxHeight = 75f;
    16.  
    17.     // Start is called before the first frame update
    18.     void Start() {
    19.  
    20.         rotation = Camera.main.transform.rotation;
    21.        
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update() {
    26.  
    27.         MoveCamera();
    28.         RotateCamera();
    29.  
    30.         if (Input.GetKeyDown(KeyCode.Space))
    31.         {
    32.             Camera.main.transform.rotation = rotation;
    33.         }
    34.  
    35.     }
    36.  
    37.     void MoveCamera()
    38.     {
    39.         float moveX = Camera.main.transform.position.x;
    40.         float moveY = Camera.main.transform.position.y;
    41.         float moveZ = Camera.main.transform.position.z;
    42.  
    43.         float xPos = Input.mousePosition.x;
    44.         float yPos = Input.mousePosition.y;
    45.  
    46.         if(Input.GetKey(KeyCode.A) || xPos > 0 && xPos < panDetect)
    47.         {
    48.             moveX -= panSpeed;
    49.         }
    50.         else if(Input.GetKey(KeyCode.D) || xPos < Screen.width && xPos > Screen.width - panDetect)
    51.         {
    52.             moveX += panSpeed;
    53.         }
    54.  
    55.         if(Input.GetKey(KeyCode.W) || yPos < Screen.height && yPos > Screen.height - panDetect)
    56.         {
    57.             moveZ += panSpeed;
    58.         }
    59.         else if(Input.GetKey(KeyCode.S) || yPos > 0 && yPos < panDetect)
    60.         {
    61.             moveZ -= panSpeed;
    62.         }
    63.  
    64.         moveY -= Input.GetAxis("Mouse ScrollWheel") * (panSpeed * 20);
    65.  
    66.         moveY = Mathf.Clamp(moveY, minHeight, maxHeight);
    67.  
    68.         Vector3 newPos = new Vector3(moveX, moveY, moveZ);
    69.  
    70.         Camera.main.transform.position = newPos;
    71.  
    72.     }
    73.  
    74.     void RotateCamera()
    75.     {
    76.         Vector3 origin = Camera.main.transform.eulerAngles;
    77.         Vector3 destination = origin;
    78.  
    79.         if(Input.GetMouseButton(2))
    80.         {
    81.             destination.x -= Input.GetAxis("Mouse Y") * rotateAmount;
    82.             destination.y += Input.GetAxis("Mouse X") * rotateAmount;
    83.         }
    84.  
    85.         if(destination != origin)
    86.         {
    87.             Camera.main.transform.eulerAngles = Vector3.MoveTowards(origin, destination, Time.deltaTime * rotateSpeed);
    88.  
    89.         }
    90.     }
    91. }
     
  2. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    1) use one of the build in function to convert from local space to world space (https://docs.unity3d.com/ScriptReference/Transform.InverseTransformDirection.html i think)

    2) take the vector you want to move by, multiply it with the rotation of the camera, then add it to the position.
    quaternions come first so (pos * rot) won't work, it needs to be (rot * pos)

    this is one of my methods for moving a camera, please excuse my excessive one-liner.
    Code (CSharp):
    1.             CamRig.position += Quaternion.Euler (0, CamRig.eulerAngles.y, 0)
    2.                 * new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical"))
    3.                 * (Input.GetKey (speedKey) ? moveSpeed * 5 : moveSpeed)
    4.                 * Time.deltaTime;
    5.  
     
    Kurt-Dekker likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Easy fix! You need to get the X and Z motions from your WASD controls, and put them into a vector of their own.

    In your code you are actually adding them to the camera position before putting it back in, so you have to change the order around:

    1. get X/Z input
    2. put into vector
    3. magic <<--- keep reading below
    4. add to camera position
    5. assign back to camera.

    The "magic" step above is you need to rotate that XZ Vector data around its Y axis according to the heading of the camera.

    If you have this variable:

    Code (csharp):
    1. Vector3 CameraMovement = ...;    // load X, Y and Z movement in here
    then this is the rotation you need to do:

    Code (csharp):
    1. float camHeading = Camera.main.transform.rotation.eulerAngles.y;
    2.  
    3. CameraMovement = Quaternion.Euler( 0, camHeading, 0) * CameraMovement;
    THEN go onto step 4 and 5 above.
     
    SparrowGS likes this.
  4. Cloaked_Gamer

    Cloaked_Gamer

    Joined:
    Jul 22, 2019
    Posts:
    4
    Hey, thanks for the reply! Unfortunately, I'm a newbie to Unity, so how would I implement this?