在游戏的编程之中,基本上都需要依赖鼠标的输出,特别是在手机游戏上,绝大部分都需要通过手指触摸来控制游戏。如果要实现一个精灵,当手指点击精灵的会触发相关的操作,或者我们使用一张图片来作为按钮,点击的时候触发相关的操作,这时候就需要使用鼠标输入处理了。处理鼠标输入会有下面的3种方式:

1、使用鼠标事件OnMouseDown、OnMouseDrag、OnMouseEnter、OnMouseExit、OnMouseOver、OnMouseUp

使用鼠标事件需要两个步骤,首先需要先给游戏对象添加Collider,这个Collider可以是2D或者3D的,然后给游戏对象添加脚本处理鼠标事件,示例代码如下所示:



using UnityEngine;
using System.Collections;

public class ObjectTouch : MonoBehaviour
{    
    //Called on mouse down
    void OnMouseDown()
    {
        Debug.Log ("You clicked me");
    }
}



2、使用Input.GetMouseButton方法
    使用Input.GetMouseButton方法和使用鼠标事件的区别是,鼠标事件是在操作的瞬间触发的,使用Input.GetMouseButton方法是在游戏对象的Update方法里面,通过每一帧的处理来进行判断。脚本如下所示:



// Update is called once per frame
    void Update ()
    {
        //Is left button being pressed?
        if(Input.GetMouseButton(0))
            Debug.Log("Left Button Pressed");
         
        //Is middle button being pressed?
        if(Input.GetMouseButton(2))
            Debug.Log("Middle Button Pressed");
         
        //Is right button being pressed?
        if(Input.GetMouseButton(1))
            Debug.Log("Right Button Pressed");

        //Get mouse x position on screen
        float X = Input.mousePosition.x;
        float Y = Input.mousePosition.y;
    }



3、使用射线Ray
    射线是3D里面的概念,当然在2D游戏里面一样可以使用。

射线:射线是3D世界中一个点向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射 。

用途:射线应用范围比较广, 多用于碰撞检测(如:子弹飞行是否击中目标)、角色移动等 等。

相关API:

(1)Ray Camera.main.ScreenPointToRay(Vector3 pos)   返回一条射线Ray从摄像机到屏幕指定一个点

(2)Ray Camera.main.ViewportPointToRay(Vector3 pos)  返回一条射线Ray从摄像机到视口(视口之外无效)指定一个点

(3)Ray 射线类

(4)RaycastHit 光线投射碰撞信息

(5)bool Physics.Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask)

    当光线投射与任何碰撞器交叉时为真,否则为假。

    bool Physics.Raycast(Ray ray, Vector3 direction, RaycastHit out hit, float distance, int layerMask)

    在场景中投下可与所有碰撞器碰撞的一条光线,并返回碰撞的细节信息()。

    bool Physics.Raycast(Ray ray, float distance, int layerMask)

    当光线投射与任何碰撞器交叉时为真,否则为假。

    bool Physics.Raycast(Vector3 origin, Vector3 direction, RaycastHit out hit,float distance, int layerMask)

    当光线投射与任何碰撞器交叉时为真,否则为假。

 

    注意:如果从一个球型体的内部到外部用光线投射,返回为假。

    参数理解:

  origin : 在世界坐标中射线的起始点

  direction: 射线的方向

  distance: 射线的长度

  hit: 使用c#中out关键字传入一个空的碰撞信息类,然后碰撞后赋值。可以得到碰撞物体的transform,rigidbody,point等信息。

  layerMask: 只选定Layermask层内的碰撞器,其它层内碰撞器忽略。 选择性的碰撞

(6)RaycastHit[] RaycastAll(Ray ray, float distance, int layerMask)

   投射一条光线并返回所有碰撞,也就是投射光线并返回一个RaycastHit[]结构体。

 

好的,下面我们再回到我们的主题,鼠标或者触摸的输入判断,使用射线来检测鼠标的输入,首先我们需要给游戏添加Collider,但是注意这个必须是3D的Collider不能是2D的,然后我们给摄像机添加脚本。通常我们也需要给检测鼠标输入的游戏添加一个脚本组件用于表示区别不同的游戏对象,如添加一个ButtonId的脚本如下:



using UnityEngine;
using System.Collections;

public class ButtonId : MonoBehaviour
{
    //Ids and Strings are modified in the Inspector
    public string who;
    public string id;
    public int idLevel;
}



那么我们就可以通过这个ButtonId的属性信息来区别不同按钮。
    接下来我们添加摄像机的脚本如下所示:



using UnityEngine;
using System.Collections;

public class MenuManipulator : MonoBehaviour {
    public ButtonId buttonPressed;
    RaycastHit hit;
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            //获取摄像机到触摸点的位置的射线
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            // 射线是否有碰撞到物体 collider
            if (Physics.Raycast(ray, out hit))
            {
                //Menu
                // 有ButtonId组件,证明是按钮
                if (hit.collider.gameObject.GetComponent<ButtonId>())
                {
                    buttonPressed = hit.collider.gameObject.GetComponent<ButtonId>();
                    if (buttonPressed.id == "mywebsite")
                    {
                        Application.OpenURL("");
                    }

                }
            }
        }
    }
}



如果是针对手机移动设备的,还可以通过Input.GetTouch来进行处理,如



using UnityEngine;
using System.Collections;

public class MobileInput : MonoBehaviour 
{
    // Update is called once per frame
    void Update () 
    {
        #if UNITY_IPHONE || UNITY_ANDROID || UNITY_BLACKBERRY || UNITY_WP8    
        if(Input.touchCount>0)
        {
            for(int i =0; i<Input.touchCount; i++)
            {
                //Screen position of touch
                Vector2 TouchLocation = Input.GetTouch(0).position;
            
                //Get phase of touch
                TouchPhase TPhase = Input.GetTouch(0).phase;
                
                //Touch begins
                if(TPhase.Equals(TouchPhase.Began))
                {
                    //Click equivalent
                }
            }
        }
        #endif
    }
}



通过摄像机脚本,用射线进行处理,如:



using UnityEngine;
using System.Collections;

public class MobileMouseMap : MonoBehaviour 
{
    // Update is called once per frame
    void Update () 
    {
        #if UNITY_IPHONE || UNITY_ANDROID || UNITY_BLACKBERRY || UNITY_WP8
        if(Input.touchCount>0)
        {
            //Screen position of touch
            Vector2 TouchLocation = Input.GetTouch(0).position;
            
            //Get phase of touch
            TouchPhase TPhase = Input.GetTouch(0).phase;
                
            //Touch begins
            if(TPhase.Equals(TouchPhase.Began))
            {
                //Generate ray from main camera and mouse position
                Ray R = Camera.main.ScreenPointToRay(TouchLocation);
                RaycastHit HitInfo;
                
                //If intersection
                if(Physics.Raycast(R, out HitInfo))
                {
                    //Click equivalent - call mouse event
                    HitInfo.collider.gameObject.SendMessage("OnMouseDown");
                }
            }
        }
        #endif
    }
}