Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by stopiccot · May 02, 2013 at 01:29 PM · inputmousetouch

Simulate touch with mouse

According to earlier questions about simulating touches with mouse you should use Input.GetMouseButton() on PC and Input.touches on smartphones. Haven't changed anything from that time? Do we have nice single interface right now? Or still need to write "if (Application.platform != RuntimePlatform.IPhonePlayer"?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

6 Replies

· Add your reply
  • Sort: 
avatar image
19

Answer by Tommynator · Oct 02, 2014 at 08:41 AM

Might be a bit late to follow up on this, but I just stumbled across the same problem and build a simple workaround that might be interesting for someone.

The scenario is: you build a mobile game and don't want to have a hybrid (mouse/touch) input system, just to be able to test in the editor. Using reflection you can gain read.write access on private members of any model e.g. UnityEngine.Touch and wrap everything up in something like this:

 using UnityEngine;
 using System.Reflection;
 using System.Collections.Generic;
 
 public class TouchCreator
 {
     static BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
     static Dictionary<string, FieldInfo> fields;
 
     object touch;
 
     public float deltaTime { get { return ((Touch)touch).deltaTime; } set { fields["m_TimeDelta"].SetValue(touch, value); } }
     public int tapCount { get { return ((Touch)touch).tapCount; } set { fields["m_TapCount"].SetValue(touch, value); } }
     public TouchPhase phase { get { return ((Touch)touch).phase; } set { fields["m_Phase"].SetValue(touch, value); } }
     public Vector2 deltaPosition { get { return ((Touch)touch).deltaPosition; } set { fields["m_PositionDelta"].SetValue(touch, value); } }
     public int fingerId { get { return ((Touch)touch).fingerId; } set { fields["m_FingerId"].SetValue(touch, value); } }
     public Vector2 position { get { return ((Touch)touch).position; } set { fields["m_Position"].SetValue(touch, value); } }
     public Vector2 rawPosition { get { return ((Touch)touch).rawPosition; } set { fields["m_RawPosition"].SetValue(touch, value); } }
 
     public Touch Create()
     {
         return (Touch)touch;
     }
     
     public TouchCreator()
     {
         touch = new Touch();
     }
 
     static TouchCreator()
     {
         fields = new Dictionary<string, FieldInfo>();
         foreach(var f in typeof(Touch).GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
         {
             fields.Add(f.Name, f);
             Debug.Log("name: " + f.Name);
         }
     }
 }

So - based on the previous approach of StarManta you should now be able to build your own touch simulator environment for the editor. Ideally you make use of the UNITY_EDITOR preprocessor tag to make sure to strip it from your final build and keep the mobile code clean.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image airmcmonky · Feb 13, 2015 at 10:46 PM 0
Share

I just want to say that this answer saved me a lot of headache. Unity remote has terrible touch movement detection and is giving me very inconsistent responses, so I needed a better way to test without building directly to iPad. $$anonymous$$aking an entire new input system was going to be a lot of work for something only needed for testing, so this was a perfect drop in utility.

avatar image jtrue · Apr 24, 2016 at 11:29 PM 2
Share

Can someone show how this is implemented?

avatar image l0calhost jtrue · Dec 14, 2017 at 08:03 PM 0
Share

Use the InputHelper example by @joonturbo which makes use of the TouchCreator class.

avatar image
11

Answer by joonturbo · Apr 28, 2015 at 11:46 PM

I added a script, called InputHelper, which uses Tommynator's TouchCreator. I just use InputHelper.GetTouches() instead of Input.touches() and it works perfectly.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class InputHelper : MonoBehaviour {
 
     private static TouchCreator lastFakeTouch;
 
     public static List<Touch> GetTouches()
     {
         List<Touch> touches = new List<Touch>();
         touches.AddRange(Input.touches);
 #if UNITY_EDITOR
         if(lastFakeTouch == null) lastFakeTouch = new TouchCreator();
         if(Input.GetMouseButtonDown(0))
         {
             lastFakeTouch.phase = TouchPhase.Began;
             lastFakeTouch.deltaPosition = new Vector2(0,0);
             lastFakeTouch.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
             lastFakeTouch.fingerId = 0;
         }
         else if (Input.GetMouseButtonUp(0))
         {
             lastFakeTouch.phase = TouchPhase.Ended;
             Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
             lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
             lastFakeTouch.position = newPosition;
             lastFakeTouch.fingerId = 0;
         }
         else if (Input.GetMouseButton(0))
         {
             lastFakeTouch.phase = TouchPhase.Moved;
             Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
             lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
             lastFakeTouch.position = newPosition;
             lastFakeTouch.fingerId = 0;
         }
         else
         {
             lastFakeTouch = null;
         }
         if (lastFakeTouch != null) touches.Add(lastFakeTouch.Create());
 #endif
            
 
  return touches;      
     }
 
 }

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image petersvp · Nov 07, 2015 at 02:04 AM 0
Share

