On Screen Controls not working correctly.

Sigh…

Is there a bug report for this? Pulling my hair out. Input schema repeatedly changes between Gamepad and Touch, causing nonstop cancel events to fire.

Apparently there is an “Isolated Mode” which seems to “fix” this except that it doesn’t because if you have a second on screen stick they start to break. On-screen Controls | Input System | 1.7.0

The only workaround I’ve come up with in hrs of trying to get this to work:

    public void Start()
    {
        EnhancedTouchSupport.Enable();
        playerInput.actions["Move"].performed += HandleMove;
        playerInput.actions["Move"].canceled += HandleMove;
    }
  
    public void HandleMove(InputAction.CallbackContext input)
    {
        if (playerInput.currentControlScheme != "Gamepad")
        {
            return;
        }
        var dir = input.ReadValue<Vector2>();
        OnActionMove.Invoke(dir);
    }

Basically just ignore inputs from other control schemes for these actions.

Except that when I simulate it on my Android using the Unity Remote app, the final “cancel” event is never called for the Gamepad control scheme. So annoying how inconsistent and buggy this whole thing is.

Hey all I reported this as a bug with a minimal reproducible project. Hopefully Unity will get back on it.

In the meantime, the best workaround that I’ve found is to create a custom On-Screen Stick component.

In my case I just copied Unity’s component, but removed the parts where it uses the broken buggy Input system.

The idea is that it is a drop-in replacement for the Unity built-in component, with the only difference being that you subscribe to events directly rather than doing it through the Player Input system.

For example:

    public OnScreenStickCustom movementStick;


    public void Start()
    {
        movementStick.onJoystickMove.AddListener(OnStickMove);
        movementStick.onJoystickRelease.AddListener(OnStickRelease);
    }

    public void OnStickMove(Vector2 direction)
    {
        Debug.Log(direction);
    }

    public void OnStickRelease()
    {
         Debug.Log("STOP");
    }

File attached with the custom component.

9265131–1296573–OnScreenStickCustom.cs (20.5 KB)

6 Likes

Hi all. I believe I have figured out the problem and have your temporary solution! I believe that the Player Input component subscribes to the input events on awake/start/onenable. However, it does this before your on-screen stick is ‘enabled’. Therefore, the playerinput does not ‘listen’ to the on-screen stick.

A custom fix is simply disabling and re-enabling your player input script. You can manually try this in the editor, and if everything else is set up correctly, it should work!

1 Like

thank you so much
it actually works!!

Sure enough Unity reviewed my report and confirmed that this IS a bug on their end. https://issuetracker.unity3d.com/issues/the-cancel-event-is-registered-every-frame-when-the-move-action-is-used

So yeah this is completely broken for who knows how long. Leaving this here for anyone that finds it useful, meanwhile I however have since moved on to Godot and am loving it!

5 Likes

so frustrating
what a waste of time
How do you even play/make a game if the input itself is so broken

Yes, Some problem here with Unity 2022.3 Lastested version.

So, anyone have any soluction for ScreenStick and Screen Buttons? All broke here

This is what I end up using, since the problem for me is just the OnScreenStick and my using PlayerInput for the rest of the OnScreenButtons

After Spending so much time I made this script, I am using the generated c# class for input action and it seem to fix all my issue with it, gonna leave it here, maybe it can help someone.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Temp : MonoBehaviour
{
[SerializeField] float lookSpeed = 5;
[SerializeField] float forceMagnitude = 10;
[SerializeField] float maxVelocity = 6;

PlayerInputAction playerInputAction;
Vector2 movementDirection;
Vector2 lookDirection;
Rigidbody rb;

private void Awake()
{
playerInputAction = new PlayerInputAction();
playerInputAction.Enable();
}

private void Update()
{
LookAtMouse();
}

private void FixedUpdate()
{
MovePlayer();
}

private void MovePlayer()
{
movementDirection = playerInputAction.Player.Move.ReadValue();
movementDirection.Normalize();

Vector3 movement = new Vector3(movementDirection.x, 0f, movementDirection.y);
rb.AddForce(movement * forceMagnitude, ForceMode.Force);
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxVelocity);
}

