OnPointerExit Issue w/ Radial Menu on Android

Greetings! In my mobile game, I connect to my game server to get a list of X characters and then once they are loaded, I instantiate them into my scene. Each of the characters has a radial menu of actions they can take that activates when you touch and hold. When you release, the menu goes away. While the menu is displaying, you can move your touch onto one of the menu options and release, which will choose that option. I have implemented the radial menu based on the following YouTube tutorial: Unity Tutorial: Radial Menu (Part 1) from Board to Bits - YouTube – the only thing I’ve added is code to take the selected action, which is not covered in the tutorial.

Everything works perfect in the Unity Editor. However, when I run it on my Android device, I run into a “small” problem. When I release on a menu item, the action never occurs. After thorough debugging, it looks like the issue is that the OnPointerExit handler which is used to deselect the button gets called when I lift my finger (remove the touch) and not just when I move my touch off of the button. So, basically, choosing a menu option is acting the same as deselecting it.

Here’s the code:

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;

public class RadialButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
	
	public Image circle;
	public Image icon;
	public string title;
	public Interactable.InteractableAction action;
	public RadialMenu myMenu;
	public float speed = 8f;

	Color defaultColor;

	public void Anim() {
		StartCoroutine (AnimateButtonIn ());
	}

	IEnumerator AnimateButtonIn() {
		transform.localScale = Vector3.zero;
		float timer = 0f;
		while (timer < (1 / speed)) {
			timer += Time.deltaTime;
			transform.localScale = Vector3.one * timer * speed;
			yield return null;
		}
		transform.localScale = Vector3.one;
	}

	public void OnPointerEnter (PointerEventData eventData)
	{
		myMenu.selected = this;
		defaultColor = circle.color;
		circle.color = Color.white;
	}

	public void OnPointerExit (PointerEventData eventData)
	{
		myMenu.selected = null;
		circle.color = defaultColor;
	}
}

I have tried to implemented a separate touch system using preprocessor directives, but that has been a colossal failure. Any elegant solution to this? Is it possible on touch ended to prevent the on pointer exit handler from processing temporarily or something cheeky?

Unfortunately, IPointerUpHandler did nothing (quite literally). I think it requires a collider, possibly. The documentation is pretty sparse. I found an elegant solution, however:

public void OnPointerExit (PointerEventData eventData)
	{
		if (Input.touchSupported) {
			if (Input.touches [0].phase == TouchPhase.Ended) {
				myMenu.selected = this;
			} else {
				myMenu.selected = null;
			}
		} else {
			myMenu.selected = null;
		}
		circle.color = defaultColor;
	}

Basically, we check if we’re on a touch system and if the finger has been lifted to set the action. If we exit for any reason other than the finger lifting, we deselect. On a non-touch system, we always deselect, because the exit handler only gets called when we mouse off and not when we release the mouse. In all cases, we reset the button color.