コード例 #1
0
    /// <summary>
    /// Called by `Event Trigger`'s Pointer Down
    /// </summary>
    public void NormalTouch(BaseEventData baseEventData)
    {
        PointerEventData pointerEventData = (PointerEventData)baseEventData;

        //Unity's input system does not include the timestamp, so we ask for the touch time from native side at this moment.
        //(But it is still not the real touch time, just that it can be compared with native touch's time.
        double nativeTouchTime = NativeTouch.GetNativeTouchTime();

        rememberRealTimeSinceStartup = Time.realtimeSinceStartup;

        //StringBuilder is a reference type that is also used in the touch callback. To prevent potentially 2 threads accessing at the same time, we are putting a lock on it.
        lock (stringBuilder)
        {
            if (lineCount > lineMax)
            {
                stringBuilder.Length = 0;
                lineCount            = 0;
            }

            stringBuilder.AppendLine(string.Format("Unity : CallbackTime {0} CallbackTime in native timestamp {1} Frame# {2} Pos {3}", rememberRealTimeSinceStartup, nativeTouchTime, Time.frameCount, pointerEventData.position));

            lineCount++;
            consoleText.text = stringBuilder.ToString();
            scrollRect.verticalNormalizedPosition = 0;
        }
    }
コード例 #2
0
    /// <summary>
    /// This is for using with the callback-based API.
    /// The other signature we can use, you replace `NativeTouchData` with `NativeTouchDataFull`, then start with full mode.
    ///
    /// You have to **ALWAYS keep in mind** that everything in this code scope may **not** be in Unity's main thread. (On Android it is like that)
    /// Since this is really called by whatever thread that is handling touches at native side! Be careful of things you could not do outside of Unity's main thread.
    /// For example `Time.___` are mostly main thread dependent. Calling them in this method's scope in Android will hard crash the game. (But usable in iOS)
    ///
    /// If you are accessing reference type, even if they are `static`, putting `lock(___)` statement on them is a good idea to ensure nothing in the main thread
    /// is doing something to it as the same time as this touch callback which might be in an other thread.
    ///
    /// The objective of this static receiver is to calculate and remember position, so that main thread comes around, the `Update()` could use this position to move the graphic.
    /// </summary>
    public static void NativeTouchStaticReceiver(NativeTouchData ntd)
    {
        //First, try to flip Y axis.

        //Get the screen resolution again just in case you rotate the demo. (Should cache only once in the real game, in the case of not using Dynamic Resolution Scaling)
        cachedRealScreenResolution = NativeTouch.RealScreenResolution();

        //If we use `Screen.height` here it would be incorrect in the case of using Resolution Scaling.
        //Native Touch's data is unscaled, unlike Unity's `Touch` data.
        var convertedY = cachedRealScreenResolution.y - ntd.Y;

#if UNITY_IOS
        var convertedPreviousY = cachedRealScreenResolution.y - ntd.PreviousY;
#endif

        //StringBuilder is a reference type that is also used in Unity's main thread `NormalTouch` method.
        //To prevent potentially 2 threads accessing at the same time, we are putting a lock on it.
        lock (stringBuilder)
        {
            //Use the touch from native side as you like
            if (lineCount > lineMax)
            {
                stringBuilder.Length = 0;
                lineCount            = 0;
            }

#if UNITY_IOS
            //iOS does not provide finger ID
            stringBuilder.AppendLine(string.Format("<color=red>NATIVE : Phase {0} Pos {1} {2} Movement {3} {4} Timestamp {5} CallbackTime {6} Frame# {7}</color>", ntd.Phase.ToString(), ntd.X, convertedY, ntd.X - ntd.PreviousX, convertedY - convertedPreviousY, ntd.Timestamp, rememberRealTimeSinceStartup, Time.frameCount));

            //iOS is on the main thread. We can just set the text here without fear of crashing the game.
            //But because this is static context, we need the NativeTouchDemo that is remembered to static.
            singleton.consoleText.text = stringBuilder.ToString();
            singleton.scrollRect.verticalNormalizedPosition = 0;
#elif UNITY_ANDROID
            //Android does not provide previous position and cannot get frame count since we are on the other thread.
            stringBuilder.AppendLine(string.Format("<color=red>NATIVE : Phase {0} Pos {1} {2} Timestamp {3} PointerID {4}</color>", ntd.Phase.ToString(), ntd.X, convertedY, ntd.Timestamp, ntd.PointerId));
            //We set text later on the main thread with Android
            //If we put the same thing as iOS here, you have about 10% chance of crashing uGUI because attempting to change text while in graphic rebuild loop.
#endif
        }

        //Be sure to scale to the current resolution to support resolution scaling.
        nativeFollowerPosition = new Vector2(Screen.width * (ntd.X / cachedRealScreenResolution.x), Screen.height * (convertedY / cachedRealScreenResolution.y));

        nativeTouchCount++;
        lineCount++;

#if UNITY_IOS
        //This is to show that even if you set the position here, on the callback that was called before the end of previous frame,
        //the position did not get submitted for drawing. It is too late.
        //And so in the demo scene you can never get the red square to be ahead of yellow no matter how fast you try to drag on the screen.
        Vector3 worldFollower = nativeFollowerPosition;
        singleton.nativeFollower.position = new Vector3(worldFollower.x, worldFollower.y, 0);
#endif

        //If you choose to disable Unity touch as start option,
        //Don't forget to prepare a way to get out of NativeTouch without relying on Unity's event system.
        //In this case we did not disable Unity touch so we can still press that Stop button.
    }
