1.Reproduce CursorLockMode.Confined on WebGL.
2.(optional) Control virtual mouse cursor with gamepad.
3.(optional) Move the in-game monitor cursor with a physical mouse.
I would like to realize these.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Users;
public class VirtualCursorTest : MonoBehaviour
{
[SerializeField] private PlayerInput playerInput;
[SerializeField] private RectTransform cursorTransform;
[SerializeField] private Canvas canvas;
[SerializeField] private RectTransform canvasRectTransform;
[SerializeField] private float cursorSpeed = 100f;
private bool previousMouseState;
private Mouse virtualMouse;
private Mouse currentMouse;
private Camera mainCamera;
private void OnEnable ()
{
mainCamera = Camera.main;
currentMouse = Mouse.current;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
InputDevice virtualMouseInputDevice = InputSystem.AddDevice("VirtualMouse");
if (virtualMouseInputDevice == null) {
virtualMouse = (Mouse)InputSystem.AddDevice("VirtualMouse");
}
else if (!virtualMouseInputDevice.added) {
virtualMouse = (Mouse)InputSystem.AddDevice("VirtualMouse");
}
else {
virtualMouse = (Mouse)virtualMouseInputDevice;
}
InputUser.PerformPairingWithDevice(virtualMouse, playerInput.user);
if (cursorTransform != null) {
Vector2 position = cursorTransform.anchoredPosition;
InputState.Change(virtualMouse.position, position);
}
InputSystem.onAfterUpdate += UpdateMotion;
}
private void OnDisable ()
{
if (virtualMouse != null && virtualMouse.added) InputSystem.RemoveDevice(virtualMouse);
InputSystem.onAfterUpdate -= UpdateMotion;
}
private void UpdateMotion ()
{
if (virtualMouse == null || Gamepad.current == null) return;
Vector2 deltaValue = currentMouse.delta.ReadValue();
Vector2 currentPosition = virtualMouse.position.ReadValue();
Vector2 newPosition = currentPosition + deltaValue;
newPosition.x = Mathf.Clamp(newPosition.x, 0, Screen.width);
newPosition.y = Mathf.Clamp(newPosition.y, 0, Screen.height);
InputState.Change(virtualMouse.position, newPosition);
InputState.Change(virtualMouse.delta, deltaValue);
bool aButtonIsPressed = Mouse.current.leftButton.IsPressed();
if (previousMouseState != Mouse.current.leftButton.isPressed) {
virtualMouse.CopyState<MouseState>(out var mouseState);
mouseState.WithButton(MouseButton.Left, aButtonIsPressed);
InputState.Change(virtualMouse, mouseState);
previousMouseState = aButtonIsPressed;
}
AnchorCursor(newPosition);
}
private void AnchorCursor (Vector2 position)
{
Vector2 anchoredPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, position, canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : mainCamera, out anchoredPosition);
cursorTransform.anchoredPosition = anchoredPosition;
}
}
With this script, I put the mouse cursor in the CursorLockMode.Locked state, operated the virtual mouse with the delta value of the physical mouse, and reflected it in the GUI.
However, when CursorLockMode.None, both cursor movement and button operation can be performed normally, but when CursorLockMode.Locked, the button does not respond even if the cursor can be moved.
anybewitchedkob
When InputSystemUIInputModule.cursorLockBehavior is set to ScreenCenter, even if the cursor is off the center button, it can be highlighted or clicked, so this part is probably overriding the position.
Is there any good way to solve this problem?
Unity 2021.3.9f1
Input System 1.4.3
I’m not very good at English and I use online translators a lot, so I’m sorry if my sentences sound weird.