Unity3D学习(13)之UI界面与背包系统

来源:互联网 发布:淘宝音乐 编辑:程序博客网 时间:2024/05/19 17:58

       之前傻傻地认为Unity3D的UI只是在OnGUI的时候画画Button,Image用的,根本没想过UI的效果竟然可以这么棒。废话不多说先上个效果图。

                                    

是不是看起来特别帅,感觉一个好的UI界面是一个游戏成功的一半啊。

首先建立一个Canvas,并且在Canvas里面建立五个Panel分别命名为Window(主界面),HeadBag(次级界面1),HandBag(次级界面2),FootBag(次级界面3),Equip(装备界面)。并且将层次设置为UI界面,用UIcamera来渲染。

然后在Window界面建立一个Panel命名为Title,和三个Button分别命名为Head,Hand,Foot指向三个次级界面。为了让button,panel更好看我们可以加个图片控制UI显示的形状,比如Title用了SFtitle这张贴图。


为了让panel有动画,我录制了进来(window)和退出(Exit)的动画。设置Bool参数Open控制状态变换

接着制作HeadBag,HandBag,FootBag次级菜单,添加Grid Layout Group组件,用于布局。然后在菜单里面添加10个按钮,1个退出菜单,9个装备菜单。利用Button的text写下背包名称,在image组件添加图片,即为所储存的装备。

同理复制粘贴搞定另外两个,同时录制好进出的动画。然后考虑菜单随鼠标摆动。编写TiltWindow.cs