コード例 #3
0
    /// <summary>
    /// Do not play audio on EventTrigger down if we have Native Touch and it is enabled.
    /// We can do it faster via callbacks and ring buffer iteration instead.
    ///
    /// Regardless of modes, the light up logic will be run by `EventTrigger`.
    /// </summary>
    public void Down()
    {
        //The light up is working by `EventTrigger` no matter using Native Touch or not.
        image.color = downColor;

        if (!(NativeTouch.OnSupportedPlatform() && mainLogic.NativeTouchChecked))
        {
            PlayAudio(comingFromCallback: false);
        }
    }
コード例 #4
0
    /*
     * Retrieves touch data from native code.
     */
    public static List <NativeTouch> GetNativeTouches()
    {
        if (touches == null)
        {
            touches = new List <NativeTouch> ();
        }
        else
        {
            touches.Clear();
        }

                #if UNITY_EDITOR
        //do nothing
                #elif UNITY_IOS
        //Create a memory pointer
        IntPtr unmanagedPtr;

        //Receive binary data from native code. Native code also allocates memory for this data.
        int size = getNativeTouches(out unmanagedPtr);

        //if touches are available
        if (size > 0)
        {
            //copy binary data from unamanged memory to managed memory
            byte[] managedData = new byte[size];
            Marshal.Copy(unmanagedPtr, managedData, 0, size);

            int touchCount = (int)size / TOUCH_BINARY_SIZE;                   //each touch is serialized into 36 bytes of binary data
            for (var i = 0; i < touchCount; i++)
            {
                var temp = new NativeTouch()
                {
                    id              = BitConverter.ToInt32(managedData, i * TOUCH_BINARY_SIZE),
                    pos             = new Vector2(BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 4), BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 8)),
                    delta           = new Vector2(BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 12), BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 16)),
                    force           = BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 20),
                    maxforce        = BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 24),
                    radius          = BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 28),
                    radiusTolerance = BitConverter.ToSingle(managedData, i * TOUCH_BINARY_SIZE + 32)
                };

                touches.Add(temp);
            }

            //release unamanaged memory
            Marshal.FreeHGlobal(unmanagedPtr);
        }
                #else
        //do nothing
                #endif
        return(touches);
    }
コード例 #5
0
    public void StartNativeTouchButton()
    {
        NativeTouch.ClearCallbacks();
        NativeTouch.RegisterCallback(NativeTouchStaticReceiver);

        //We want only few essential data so that's "minimal" = not full
        NativeTouch.Start(new NativeTouch.StartOption {
            fullMode = false, disableUnityTouch = false
        });

        noCallbackEnabled = false;

#if !UNITY_EDITOR
        runningText.text = "Native touch is running (callback).";
#endif
    }
コード例 #6
0
    /*
     * You can remove this code if you don't rely on touch phase in your code.
     *
     * Add Native Touches to the list.
     */
    private void HandleNativeInput(NativeTouch touch)
    {
        for (int i = 0; i < touches.Count; i++)
        {
            if (touches[i].id == touch.id)
            {
                //if touch delta isn't zero - this touch moved since last frame, otherwise it remained stacionary
                touch.phase = (touch.delta != Vector2.zero) ? TouchPhase.Moved : TouchPhase.Stationary;
                touches[i]  = touch;
                return;
            }
        }

        //if touch wasn't found on the list, it must have just began
        touch.phase = TouchPhase.Began;
        touches.Add(touch);
    }
