Home > Blockchain >  How to improve UI Selection logic?
How to improve UI Selection logic?

Time:12-08

So I have this piece of code to select objects in the UI on hover, and to store the currently hovered element in the class scope with hoveredAction.

I feel like there would be a more elegant approach of this logic. I know that I could add one more check to avoid some computation if the raycasted object is the same as the stored one, but the "boilerplate" else if (hoveredAction != null) would persist.

This isn't the first time I come across this kind of logic, but this time it is simple enough for me to summarize it, any Idea would help.

    void Update()
    {
        pointerEventData = new PointerEventData(eventSystem)
        {
            position = Input.mousePosition
        };
        List<RaycastResult> results = new();
        raycaster.Raycast(pointerEventData, results);
        if (results.Count > 0)
        {
            var result = results[0];
            var obj = allowedActions.Where(a => result.gameObject == a.UiObject.gameObject);
            if (obj.Count() > 0)
            {
                hoveredAction = obj.First();
                hoveredAction.UiObject.GetComponent<Image>().color = shown;
            }
            else if(hoveredAction != null)
            {
                hoveredAction.UiObject.GetComponent<Image>().color = hidden;
                hoveredAction = null;
            }
        }
        else if (hoveredAction != null) 
        {
            hoveredAction.UiObject.GetComponent<Image>().color = hidden;
            hoveredAction = null;
        }
    }

CodePudding user response:

Note that yours this is also not complete: In the case if (obj.Count() > 0) you also will want to set any previous hit to hidden ... or skip both if previous hit == current

I would split it up and only track the newCurrent hit an do e.g.

void Update()
{
    pointerEventData = new PointerEventData(eventSystem)
    {
        position = Input.mousePosition
    };

    List<RaycastResult> results = new();

    raycaster.Raycast(pointerEventData, results);

    // whenever you deal with linq make sure to iterate only once!
    Gamebject currentHoveredAction = results.Count == 0 ? null : allowedActions.Where(a => result.gameObject == a.UiObject.gameObject).FirstOrDefault();

    // This is 
    // - either you hit a different object than before
    // - you didn't hit anything before but do now
    // - or you did hit something before but nothing now
    if(hoveredAction != currentHoveredAction)
    {
        // if there is a previous hit reset it
        if (hoveredAction != null) 
        {
            hoveredAction.UiObject.GetComponent<Image>().color = hidden;
        }

        // if there is a current hit set it
        if(currentHoveredAction != null)
        {
            currentHoveredAction.UiObject.GetComponent<Image>().color = show; 
        }

        // either way store the new result
        hoveredAction = currentHoveredAction;
    }
}
  • Related