Please fix your Stationary bug:

                 Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
                 lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
                 lastFakeTouch.phase = lastFakeTouch.deltaPosition.magnitude == 0 ? TouchPhase.Stationary : TouchPhase.$$anonymous$$oved;
avatar image $$anonymous$$ petersvp · Feb 13, 2017 at 10:07 PM 0
Share

where do you add this?

avatar image l0calhost $$anonymous$$ · Dec 14, 2017 at 08:04 PM 2
Share

Replace

 else if (Input.Get$$anonymous$$ouseButton(0))
          {
              lastFakeTouch.phase = TouchPhase.$$anonymous$$oved;
              Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
              lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
              lastFakeTouch.position = newPosition;
              lastFakeTouch.fingerId = 0;
          }

with

 else if (Input.Get$$anonymous$$ouseButton(0))
             {
                 //lastFakeTouch.phase = TouchPhase.$$anonymous$$oved;
                 Vector2 newPosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
                 lastFakeTouch.deltaPosition = newPosition - lastFakeTouch.position;
                 lastFakeTouch.phase = lastFakeTouch.deltaPosition.magnitude == 0 ? TouchPhase.Stationary : TouchPhase.$$anonymous$$oved;
                 lastFakeTouch.position = newPosition;
                 lastFakeTouch.fingerId = 0;
             }


avatar image
8

Answer by StarManta · Apr 04, 2014 at 09:42 PM

(How would you simulate a pinch with a mouse, or a three finger gesture?)

Obviously you can't. But that's no reason at all not to allow simulation of single-touch gestures.

And using platform-dependent compilation doesn't help a lick with TESTING touch input. I want to iterate quickly on my UI code, and I can't do that if it takes me 10 minutes to build and test a single code change.

So, yeah, this is still very much an unsolved issue. And you know what? All it would take is Unity allowing me to create my own instance of the Touch class. But no, it's a complete black box - everything is read-only and there's no useful constructor.

     foreach (Touch thisTouch in Input.touches) {
         HandleTouch(thisTouch);
     }
     
     if (Input.GetMouseButton(0) ) {
         Touch fakeTouch = new Touch();
         fakeTouch.fingerId = 10;
         fakeTouch.position = Input.mousePosition;
         fakeTouch.deltaTime = Time.deltaTime;
         fakeTouch.deltaPosition = Input.mousePosition - lastMousePosition;
         fakeTouch.phase =    (Input.GetMouseButtonDown(0) ? TouchPhase.Began : 
                             (fakeTouch.deltaPosition.sqrMagnitude > 1f ? TouchPhase.Moved : TouchPhase.Stationary) );
         fakeTouch.tapCount = 1;
         
         HandleTouch(fakeTouch);
     }

See? Useful, platform-agnostic touch handling. But no, Unity went out of their way to prevent me from doing that.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image nazia08 · Apr 08, 2014 at 11:56 AM 0
Share

it is possible to simulate mouse input to touches pointer with $$anonymous$$ulti Touch Vista

avatar image Graham-Dunnett ♦♦ · Apr 08, 2014 at 11:58 AM 0
Share

Yeah, and ins$$anonymous$$d we build a remote app that can run on the mobile device to allow you to test your game in the editor.

avatar image
0

Answer by Graham-Dunnett · May 02, 2013 at 08:41 PM

No, there's not a nice simple interface. (How would you simulate a pinch with a mouse, or a three finger gesture?)

What you should do now is use the platform dependent approach.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image g123 · Feb 10, 2014 at 06:56 AM 0
Share

You would simulate a pinch or 3 finger gesture in the same way as the iPhone simulator for xCode does it. Hold a key down, 2 fingers appear on screen - same for 3 etc.

Apple: Simulating User Gestures

avatar image rakkarage · Mar 22, 2015 at 04:02 PM 1
Share

http://touchscript.github.io/ also provides a working open source solution in unity editor

just hold down a key to save touches, so that when you hold control (for example) and touch twice in different spots both touches or more are still in collection till control is released

in ios they do it a little different and use control and the center point i think? you you just need control and one click to zoom ins$$anonymous$$d of two but i prefer the flexability provided with the first approach

avatar image
0

Answer by KirillKuzyk · May 28, 2020 at 08:52 AM

Unity translates these calls to the first touch on mobile: Input.GetMouseButtonDown(0), Input.GetMouseButton(0) and Input.GetMouseButtonUp(0) . So you can think of it as a common interface if you're interested in only one pointer at a time.

If you have a lot of already written code that relies on touch input, you can use this InputWrapper to test it in Editor. To use it, add this line on top of all scripts that uses UnityEngine.Input:

using Input = InputWrapper.Input;

 using UnityEngine;
 using UnityEngine.Assertions;
 
 
 namespace InputWrapper {
     public static class Input {
         static bool touchSupported => UnityEngine.Input.touchSupported;
         static Touch? fakeTouch => SimulateTouchWithMouse.Instance.FakeTouch;
 
         public static bool GetButton(string buttonName) {
             return UnityEngine.Input.GetButton(buttonName);
         }
 
         public static bool GetButtonDown(string buttonName) {
             return UnityEngine.Input.GetButtonDown(buttonName);
         }
 
         public static bool GetButtonUp(string buttonName) {
             return UnityEngine.Input.GetButtonUp(buttonName);
         }
 
         public static bool GetMouseButton(int button) {
             return UnityEngine.Input.GetMouseButton(button);
         }
 
         public static bool GetMouseButtonDown(int button) {
             return UnityEngine.Input.GetMouseButtonDown(button);
         }
 
         public static bool GetMouseButtonUp(int button) {
             return UnityEngine.Input.GetMouseButtonUp(button);
         }
 
         public static int touchCount {
             get {
                 if (touchSupported) {
                     return UnityEngine.Input.touchCount;
                 } else {
                     return fakeTouch.HasValue ? 1 : 0;
                 }
             }
         }
 
         public static Touch GetTouch(int index) {
             if (touchSupported) {
                 return UnityEngine.Input.GetTouch(index);
             } else {
                 Assert.IsTrue(fakeTouch.HasValue && index == 0);
                 return fakeTouch.Value;
             }
         }
 
         public static Touch[] touches {
             get {
                 if (touchSupported) {
                     return UnityEngine.Input.touches;
                 } else {
                     return fakeTouch.HasValue ? new[] {fakeTouch.Value} : new Touch[0];
                 }
             }
         }
     }
 
     internal class SimulateTouchWithMouse {
         static SimulateTouchWithMouse instance;
         float lastUpdateTime;
         Vector3 prevMousePos;
         Touch? fakeTouch;
 
 
         public static SimulateTouchWithMouse Instance {
             get {
                 if (instance == null) {
                     instance = new SimulateTouchWithMouse();
                 }
 
                 return instance;
             }
         }
 
         public Touch? FakeTouch {
             get {
                 update();
                 return fakeTouch;
             }
         }
 
         void update() {
             if (Time.time != lastUpdateTime) {
                 lastUpdateTime = Time.time;
                 
                 var curMousePos = UnityEngine.Input.mousePosition;
                 var delta = curMousePos - prevMousePos;
                 prevMousePos = curMousePos;
 
                 fakeTouch = createTouch(getPhase(delta), delta);
             }
         }
 
         static TouchPhase? getPhase(Vector3 delta) {
             if (UnityEngine.Input.GetMouseButtonDown(0)) {
                 return TouchPhase.Began;
             } else if (UnityEngine.Input.GetMouseButton(0)) {
                 return delta.sqrMagnitude < 0.01f ? TouchPhase.Stationary : TouchPhase.Moved;
             } else if (UnityEngine.Input.GetMouseButtonUp(0)) {
                 return TouchPhase.Ended;
             } else {
                 return null;
             }
         }
 
         static Touch? createTouch(TouchPhase? phase, Vector3 delta) {
             if (!phase.HasValue) {
                 return null;
             }
             
             var curMousePos = UnityEngine.Input.mousePosition;
             return new Touch {
                 phase = phase.Value,
                 type = TouchType.Indirect,
                 position = curMousePos,
                 rawPosition = curMousePos,
                 fingerId = 0,
                 tapCount = 1,
                 deltaTime = Time.deltaTime,
                 deltaPosition = delta
             };
         }
     }
 }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

25 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Switch Between Touch And Mouse Controls 0 Answers

Convert Touch input to Mouse input C#? 1 Answer

Can I fake the mouse/touch position relative to the real mouse/touch position? 0 Answers

Handle Mouse/Touch pan, zoom and click 0 Answers

Disabling touch events on Input.GetMouseButtonDown(1) 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges