Unity3d游戏物体和UI响应事件(包括VR手柄,鼠标)

目的是将检测和响应分离开,降低耦合性,提高易用性(感谢孙老师指导);

主要功能:鼠标(手柄)指向、移开、点击物体,响应这三个操作;

主要脚本:1、ButtonSetFather(定义一个父类主要包含三个响应方法)

                   2、OnTagetButton(挂在目标物体上,注册三个响应事件)

                   3、NormalButtonSet(挂在目标物体上重写父类方法,实现各自需求的功能)

                   4、InteroperatToRay(用来发射射线来检测碰触到的物体)

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();  //实例化父类
        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();
            }
            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;
            }
        }
    }

}

 

你可能感兴趣的:(学习,Unity3d,SteamVR,射线点击检测物体UI)