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;
}
}