Creating a Scrolling Map for RTS and Strategy Games in Unity
Published
In Strategy and RTS games, the player can look around the map by putting the mouse cursor near the border of the game window: by doing this, the camera starts scrolling in the selected direction on the x axis and the z axis. This is a very important system for this kind of games and easy to implement.
To do this, there are a few things to keep in mind. First, this scrolling effect does not occur until the cursor reaches near the border of the window. So we’ll need to set some boundaries to start scrolling. For these boundaries, we’ll give them values between 0 and 0.5, since we’ll be considering them as % of the viewport (aka the screen size).
Then, we’ll need to get our Mouse Position, with Input.MousePosition. An important thing to remember is that Input.MousePosition gives us the mouse position in Screen Space and we need it in Viewport Space. This is where the camera comes in: cameras in Unity can handle conversion between different world spaces. In this case, we can convert from Screen Space to Viewport Space by using the Camera.ScreenToViewportPoint method.
Finally, we compare the cursor position in Viewport space to our selected boundaries, and scroll the map accordingly: our camera system is done!
The code is pretty straightforward with plenty of comments, feel free to use it:
publicclassMouseScreenScroller : MonoBehaviour{publicCamera mCamera; [Header("Settings")]publicfloat mCameraSpeed =5f;publicVector2 mBoundsTolerance =newVector2(0.10f, 0.10f); // start scrolling at X% from borderpublicbool bLockCameraOnStart =true; // confine camera to game screen// caching camera transformprivateTransform _mCameraTransform;// allocate memory to avoid GCprivateVector3 _mMousePosition;privateVector3 _mCameraTranslation =newVector3();privatevoidStart() { _mCameraTransform = mCamera.transform; if (bLockCameraOnStart) { Cursor.lockState = CursorLockMode.Confined; } }// Update is called once per framevoidUpdate() { _mCameraTranslation.x =0f; _mCameraTranslation.z =0f;// exchanging y and z to reconcile different space references // in this example, the camera is above ground, looking down on it so we are only interested// in the x and z axis. _mMousePosition = mCamera.ScreenToViewportPoint(Input.mousePosition); _mMousePosition.z = _mMousePosition.y; _mMousePosition.y =0f;// check if out of screen? if it is, don't move. This is unnecesary if the cursor is confined to the game screenif (_mMousePosition.x <0f|| _mMousePosition.x >1f|| _mMousePosition.z <0f|| _mMousePosition.z >1f) {// early returnreturn; }// now check if the mouse position has reached the threshold.// We are using Viewport space, which is gives coordinates within our screen as belonging to the range [0, 1]// so we can consider our bounds as percentages: if the mouse is in the leftmost or rightmost X%// of the screen, we need to move the camera in that directionif(_mMousePosition.x < mBoundsTolerance.x) { _mCameraTranslation.x =-1f; } elseif (_mMousePosition.x >1f- mBoundsTolerance.x) { _mCameraTranslation.x =1f; }if (_mMousePosition.z < mBoundsTolerance.y) { _mCameraTranslation.z =-1f; }elseif (_mMousePosition.z >1f- mBoundsTolerance.y) { _mCameraTranslation.z =1f; } _mCameraTransform.localPosition += Time.deltaTime * _mCameraTranslation * mCameraSpeed; }}