这段代码用于在鼠标悬停时选择UI中的对象,并使用hoveredAction
将当前悬停的元素存储在类作用域中.
我觉得应该有一个更优雅的方法这种逻辑。我知道,如果光线投射的对象与存储的对象相同,我可以再添加一个检查来避免一些计算,但是"样板"else if (hoveredAction != null)
将持续存在
这不是我第一次遇到这种逻辑,但这次对我来说总结起来很简单,任何想法都会有所帮助。
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;
}
}
请注意,您的这也不完整:在if (obj.Count() > 0)
的情况下,您还需要将任何先前的命中设置为hidden
…如果previous hit == current
我将把它分开,只跟踪newCurrent hit和do,例如
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;
}
}