Quick answer: Browsers fire both a Touch event and a synthetic Mouse event for taps. Avoid handling both. Use the Touch object with Use Mouse Input enabled, or write logic only against Touch and ignore Mouse on mobile platforms.
Here is how to fix Construct 3 actions that run twice on tablets and phones — once for the touch event, once for the synthesized mouse event the browser also fires. The double-fire is invisible on desktop where touch is absent. On mobile, every tap costs the player two of whatever the action did. The fix is consolidating input handling on a single source.
The Symptom
A button on a tablet plays its sound twice per tap. Or a counter increments by 2 per click. Or a dialog confirms then immediately re-confirms. Desktop with mouse-only input behaves correctly.
What Causes This
Browser synthesizes mouse from touch. Web browsers fire touchstart, touchend, then often a mousedown/mouseup/click trio for every tap to support legacy code. Construct 3 surfaces both.
Both Mouse and Touch handlers active. Your event sheet has Mouse On Click and Touch On Tap on the same target. Both fire.
Touch object Mouse Input setting. The Touch object has a Use Mouse Input property that lets desktop mouse drive Touch events too. With it on, you can rely on Touch alone for both platforms.
The Fix
Step 1: Use Touch with Mouse Input. Add a Touch object to the project. Open its Properties and enable Use Mouse Input. Now Touch.On Tap fires for both touch and mouse clicks. You can delete Mouse handlers entirely.
Step 2: Consolidate logic on Touch.
Event: Touch -> On tap on Button
Action: Audio -> Play click sound
Action: System -> Add 1 to score
Remove any Mouse On Click event for the same button.
Step 3: If you must use Mouse, gate by platform.
Event: Browser -> Is on platform "Desktop"
Sub-event: Mouse -> On Left button Clicked on Button
Action: handle click
Event: Browser -> Is on platform "Mobile"
Sub-event: Touch -> On tap on Button
Action: handle click
This avoids double-fire by branching, but Touch with Mouse Input is simpler.
Step 4: For continuous input, use IsInTouch.
Event: Touch.IsInTouch
Action: Player -> Set position to (Touch.X, Touch.Y)
Touch.IsInTouch works for both pointer-down and finger-down when Mouse Input is enabled.
Step 5: Disable browser-default touch effects. Some browsers apply visual feedback or scrolling for touches. To prevent unintended interactions, in Project → Properties set Disable Touch Defaults to On.
Cross-Platform Best Practice
Always plan input on Touch as the primary source with Use Mouse Input enabled. This unifies behavior across desktop and mobile, eliminates double-fire, and keeps your event sheet smaller. Reserve Mouse-specific events for desktop-only features (right-click context menus, hover effects).
“Touch with Mouse Input handles both platforms. One event source, no double-fires.”
Related Issues
For touch input not working on mobile, see Touch Input Not Working. For pinch zoom issues, see Pinch Zoom Wrong Center.
Touch object. Use Mouse Input. Single event handler. The double-fire stops.