Forum rules - please read before posting.

GameCamera2DDrag and use interactions

edited September 2023 in Technical Q&A

I am using a GameCamera2DDrag component to move around the scene.

When I start the drag gesture above a Hotspot that has a Use Interaction, then this interaction is triggered and the 2D camera drag movement does not initiate.

Is there a way it can work the other way around? Meaning that if the drag gesture starts above a Hotspot then that Hotspot's Use Interaction won't be triggered but the 2D camera drag movement will initiate? As far as I could see the Use Interaction is triggered on mouse down, but I couldn't find a way to make this work on mouse up.

Note: I am using the ControlsReader component from the "Integration: Input System" package available in the Downloads page, so that I can leverage Unity's new Input System.

Comments

  • Another way the above could work is if the Hotspot Use Interaction is triggered on mouse up instead of down, but I couldn't make it work even if I changed the Custom_GetMouseButtonDown (int button) delegate method of the ControlsReader from Mouse.current.leftButton.wasPressedThisFrame to Mouse.current.leftButton.wasReleasedThisFrame.

    I have also noticed that the logic that sets the dragState to DragState._Camera in PlayerInput first checks whether !KickStarter.playerInteraction.IsMouseOverHotspot() and that will always fail in my case.

  • I have also noticed that the logic that sets the dragState to DragState._Camera in PlayerInput first checks whether !KickStarter.playerInteraction.IsMouseOverHotspot() and that will always fail in my case.

    What's your AC version, and what platform are you building to? A bypass for this check should be provided in the latest release, in the form of the PlayerInteraction script's hotspotsPreventCameraDragging variable.

    When modifying ControlsReader, there may be a conflict with the "InteractionA" input, as this will also be read when detecting Hotspot interactions.

    If you uncheck Mouse clicks have default functionality? in the Settings Manager, then you should be able to just modify the Custom_GetButtonDown function instead - checking that the button parameter is "InteractionA" so as to not affect any other inputs.

    The other issue to contend with is that the mouse / InteractionA inputs are also used by default for camera-dragging. You can amend this, however, by creating a new input for the camera-drag (mapped to the LMB as with InteractionA), and then enter that input's name into the Player Input component's "Drag Override Input" field.

  • edited September 2023

    Ah yes, sorry for not disclosing the version: I was using version 1.78.3 of Adventure Creator. I have since upgraded to the latest release (1.78.4). I am currently building for WebGL although my project also supports iOS, Android and Windows / Mac / PC platforms. I am currently building for WebGL.

    Based on your reply I did the following:

    • Enabled the hotspotsPreventCameraDragging flag at the PlayerInteraction component.
    • Disabled 'Mouse clicks have default functionality?' option in the Settings Manager.
    • Created a new Action in the Input Manager called 'Drag', passed that string to the 'Drag Override Input' field in the PlayerInput component. The 'Drag' interaction has a 'Left Button [Mouse]' and a 'Press [Touchscreen]' binding (with no Interactions inside of them).
    • Changed the 'InteractionA' action's bindings to be 'Primary Touch/Tap' for Touchscreen and in the 'Left Button [Mouse]' action I added a 'Tap' interaction.

    What happens now is that the drag works as before, but every time I tap on a hotspot (with or without dragging), it doesn't trigger the interaction.

    (I haven't modified the Custom_GetButtonDown function as I have changed the input actions above)

  • Also if I leave only the first two changes described above, and completely disable GameCamera2DDrag so that it doesn't conflict with the Hotspot interaction, then if I change any of the following, clicking on a hotspot won't trigger the interaction:

    • Adding the following line to Custom_GetButtonDown() of the ControlsReader:
    if (axisName == "InteractionA")
        return inputAction.WasReleasedThisFrame();
    

    or

    • Changing the 'InteractionA' > 'Left Button [Mouse]' binding by adding a 'Tap' interaction so that it behaves like a button (press and release triggers it, or at least that's how I expect it to behave).
  • edited September 2023

    OK, here's how I think I was able to fix it, so that I can now drag around the camera and click to interact with hotspots on the mouse up with out the drag triggering the hotspots:

    • 'Mouse clicks have default functionality?' option ion Settings Manager is set to false.
    • 'Hotspots Prevent Camera Dragging' in the PlayerInteraction component is set to true.
    • Created a new Input Action called Drag set its Action Type to Button and created two bindings:

      • Left Button [Mouse] (Use in control scheme: Mouse and Keyboard)
      • Press [Touchscreen] (Use in control scheme: Touchscreen)
    • Passed the Drag as a value to the 'Drag Override Input' in the PlayerInput component.

    • Changed the 'InteractionA' input action bindings:
      • Left Button [Mouse] added a Tap interaction.
      • Changed the Press [Touchscreen] binding to a Primary Touch/Tap [Touchscreen] one and assinged it to the Touchscreen in 'Use in control scheme'.

    Then I went to my ControlsReader.cs and changed the Custom_GetButtonDown (string axisName) method to this:

    private bool Custom_GetButtonDown (string axisName)
    {
        InputAction inputAction = GetInputAction (axisName);
        if (inputAction == null)
        {
            return false;
        }
    
        bool wasPerformed = inputAction.WasPerformedThisFrame();
    
        if (axisName == "InteractionA" 
            && wasPerformed
            && Custom_GetButton("Drag") == false)
        {
            KickStarter.playerInput.ResetMouseClick();
        }
    
        return wasPerformed;
    }
    

    Essentially if the 'InteractionA' action (click) succeeds and the 'Drag' action fails, then the mouse state is reset to Normal so that the click interaction can be fulfilled (otherwise the mouse state is set to HeldDown and doesn't trigger the action).

    Maybe there is a better way of doing this (I am almost certain there is) but that's how I spent my day today and I want to share what I was able to come up with :blush:

  • Great work! It's a difficult area to be sure, given the combination of input system, multi-platform, scripting, and custom needs.

    I'm a little hesitant to share an alternative, as I don't want to undermine your efforts, but there may indeed be an easier way.

    When Input method is set to Touch Screen, a Hotspot input mode field will appear inside the "Touch screen settings" pane. When set to Touch Up, it'll require taps (and clicks in the Editor) to be released for a Hotspot to be interacted with.

    As a single option, it doesn't offer the granular control that your own scripted approach offers, but have a look to see if it's workable on a mobile device.

    If so, allowing this same behaviour on WebGL (Input method set back to Mouse And Keyboard) is just a case of commenting out line 617 in AC's PlayerInteraction script:

    if (KickStarter.settingsManager.inputMethod == InputMethod.TouchScreen && KickStarter.settingsManager.touchScreenHotspotInput == TouchScreenHotspotInput.TouchUp)
    

    If doing so gives you the behaviour you're looking for - without the need for overrides / amending ControlsReader - I can consider making this check optional.

  • Thanks for the great suggestion Chris!

    I have tried your approach which definitely is more straightforward than mine.

    It works really well on the 'Touch Screen' Input method but when I comment out the if check on line 617 and then switch Input method back to 'Mouse And Keyboard', although the logic mostly works (dragging does not activate hotspots, hotspots activate on touch up), there are times (e.g. after a drag occurs) when clicking on a hotspot doesn't trigger its interaction logic on the first click but on the second or sometimes the third click.

    Regarding input method flag, I have a couple of quick questions:

    • Shall I change the Input method from 'Mouse And Keyboard' to 'Touch Screen' and vice versa programmatically by checking the Application.isMobilePlatform flag or does it change automatically by a certain option? I have noticed that the autoSyncInputMethod flag of the ControlsReader controls the input method but the SetCurrentDevice doesn't seem to fire.
    • When the Input method is set to 'Touch Screen' I am getting 'InvalidOperationException: EnhancedTouch API is not enabled; call EnhancedTouchSupport.Enable()' errors on the console until I check the "Use Enhanced Touch Support" flag on the Controls Reader component. I haven't seen any way of that flag being set automatically so I assume I also have to enable it if Application.isMobilePlatform is true.
  • edited September 2023

    Shall I change the Input method from 'Mouse And Keyboard' to 'Touch Screen' and vice versa programmatically by checking the Application.isMobilePlatform flag or does it change automatically by a certain option? I have noticed that the autoSyncInputMethod flag of the ControlsReader controls the input method but the SetCurrentDevice doesn't seem to fire.

    SetCurrentDevice relies on checking the active control scheme, which can be.. tricky to say the least, at least in my experience. IIRC it's related to devices being required as opposed to optional - though it works on my end when switching between controller and keyboard.

    Though, the autoSyncInputMethod option is more intended for cases where the input method can be dynamic in a single session - i.e. the Player picks up a controller half-way through. If you don't need this behaviour, and can set the "Input method" once at the start and be done with it, you're better off doing so.

    If you uncheck the auto option, AC will not amend the "Input method" field - leaving you free to amend as necessary. To set an AC Manager field at runtime, right-click its label to get an API reference to it.

    When the Input method is set to 'Touch Screen' I am getting 'InvalidOperationException: EnhancedTouch API is not enabled; call EnhancedTouchSupport.Enable()' errors on the console until I check the "Use Enhanced Touch Support" flag on the Controls Reader component. I haven't seen any way of that flag being set automatically so I assume I also have to enable it if Application.isMobilePlatform is true.

    You should be safe to check the option as part of the prefab itself - I don't believe there's any harm in this being enabled when porting to a device that doesn't support it, but it'd be for Unity to confirm.

  • Thanks Chris! I will experiment more and decide which approach I will end up using. To be honest, I wasn't switching from the 'Mouse And Keyboard' input method to 'Touch Screen' when switching targets from desktop to mobile builds, and everything seemed to be working just fine, but maybe it's better if I do that.

  • It turns out that my approach, and more specifically the 'Mouse clicks have default functionality' seems to affect the drag and drop inventory behavior pretty drastically, which makes it unable to drag and drop items from the inventory box to the screen, as certain states are not being calculated correctly (the selected inventory item gets deselected immediately).

    Your approach seems to be working just fine with the drag and drop inventory behavior, so if it's not a big of an ask, can you look into making the following check optional in line 617 of the PlayerInteraction script?

    if (KickStarter.settingsManager.inputMethod == InputMethod.TouchScreen && KickStarter.settingsManager.touchScreenHotspotInput == TouchScreenHotspotInput.TouchUp)
    
  • I can - though you mentioned issues when repeatedly clicking Hotspots with this. Are those still present, or are there steps you can provide to recreate?

  • Ah yes, sorry I forgot to disclose that in my previous comment.

    I can no longer recreate the issue and I think it was probably due to some leftover setting I forgot to change back (either the 'Drag Override Input' flag or the changed Input Actions of my approach).

  • No problem, thanks for clarifying.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.