首页 > 代码库 > 使用3D物体做GUI界面

使用3D物体做GUI界面

通常来说,Unity自带的OnGUI不太好用,靠代码完成,在场景中无法直接编辑。所以,一般项目使用NGUI插件来做界面,但我这次要修改一个游戏,它没用NGUI,也没用OnGUI,而是使用类似NGUI的原理,采用Plane这种3D物体来做界面。

其实很简单,比如你需要一个按钮,就创建一个Plane,然后用对应的图片创建一个材质,给它贴上去就行了。这样只是显示了一张图片,要实现点击效果,还要在Update函数中捕获用户输入。我这里检测到输入时,先使用ScreenToWorldPoint函数来转换输入,然后使用了Raycast射线检测方法,给碰撞到的物体发ButtonDown消息。对应的,还要发送其它需要的消息。

 1     void Update () 
 2     {
 3         if(Input.GetMouseButtonDown(0)) 
 4         {
 5             RaycastHit hit;
 6             Vector2 t_pos = Input.mousePosition;
 7             t_pos = camera2d.ScreenToWorldPoint(t_pos);
 8             if(Physics.Raycast(t_pos, Vector3.forward, out hit) && hit.collider.tag == "Button")
 9             {
10                 PlaySoundOneShot(ds_pressbutton);
11                 holding_button = hit.collider.gameObject;
12                 holding_button.SendMessage("ButtonDown");
13             }
14         }
15         else if (Input.GetMouseButtonUp(0))
16         {
17             RaycastHit hit;
18             Vector2 t_pos = Input.mousePosition;
19             t_pos = camera2d.ScreenToWorldPoint(t_pos);
20             if (Physics.Raycast(t_pos, Vector3.forward, out hit))
21             {
22                 if (hit.collider.gameObject == holding_button)
23                 {
24                     holding_button.SendMessage("ButtonUp");
25                 }
26             }
27 
28             if (holding_button)
29             {
30                 holding_button.SendMessage("ButtonReset");
31                 holding_button = null;
32             }
33         }
34     }

下面是按钮上挂的代码

    public Texture2D tex_pressed_button;
    public Texture2D tex_released_button;

    private float delay_time;

    // Use this for initialization
    void Start () 
    {
        delay_time = 0;
    }
    
    // Update is called once per frame
    void Update ()
    {
        if (delay_time > 0)
        {
            delay_time -= Time.deltaTime;
            if (delay_time <= 0)
            {
                ButtonActive();
            }
        }
    }

    public void ButtonDown()
    {
        renderer.material.mainTexture = tex_pressed_button;
    }
    
    public void ButtonUp ()
    {        
        delay_time = 0.2f;
    }

    public void ButtonReset()
    {
        renderer.material.mainTexture = tex_released_button;
    }

    public void ButtonActive()
    {

    }

这样做后,基本可以实现普通的按钮、图片显示等,但还是没有NGUI好用。如果你要程序文字,不要使用GUI Text 和 GUI Texture,它们都是靠OnGUI来实现的,所以会始终置于顶层,即便你使用两个Camera来隐藏其中一个,也不能实现覆盖遮挡效果。但可以使用3D Text,把scale调小,font size调大可以使文字清晰。那怎么实现血条了?一种可行的方法是,还是用Plane,同时添加脚本,根据数值变化来调整plane宽度,然后移动plane到合适的位置。不过这个方法太麻烦了,对于血条这种,仍然可以使用3D Text来实现,只需要改变材质、调整anchor和aligment,在Text中输入文字即可,这里用‘w‘比较好。