/// <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. }
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(); }