Unity3d游戏物体、UGUI、NGUI、模型等等的点击、指向、移开事件(包括HTC手柄、Pico 手柄、鼠标等)

    xiaoxiao2022-07-01  125

    目的是将检测和响应分离开,降低耦合性,提高易用性;

    主要功能:鼠标(手柄)指向、移开、点击物体(这里的物体可以是游戏物体、模型、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; } } } }

     

    最新回复(0)