public IEnumerator NearInteractionTouchableOverlapQuerySaturation()
        {
            // Use all the points
            int numTouchables = NumRandomPoints;
            var touchables    = new NearInteractionTouchable[numTouchables];
            var catchers      = new TouchEventCatcher[numTouchables];

            // Spread out touchables over a radius, decrease over time to increase density and fill the buffer
            float radiusStart = 1.0f;
            float radiusEnd   = 0.01f;

            for (int i = 0; i < numTouchables; ++i)
            {
                Vector3 r = GetRandomPoint(i);

                touchables[i] = CreateTouchable <NearInteractionTouchable>(0.15f);
                touchables[i].SetLocalForward(touchNormal);
                touchables[i].SetBounds(new Vector2(0.5f, 0.5f));
                touchables[i].transform.position = objectPosition + r * radiusStart;

                catchers[i] = CreateTouchEventCatcher(touchables[i]);
            }

            yield return(new WaitForFixedUpdate());

            yield return(null);

            yield return(PlayModeTestUtilities.ShowHand(Handedness.Right, inputSim));

            yield return(PlayModeTestUtilities.MoveHand(initialHandPosition, objectPosition, ArticulatedHandPose.GestureId.Open, Handedness.Right, inputSim, 1));

            for (int i = 0; i < PlayModeTestUtilities.ControllerMoveSteps; ++i)
            {
                float scale = radiusStart + (radiusEnd - radiusStart) * (i + 1) / PlayModeTestUtilities.ControllerMoveSteps;
                for (int j = 0; j < numTouchables; ++j)
                {
                    Vector3 r = GetRandomPoint(j + 10);
                    touchables[j].transform.position = objectPosition + r * scale;
                }
                yield return(null);
            }

            yield return(PlayModeTestUtilities.HideHand(Handedness.Right, inputSim));

            foreach (NearInteractionTouchable touchable in touchables)
            {
                Object.Destroy(touchable.gameObject);
            }
        }
        private TouchEventCatcher CreateTouchEventCatcher(BaseNearInteractionTouchable touchable)
        {
            var catcher = TouchEventCatcher.Create(touchable.gameObject);

            catcher.OnTouchStartedEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = pokeMaterial;
            });
            catcher.OnTouchCompletedEvent.AddListener(() =>
            {
                touchable.GetComponent <Renderer>().material = idleMaterial;
            });

            return(catcher);
        }
        public IEnumerator NearInteractionTouchableStack()
        {
            // Ignoring this test for now, as it needs fixing
            Assert.Ignore();

            int numTouchables = 10;
            var touchables    = new NearInteractionTouchable[numTouchables];
            var catchers      = new TouchEventCatcher[numTouchables];

            for (int i = 0; i < numTouchables; ++i)
            {
                Vector3 r = GetRandomPoint(i);

                touchables[i] = CreateTouchable <NearInteractionTouchable>(0.15f);
                touchables[i].SetLocalForward(touchNormal);
                touchables[i].SetBounds(new Vector2(0.5f, 0.5f));
                touchables[i].transform.position = objectPosition + new Vector3(0.02f * r.x, 0.015f * r.y, 0.1f * i - 0.5f);

                catchers[i] = CreateTouchEventCatcher(touchables[i]);
            }

            yield return(new WaitForFixedUpdate());

            yield return(null);

            yield return(PlayModeTestUtilities.ShowHand(Handedness.Right, inputSim));

            yield return(PlayModeTestUtilities.MoveHand(initialHandPosition, objectPosition, ArticulatedHandPose.GestureId.Open, Handedness.Right, inputSim));

            // No. 0 is touched initially
            TestEvents(catchers, new int[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new int[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
            yield return(PlayModeTestUtilities.MoveHand(objectPosition, rightPosition, ArticulatedHandPose.GestureId.Pinch, Handedness.Right, inputSim));

            // Only No. 3 gets touched when moving through the row, because No. 0 is still active while inside the poke threshold
            TestEvents(catchers, new int[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, new int[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 });
            yield return(PlayModeTestUtilities.MoveHand(rightPosition, objectPosition, ArticulatedHandPose.GestureId.Pinch, Handedness.Right, inputSim));

            // No. 3 touched a second time
            TestEvents(catchers, new int[] { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, new int[] { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0 });

            yield return(PlayModeTestUtilities.HideHand(Handedness.Right, inputSim));

            foreach (NearInteractionTouchable touchable in touchables)
            {
                Object.Destroy(touchable.gameObject);
            }
        }