public class TiltWindow : MonoBehaviour{    public Vector2 range = new Vector2(5f, 3f);//旋转范围    Transform mTrans;    Quaternion mStart;    Vector2 mRot = Vector2.zero;    void Start()    {        mTrans = transform;        mStart = mTrans.localRotation;    }    void Update()    {        Vector3 pos = Input.mousePosition;//获取鼠标位置        float halfWidth = Screen.width * 0.5f;        float halfHeight = Screen.height * 0.5f;        float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f);//求相对x比例,并且限制上下界        float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);//求相对y比例,并且限制上下界        mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f);//求插值        mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, mRot.x * range.x, 0f);//进行旋转    }}

这时第一个Bug出现了,动画机的问题,当物体处在动画状态时,会阻塞在动画那里,使得脚本失去效果,所以我们需要让动画播放完毕之后使animator失效。顺便写一写菜单切换,可以在场景建立空对象命名为MenuManger,拥有脚本MeneManger.cs控制菜单的切换。切换菜单有两个动作,一个是关闭旧的菜单,一个是开启新的菜单,关闭首先要激活旧菜单的animator,播放退出动画,然后灭活菜单,这里我使用协程,一秒钟之后灭活,开启也要激活animator,播放进入动画,然后使动画机失效,TiltWindow脚本才能有效。

然后为了让图片跟随鼠标移动,设置UIImage,有图片时改为不透明色,没有图片时改为透明色,编写UIimage.cs,UIimage属性具体设置如下:

public class UIimage : MonoBehaviour {    private Image mouse_Image;//鼠标点击的图片    public Color visable;//可见色    public Color unvisable;//不可见色// Use this for initializationvoid Start () {        mouse_Image = GetComponent<Image>();}// Update is called once per framevoid Update () {if(MenuManger.texture != null)//判断如果鼠标点击图片非空,则将UIimage设置为可见,并且将鼠标图片赋值给UIimage,同时随时更新UIimage位置        {            mouse_Image.color = visable;            mouse_Image.sprite = MenuManger.texture;            this.transform.position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);        }        else //否则不可见        {            mouse_Image.color = unvisable;        }}}

然后还需要考虑图片类型,比如头部装备不能放在手部装备处。编写Bag.cs记录类型编号
public class Bag : MonoBehaviour {    public int type;}
HeadBag类型为0,HandBag为1,FootBag为2。同时Equip板也用Grid组件建立三个按钮,挂上Bag.cs也分别设置为0,1,2。
然后考虑鼠标图片与HeadBag,HandBag,FootBag的Button贴图切换。用GetTexture传入本身对象,与鼠标的图片交换即可,需要判断条件只有类型相同才可以交换,或者鼠标没有图片时。还有鼠标图片与Equip的Button贴图,条件是类型相同或者Button有图片但是鼠标没有图片。
编写MenuManager的脚本,控制MenuManager切换,鼠标

public class MenuManger : MonoBehaviour {    private GameObject Current;//当前菜单    private GameObject Previous;//旧菜单    public GameObject Window;//在属性面板拖入相应菜单    public GameObject HeadBag;//    public GameObject HandBag;//    public GameObject FootBag;//    public static Sprite texture;//鼠标获取的图片    public static int type = -1;//鼠标获得图片类型,-1表示无图片// Use this for initializationvoid Start () {        texture = null;        Current = Window;        Previous = Window;        StartCoroutine(OpenDelay());//关闭动画    }    public void getTexture(GameObject obj)    {        if(type == -1 || type == obj.GetComponent<Bag>().type)        {            Sprite previous = texture;//保存鼠标先前的图片            texture = obj.GetComponent<Image>().sprite;//            obj.GetComponent<Image>().sprite = previous;//交换图片            type = obj.GetComponent<Bag>().type;//保存类型        }        if(texture == null)        {            type = -1;//如果为空置-1        }    }    public void putTexture(GameObject obj)    {        if ((type == -1 && obj.GetComponent<Image>().sprite != null)  ||type == obj.GetComponent<Bag>().type)        {            Sprite previous = texture;//保存鼠标先前图片            texture = obj.GetComponent<Image>().sprite;//            obj.GetComponent<Image>().sprite = previous;//交换图片            type = obj.GetComponent<Bag>().type;//保存类型        }        if (texture == null)        {            type = -1;        }    }    public IEnumerator OpenDelay()    {        int CoolTimes = 1;//延迟1秒        while (CoolTimes > 0)        {            print("还剩" + CoolTimes);            yield return new WaitForSeconds(1);//等待1秒            CoolTimes--;        }        Current.GetComponent<Animator>().enabled = false;//灭活动画    }    public IEnumerator CloseDelay()    {        int CoolTimes = 1;//延迟1秒        Previous.GetComponent<Animator>().enabled = true;//激活动画        Previous.GetComponent<Animator>().SetBool("Open", false);//播放关闭动画        while (CoolTimes > 0)        {            print("还剩" + CoolTimes);            yield return new WaitForSeconds(1);//等待1秒            CoolTimes--;        }        Previous.SetActive(false);//灭活旧菜单        OpenPanel();//打开新菜单    }    void OpenPanel()    {        Current.SetActive(true);//激活菜单        Previous.GetComponent<Animator>().enabled = true;//激活动画        Current.GetComponent<Animator>().SetBool("Open", true);//播放开启动画        StartCoroutine(OpenDelay());//开启延迟    }    public void OpenPanel(GameObject panel)//打开菜单    {        Previous = Current;//保存旧菜单对象        Current = panel;//保存新菜单对象        StartCoroutine(CloseDelay());//协程关闭菜单    }}

在BUutton的Onclick函数调用相应函数,具体设置如下


然后用UIcamera负责渲染UI层,main camera渲染背景,用canvas加panel贴背景图,再放个粒子系统。设置如下


这就大功告成了,其实真正做应该是花了一天时间但是看博客,学课堂案例的代码学了挺久,一直以为很难,但其实只有真正动手才能知道难在哪里。再次吐槽我的电脑,明明下了Unity Web Player但是就是看不了demo,什么方法都试过了,我也无话可说,同样的操作同学的电脑却可以成功,而我只能凭着想象力把游戏做出来。微笑微笑微笑

有兴趣看我的工程可以去我的Gihub上看Demo.


0 0
原创粉丝点击