private void LookAtMouse()
{
lookDirection = playerInputAction.Player.Look.ReadValue();
lookDirection.Normalize();

Vector3 direction = new Vector3(lookDirection.x, 0f, lookDirection.y);

if (direction != Vector3.zero)
{
Quaternion lookRotation = Quaternion.LookRotation(direction, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, lookSpeed * Time.deltaTime);
}
}
}

Even if no script is attached, the on-screen stick cannot be dragged with the mouse (it immediately returns to 0,0).

I saw the script above.
“PlayerInputAction playerInputAction;”
This will result in an error.
what is this?

no this will not result in an error, the PlayerInputAction is a C# script that will generate automatically by clicking on the generate C# Script in the Input Action, and whatever you named your Input Action will be your C# Genrated Script.

in my case, I named my input action PlayerInputAction so my Generated C# script will be called PlayerInputAction.cs. hope this helps tell me if you have any other confusion related to my code.

Thank you for your kind explanation.
I think the script is working without any problems.
However, it didn’t solve my problem.
Do you know why?

https://drive.google.com/file/d/1Mxu9Fe5o8rai9h_joF4fmY4PtmX-E_u0/view?usp=drive_link

Hi guys, I just found this thread, right after posting almost the same question in another one. I think I have the same problem as everyone else. Seems to be a major general problem with how the Player Input works?

In my simple example I have a jump controlled by a On-Screen Button mapped to the Control Path "Button South (Gamepad). To execute the jump I have a PlayerInput component with a Unity Event. This is set up as in the few samples I have found.

The problem is that the Player Input scheme keeps changing back and forth between Touch and GamePad when i touch the On-Screen button (you can see the active Control Schema in the Player Input inspector). Sometimes cancelling the jump, and making the On-Screen button unresponsive.

I tried disabling Auto-Switch, setting the default schema to GamePad, but then the On-Screen button does not trigger at all. For testing I’m using the simulator game view with “Simulate Touch Input from Mouse” enabled in the Input Debugger.

I have also tried the On-Screen Stick, with the same type of problems. The stick just moves a tiny bit before the control scheme switches, cancelling the movement.

What would the correct way to setup and configure Action, PlayerInput and On-Screen controls? Seems like my sample should be one of the simplest to setup and use, almost out of the box?

The area and position of the stick on the screen,
I think it would be a good idea to make sure it doesn’t go to 0.0.
Avoid placing it on the bottom left.

Sorry if I misunderstood.

can you show me your input action setup and the script where you are taking inputs from the player, maybe after seeing that I can find the problem in your case.

also, I would recommend watching Code Monkey video about the input system

I am using the Generated C# Class variant of input action without using the player input component on the player, because any other way of using the input system does not solve my problem, hope the video helps somewhat.

here is the issue you using Player Input Component in your project don’t use that instead use C# Genrated Class method of taking inputs that way you don’t even need to use Player Input Component, by doing this solved my problem. I was also having the same problem as you previous by using Player Input Component and the Broadcast Messages. instead when i use C# Genrated Class method of taking input every issue solve itself.

1 Like

after seeing all your comments, I also tried out the Player Input Component with the Generated C# Class and it also worked fine without any issues, so now we have 2 options. we can use Generated C# Class with or without the Player Input Component, currently, I am trying out changing the input Schemes within the code according to the different devices and running different input codes according to that, will update when i able to do that.

https://drive.google.com/file/d/1Mxu9Fe5o8rai9h_joF4fmY4PtmX-E_u0/view?usp=drive_link
This is a problem before the script, and the image object to which the “on-screen stick” is attached does not move like a video.
Therefore, any script will not work.

can you also show me your player input or player movement script, because i think the problem is there in those scripts, if you can take a screenshot or put those scripts on google drive then i can see and if i find any issue related to it, i will try my best to help you