1
\$\begingroup\$

I am trying to implement my own runtime color picker that's easy to use for touch interfaces. I want the hue slider to be a ring, along these lines, except the whole ring texture would rotate when dragged.

I have scavenged enough code to get a raw image object rotating when dragged in a UI canvas in the manner I'm looking for:

    private float baseAngle;
    private Vector2 pos;
    
    public void OnBeginDrag(PointerEventData eventData)
    {
        pos = transform.position;
        pos = eventData.pressPosition - pos;
        baseAngle = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg;
        baseAngle -= Mathf.Atan2(transform.right.y, transform.right.x) * Mathf.Rad2Deg;
    }

    public void OnDrag(PointerEventData eventData)
    {
        pos = transform.position;
        pos = eventData.position - pos;
        float ang = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg - baseAngle;
        transform.rotation = Quaternion.AngleAxis(ang, Vector3.forward);
    }

Since it doesn't use colliders, how can I limit the draggable region to a circle within the square bounds of the texture? Even better, also limit it to a ring rather than a whole circle. Will I have to implement my own check based on some pure math or is there a built in way?

thanks!

\$\endgroup\$
1
  • \$\begingroup\$ EventSystem should raycast UI, you can check if the object currently being raycasted is the one you need, but it's probably going to raycast whole image and not just sprite, so it might not work. In that case you need your own system I guess. Thing is - think about ways a computer can detect collision in sprites, if it's not possible then it's probably not in the game engine. If you come to conclusion that it needs colliders or pixel value detection then use those. See if you can have polygonal colliders for sprites. Another way would be to block areas inside and outside from raycasting. \$\endgroup\$ May 1, 2021 at 13:21

1 Answer 1

0
\$\begingroup\$

You should consider how this detection can be achieved fundamentally, then search if this solution already exits in Unity engine.

• If I couldn't find anything specific - I would use a polygonal 2D/3D collider (may require a rigidbody). Or I would use 2 circle colliders in your case.

• If I had to write my own detection - I would use just simple radius calculations, first I would define min/max radius, then detect collision by using internal methods for UI collision which would give me the object I need, and the last step would be to calculate my mouse position relative to min/max radius that I have and to determine if it's inside these bounds.

My Comment: EventSystem should raycast UI, you can check if the object currently being raycasted is the one you need, but it's probably going to raycast whole image and not just sprite, so it might not work. In that case you need your own system I guess. Thing is - think about ways a computer can detect collision in sprites, if it's not possible then it's probably not in the game engine. If you come to conclusion that it needs colliders or pixel value detection then use those. See if you can have polygonal colliders for sprites. Another way would be to block areas inside and outside from raycasting.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .