目的是将检测和响应分离开,降低耦合性,提高易用性;
主要功能:鼠标(手柄)指向、移开、点击物体(这里的物体可以是游戏物体、模型、UGUI、NGUI等等,可以说几乎任何需要交互的对象都适用),响应这三个操作;
基本原理:通过射线(Ray)来检测目标对象;
主要脚本:1、ButtonSetFather(定义一个父类主要包含三个响应方法,无需挂载)
2、OnTagetButton(挂在目标物体上,注册三个响应事件)
3、NormalButtonSet(挂在目标物体上重写父类方法,实现各自需求的功能)
4、InteroperatToRay(用来发射射线来检测碰触到的物体,随便挂载一个物体上)
5、还有一点不要忘记,目标物体上一定要有BoxCollider,大小自己调整
public abstract class ButtonSetFather : MonoBehaviour
{public abstract void OnFocusRespons(); //鼠标指向响应public abstract void OnLoseFocusRespons(); //鼠标离开响应public abstract void OnClickRespons(); //鼠标点击响应
}
public class OnTagetButton: MonoBehaviour
{//定义三个事件,这里需要引用命名空间“using UnityEngine.Events;”public UnityEvent OnClick, OnFocus, OnLoseFocus;private void Awake(){//这里可以设置每个物体的层级方便控制点击层级this.transform.gameObject.layer = 8; ButtonSetFather Bsf = this.GetComponent<ButtonSetFather>(); //实例化父类OnClick.AddListener(Bsf.OnClickRespons); //监听点击事件OnFocus.AddListener(Bsf.OnFocusRespons); //鉴听指向事件OnLoseFocus.AddListener(Bsf.OnLoseFocusRespons); //监听移开事件}public void GetFocus(){OnFocus.Invoke(); //响应指向}public void LoseFocus(){OnLoseFocus.Invoke(); //响应移开}public void GetClicked(){OnClick.Invoke(); //响应点击}
}
public class NormalButtonSet : ButtonSetFather
{//在这里可以根据自己需求改写这三个方法,我这里写的是指向变大,移开缩小Vector3 startScale;private void Start(){startScale = new Vector3(1f,1f,1f);}public override void OnClickRespons(){}public override void OnFocusRespons(){Debug.Log("射线指向于此");this.transform.localScale = startScale * 1.4f; //指向物体(UI)变大}public override void OnLoseFocusRespons(){Debug.Log("Loset");this.transform.localScale = startScale; //移开物体(UI)变小}
}
public class InteroperatToRay : MonoBehaviour
{private OnTagetButton _currentButton; //定义一个先接触到的对象public OnTagetButton CurrentButton{get{return _currentButton;}}private OnTagetButton_lastButton; //定义一个在_currentButton之前接触到的对象private Ray ray = new Ray(); //使用射线来检测碰触到的物体private RaycastHit hitInfo; private OnTagetButton hitButton; //用来临时存储碰触到的对象private void Update(){//射线从相机为远点发出指向鼠标位置ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out hitInfo, Mathf.Infinity, 1 << 8)){try{//使用try catch试着得到射线接触到的物体hitButton = hitInfo.transform.GetComponent<OnTagetButton>();}catch{Debug.LogError("标记为button的物体,没有mybutton script " + hitInfo.transform.name);}//如果得到了碰触到的物体if (hitButton != null){//使用_currentButton来存储碰触到的物体_currentButton = hitButton;if (_lastButton != _currentButton)//若这次和上次碰触到的不是一个对象{//次目标响应指向事件,这里可以根据自己需求写点击移开指向事件_currentButton.GetFocus(); if (_lastButton != null)//若上次的目标不为空,那么上次目标响应移开事件_lastButton.LoseFocus();_lastButton = CurrentButton;//这次目标付给_lastButton}}else{_currentButton = null;if (_lastButton != null){_lastButton.LoseFocus();_lastButton = null;}}}else{_currentButton = null;if (_lastButton != null){_lastButton.LoseFocus();_lastButton = null;}}}}