Hi,
this topic has come up several times, but it always ended up in unsatisfying solutions.
Using the OnScreenStick I want to implement a floating/dynamic Joystick:
- Hidden by default.
- User starts touching the screen.
- Joystick will be visible and centered to the touch.
- When the users moves his finger the OnScreenStick follows according to its setup.
- User stops touching the screen.
- Joystick will be hidden.
This is a pretty common scenario for mobile games, so it should not be that hard to implement.
This is my control scheme:
My action map looks like this for this setup:
- Movement Action
- WSAD is just for testing in the editor.
- The Gamepad Left Stick moves the actual player character. The OnScreenStick component feeds the value.
- Touch Action
- Recognizing the user’s touch and position
All actions are of type Value/Vector2
.
OnScreenStick component:
In code I do:
// Component: InputReader
public void OnTouch(InputAction.CallbackContext context)
{
if (context.started)
{
TouchStart(context.ReadValue<Vector2>());
}
if (context.canceled)
{
TouchEnd();
}
}
// Component: JoystickPositionController
private void OnEnable()
{
InputReader.TouchStart += TouchStart;
InputReader.TouchEnd += TouchEnd;
}
private void OnDisable()
{
InputReader.TouchStart -= TouchStart;
InputReader.TouchEnd -= TouchEnd;
}
private void TouchStart(Vector2 position)
{
if (GameSettings.JoystickPosition != JoystickPosition.Dynamic)
{
return;
}
Debug.Log("TouchStart: " + position);
JoystickContainer.anchoredPosition = position;
JoystickContainer.gameObject.SetActive(true); // 1
}
private void TouchEnd()
{
if (GameSettings.JoystickPosition != JoystickPosition.Dynamic)
{
return;
}
Debug.Log("TouchEnd");
JoystickContainer.gameObject.SetActive(false); // 1
}
My expectation is that when I touch the screen, I get one log message with “TouchStart” and when I stop touching I’ll see “TouchEnd”.
What happens instead is that I get those messages spammed, one after the other.
If I remove the code at // 1
, I see the expected messages.
From what I understand so far, my Touch action gets canceled because the OnScreenStick also assigns an Action to the same controls. So after my touch has been recognized the OnScreenStick gets active and recognizes the touch as well, cancelling my touch again and thus TouchEnd
is called.
Or it could be that the OnScreenStick sends the current value to the Gamepad/LeftStick
, which switches the currently active device from TouchScreen to Gamepad, and thus, it cancels my Touch action again.
I wonder what the correct set up is to make this scenario work.
What I’ve tried so far:
- Using
Pass through
in myTouch
action, but it still happens. - Turning on
Use Isolated Input Actions
. - Using 3 different control schemes, one for each device (Keyboard/Gamepad/TouchScreen).
- Using
ExactPositionWithDynamicOrigin
which is indeed what I would need, but since I want to have a non-moving background image, I need to make the placement myself. Only the inner white part is contains theOnScreenStick
, everything else is background:
Any idea is welcome!
Thanks