本文只作为参考,个人水平有限,望见谅!
最近接触HTC Vive的项目中,使用的UI交互要不就是World下的UGUI,要不就是使用立体的Sprite来实现。而最经常出现的就是多个选择按钮,高亮选择,点击执行操作。所以在这里总结出两种情况下的ButtonGroup类,提供给有需要的人。PC是可以使用的,在Vive中需要导入Vive Input Utility这个插件,由于时间关系我还没试过。
ButtonGroup.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public delegate void ButtonEventArg(BaseEventData data);
[System.Serializable]
public abstract class ButtonGroup
{
public bool canRepeatClick;
public List<ButtonEventArg> OnMouseEnter;
public List<ButtonEventArg> OnMouseExit;
public List<ButtonEventArg> OnMouseClick;
private int currentClickIndex;
private int currentEnterIndex;
public void Init(int heilightIndex)
{
OnMouseEnter = new List<ButtonEventArg>();
OnMouseExit = new List<ButtonEventArg>();
OnMouseClick = new List<ButtonEventArg>();
currentClickIndex = heilightIndex;
SetButtonSprite(currentClickIndex, true);
}
public void OnEnter(BaseEventData data)
{
int index = GetIndexFromData(data);
if (index == -1) return;
if (currentClickIndex!=index)
SetButtonSprite(currentClickIndex, false);
SetButtonSprite(index, true);
if (index < OnMouseEnter.Count && OnMouseEnter[index] != null)
OnMouseEnter[index](data);
currentEnterIndex = index;
}
public void OnExit(BaseEventData data)
{
int index = currentEnterIndex;
if (index == -1) return;
SetButtonSprite(index, false);
if (index<OnMouseExit.Count&&OnMouseExit[index] != null)
OnMouseExit[index](data);
currentEnterIndex = -1;
}
public void OnClick(BaseEventData data)
{
int index = GetIndexFromData(data);
if (index == -1) return;
SetButtonSprite(index, true);
if (index!=currentClickIndex)
SetButtonSprite(currentClickIndex, false);
if (index < OnMouseClick.Count && OnMouseClick[index] != null)
{
if(canRepeatClick||(!canRepeatClick&&index!=currentClickIndex))
OnMouseClick[index](data);
}
currentClickIndex = index;
}
protected abstract int GetIndexFromData(BaseEventData data);
protected abstract void SetButtonSprite(int index, bool heilight);
}
[System.Serializable]
public class UGUIButton
{
public Image image;
public Sprite normal;
public Sprite heilight;
}
[System.Serializable]
public class SpriteButton
{
public SpriteRenderer image;
public Sprite normal;
public Sprite heilight;
}
[System.Serializable]
public class UGUIButtonGroup:ButtonGroup
{
public List<UGUIButton> buttonList;
protected override int GetIndexFromData(BaseEventData data)
{
PointerEventData pData = (PointerEventData)data;
GameObject go = pData.pointerCurrentRaycast.gameObject;
if (!go) return -1;
Button bt = go.GetComponent<Button>();
if (!bt) return -1;
for(int i=0;i<buttonList.Count;i++)
{
if (buttonList[i].image.Equals(bt.image))
return i;
}
return -1;
}
protected override void SetButtonSprite(int index, bool heilight)
{
if (index != -1 && index < buttonList.Count && buttonList[index] != null)
buttonList[index].image.sprite = heilight ?
buttonList[index].heilight :buttonList[index].normal;
}
}
[System.Serializable]
public class SpriteButtonGroup : ButtonGroup
{
public List<SpriteButton> buttonList;
protected override int GetIndexFromData(BaseEventData data)
{
PointerEventData pData = (PointerEventData)data;
GameObject go = pData.pointerCurrentRaycast.gameObject;
if (!go) return -1;
SpriteRenderer sp = go.GetComponent<SpriteRenderer>();
if (!sp) return -1;
for (int i = 0; i < buttonList.Count; i++)
{
if (buttonList[i].image.Equals(sp))
return i;
}
return -1;
}
protected override void SetButtonSprite(int index, bool heilight)
{
if (index != -1 && index < buttonList.Count && buttonList[index] != null)
buttonList[index].image.sprite = heilight ?
buttonList[index].heilight : buttonList[index].normal;
}
}
test.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class test : MonoBehaviour {
public UGUIButtonGroup btGroup;
void Start () {
// 参数为按钮序号,-1表示不需要初始高亮按钮
btGroup.Init(0);
// 添加按钮事件
btGroup.OnMouseClick.Add(ClickBt1);
// 如果中间有一个按钮不需要事件则
// btGroup.OnMouseClick.Add((BaseEventData data) => { });
btGroup.OnMouseClick.Add(ClickBt2);
btGroup.OnMouseClick.Add(ClickBt3);
}
public void Click(BaseEventData data)
{
btGroup.OnClick(data);
}
void ClickBt1(BaseEventData data)
{
Debug.Log("Button 1 Clicked!");
}
void ClickBt2(BaseEventData data)
{
Debug.Log("Button 2 Clicked!");
}
void ClickBt3(BaseEventData data)
{
Debug.Log("Button 3 Clicked!");
}
//以下为鼠标进入Button就高亮的代码
//public void Enter(BaseEventData data)
//{
// btGroup.OnEnter(data);
//}
//public void Exit(BaseEventData data)
//{
// btGroup.OnExit(data);
//}
}
使用方法
1.UGUIButtonGroup
将所有Button引用和[正常态、高亮态图片]的引用拖入带有test脚本的物体中,将每个Button的Translation改为none并添加【EventTrigger】组件。最后根据需要为每个Button添加[PointClick]和[PointEnter+PointExit]事件,事件方法指定到test的物体上的[Click]和[Enter+Exit]就可以了。
2.SpriteButtonGroup
同上,只是还需要为每个Sprite添加【Box Collider】组件以及为摄像机添加 【Physics Racaster】组件即可。