Hi, I’m making my first videogame using Unity.
I was recently scripting the camera movement for my 2D topdown shooter game. The camera needs to make a smooth movement towards the cursor, but the players always needs to be on the screen as well and there is also a maximum look distance. So this is what I came up with:
switch (playerInput.currentControlScheme)
{
case "KeyboardAndMouse":
Vector2 mousePos = Mouse.current.position.ReadValue();
mousePos.x = Mathf.Clamp(mousePos.x / Screen.width, 0f, 1f) - 0.5f;
mousePos.y = Mathf.Clamp(mousePos.y / Screen.height, 0f, 1f) - 0.5f;
pointerPos = transform.position + (Vector3)(mousePos * ((isLooking) ?
lookDistance :
MOUSE_IDLE_LOOK_DISTANCE));
break;
case "Gamepad":
Vector2 rightStick = Gamepad.current.rightStick.ReadValue();
Vector3 lookPos = Vector3.zero;
if (isLooking)
lookPos = rightStick * lookDistance;
else
lookPos = ((rightStick * 10).normalized * GAMEPAD_IDLE_LOOK_DISTANCE); // Only get stick direction
pointerPos = transform.position + lookPos;
if (crosshair != null)
{
if (lookPos.magnitude > 0f)
{
if (!crosshair.gameObject.activeInHierarchy) crosshair.gameObject.SetActive(true);
crosshair.anchoredPosition = (Vector2)Camera.main.WorldToScreenPoint(pointerPos) - (crosshair.sizeDelta / 2);
}
else
if (crosshair.gameObject.activeInHierarchy) crosshair.gameObject.SetActive(false);
}
break;
}
There must be, of course, two different systems, one for PC and one for gamepad. The gamepad part looks perfect, although I’m having a problem with the KeyboardAndMouse part.
Essentially, I get some kind of normalized 2D vector of the cursor position (for example, the top left corner of the screen is -0.5, 0.5) so that different sized resolutions don’t cause any problems with look distance. The components range from -0.5 to 0.5 instead from -1 to 1 because the player is supposed to be in the center of the screen.
Then, I add that “normalized” vector (multiplied by the look distance) to the player transform position.
Finally, in the FixedUpdate loop, the player character constantly rotates towards the pointer.
protected override void FixedUpdate()
{
base.FixedUpdate();
//Debug.Log($"{(pointerPos - Camera.main.ScreenToWorldPoint(Mouse.current.position.ReadValue())).magnitude}");
Vector2 lookDir = pointerPos - transform.position;
float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg;
rb.rotation = angle;
}
This works, although it has a pretty severe imprecision, and I have no idea what is causing it. It’s causing the player character to aim incorrectly. Look at the following image: the red dot is the calculated pointerPos, the green dot is the actual mouse position. They are unaligned.
After some time I managed to figure out what’s causing the problem, but I have no idea how to solve it. It’s the aspect ratio: setting the player window to 1:1 fixes the issue. Having it in rectangular ratios like 16:9 (mine) causes the aiming to be imprecise. But of course, the game needs to work on all aspect ratios.
Any suggestions?