コード例 #7
0
    private void Awake()
    {
#if UNITY_IOS
        singleton = this;
#endif

#if !UNITY_EDITOR
        //If we use resolution scaling, the `Screen.` API will be scaled down but the point from native side is as if it is not scaled.
        //RealScreenResolution is the `Screen.` resolution as if it hadn't scaled.
        cachedRealScreenResolution = NativeTouch.RealScreenResolution();
#endif

        Debug.Log("UNITY RESOLUTION " + Screen.currentResolution + " " + Screen.width + " " + Screen.height);
        Debug.Log("REAL SCREEN RESOLUTION " + cachedRealScreenResolution);
        Application.targetFrameRate = 60;

        stringBuilder = new StringBuilder();
    }
コード例 #8
0
    public void StartNativeTouchButtonRingBuffer()
    {
        NativeTouch.ClearCallbacks();

        //This does nothing, for we disable the callback below...
        NativeTouch.RegisterCallback(NativeTouchStaticReceiver);

        //To iterate the ring buffer in main thread instead of handling the callback, we could potentially disable the callback to boost performance.
        //This is important in platform like Android IL2CPP where the callback is slow and you rather ONLY iterate the ring buffer.
        NativeTouch.Start(new NativeTouch.StartOption {
            fullMode = false, disableUnityTouch = false, noCallback = true
        });

        noCallbackEnabled = true;

#if !UNITY_EDITOR
        runningText.text = "Native touch is running (no callback).";
#endif
    }
コード例 #9
0
    public void StopLatestPlay()
    {
#if NATIVE_TOUCH_INTEGRATION
        Debug.Log("Native touch started!!");
        staticPointer = nativeAudioPointer;
        NativeTouch.RegisterCallback(NTCallback);
        NativeTouch.Start(new NativeTouch.StartOption {
            disableUnityTouch = true
        });
        NativeTouch.WarmUp();
        return;
#endif
        if (NotRealDevice())
        {
            return;
        }
        if (nativeAudioController != null)
        {
            nativeAudioController.Stop();
        }
    }
コード例 #10
0
 public void StopNativeTouch()
 {
     NativeTouch.Stop();
     runningText.text = "Stopped Native Touch";
 }
コード例 #11
0
        /// <summary>
        /// Refreshes touch inputs from Instant Preview to reflect the state
        /// since the last time Update was called.
        /// </summary>
        public static void Update()
        {
            if (!Application.isEditor)
            {
                return;
            }

            // Removes ended touches, and converts moves to stationary.
            for (int i = 0; i < s_TouchList.Count; ++i)
            {
                if (s_TouchList[i].phase == TouchPhase.Ended)
                {
                    s_TouchList.RemoveAt(i);
                    --i;
                    continue;
                }

                var curTouch = s_TouchList[i];
                curTouch.phase         = TouchPhase.Stationary;
                curTouch.deltaPosition = Vector2.zero;
                s_TouchList[i]         = curTouch;
            }

            // Updates touches.
            IntPtr nativeTouchesPtr;
            int    nativeTouchCount;

            NativeApi.GetTouches(out nativeTouchesPtr, out nativeTouchCount);

            var structSize = Marshal.SizeOf(typeof(NativeTouch));

            for (var i = 0; i < nativeTouchCount; ++i)
            {
                var         source      = new IntPtr(nativeTouchesPtr.ToInt64() + (i * structSize));
                NativeTouch nativeTouch = (NativeTouch)Marshal.PtrToStructure(source, typeof(NativeTouch));

                var newTouch = new Touch()
                {
                    fingerId = nativeTouch.Id,
                    phase    = nativeTouch.Phase,
                    pressure = nativeTouch.Pressure,

                    // NativeTouch values are normalized and must be converted to screen coordinates.
                    // Note that the Unity's screen coordinate (0, 0) starts from bottom left.
                    position = new Vector2(Screen.width * nativeTouch.X, Screen.height * (1f - nativeTouch.Y)),
                };

                var index = s_TouchList.FindIndex(touch => touch.fingerId == newTouch.fingerId);

                // Adds touch if not found, otherwise updates it.
                if (index < 0)
                {
                    s_TouchList.Add(newTouch);
                }
                else
                {
                    var prevTouch = s_TouchList[index];
                    newTouch.deltaPosition += newTouch.position - prevTouch.position;
                    s_TouchList[index]      = newTouch;
                }
            }

            s_Touches = s_TouchList.ToArray();
        }
コード例 #12
0
 public void StartNativeTouch()
 {
     Debug.Log("Start native touch!!");
     NativeTouch.StartNativeTouch();
 }