unity实现丧尸围城项目(第一天)

794 阅读6分钟

1.导入资料包

image.png

2.新建面板

在当前场景下,新建面板,新建面板后自动创建好Canvas,并且面板是包含Canvas里面,

设置Canvas的UI缩放模式为屏幕大小缩放,分辨率改为1920*1080,并且在游戏界面也将展示模式改为16:9,

image.png

取消勾选面板的image组件,如果不取消勾选的话,里面会包含一个白色底的图片,会影响我们的效果,相对于在这里我们只需要将面板作为一个大容器即可 image.png

配置Panle面板参数,重命名为BeginPanle,取消勾选image的组件(如果不取消勾选,会存在有地图效果,这是我们不需要的,我们只需要一个空的容器即可)。

新建图像Image,更改好图像的颜色,适当的调好浓度,更改好图像的位置,存放在左上,这里的调位置是有规矩的,我们要同时按住ALT+SHIFT键选择需要调整的位置,因为只有这样调整好我们才能在不同分辨率下的基本布局才不会乱,如果你单个移动的,虽然说在这个分辨率下是正常的,但是你在其他分辨率下就会显得很乱。--所以我们调整好位置后一般都会不断的调整显示的模式来查看是否调整好。

调整图片好后,新建文字,字体更改为场景中子自带的,对齐改为居垂直对齐、右对齐

新建三个按钮,分别命名为btnStart、btnSetting、btnStop,调整好对应的样式配置即可

总体配置如下:

image.png

3.预制体

在BeginPanle面板中挂载一个BeginPanle脚本文件,注意:这里的预制体名称和脚本名称要保持一致,方便我们以后在脚本文件中使用它,并将事先创建好的三个按钮当做变量拖入到在脚本文件公开的三种按钮类型当中,获取三个按钮,我们可以在代码中监听到对应按钮的点击事件,实现不同的业务

     //关联三个按钮
    public Button btnStart;
    public Button btnSetting;
    public Button btnStop;

完整的BeginPanle代码如下:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BeginPanle : basePanle
{
    //关联三个按钮
    public Button btnStart;
    public Button btnSetting;
    public Button btnStop;
    public override void Init()
    {
        //点击开始按钮,监听事件
        btnStart.onClick.AddListener(() =>
        {
            //显示开始页面,关闭当前页面

        });
        btnSetting.onClick.AddListener(() =>
        {
            //显示设置页面
            Debug.Log("设置");
        });
        btnStop.onClick.AddListener(() =>
        {
            //游戏退出
            Application.Quit(); //只会在发布完之后到设备上才会生效
        });
    }
}

image.png

将新建好的BeginPanle拖入到建好的Resources/UI文件夹里面,然后在将Canvas拖入到Resources/UI文件夹中,拖入之后可以删除建立好的物体,将它们作为预制体

image.png

BeginPanle继承父类basePanle,所以basePanle代码如下:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public abstract class basePanle : MonoBehaviour //基类
{
    //创建一个委托 untiy内置了一个委托
    private UnityAction callback = null;
    //首先每个继承basePanle的物体是不是都要添加一个透明度CanvasGroup组件
    private CanvasGroup canvasGroup;
    //速度:淡入淡出的速度
    float alphaSpeed = 10f;
    //创建一个布尔值来记录当前的状态
    bool isShow = false;
    //当对象被唤醒的时候,是不是要添加canvasGroup组件
    //游戏对象被激活,自动帮我们调用Awake方法---添加组件
    protected virtual void Awake() //可以被继承,所以权限要确保子类(派生类)能够被访问;virtual派生类惊进行重写要用虚函数
    {
        //如果组件不存在,则需要添加一个组件
        if (canvasGroup == null)
        {
            this.gameObject.AddComponent<CanvasGroup>();

        }
        //获取当前的canvasGroup组件  this指代当前的对象
        canvasGroup = this.gameObject.GetComponent<CanvasGroup>();
    }
    protected virtual void Start()
    {
        Init();
    }

    //抽象方法  提示我们必须要实现这个方法  讲ui的时候可能 需要初始化一些参数,把它写到一个方法里面
    public abstract void Init();

    //实现淡出的方法,修饰符公开.透明度从0开始变化,最后变成1

    public void showMe()
    {
        canvasGroup.alpha = 0;
        isShow = true;
    }
    //实现淡入的方法 返回挂载的脚本
    //callback 可以方便的调用另一个脚本的方法
    public void hideMe(UnityAction call) //隐藏完我们一般销毁游戏对象 在调用的地方传入一个回调函数,在这里面进行执行
    {
        
        canvasGroup.alpha = 1;
        isShow = false;
        //移除游戏对象
        //if (callback != null) callback.Invoke(); //调用传进来的委托函数
        if (call != null) callback = call; //调用传进来的委托函数
    }

    private void Update()
    {
        //判断当前的显示状态
        if (isShow && canvasGroup.alpha <1)
        {
            //显示:透明度0-》1  一定要加上Time.deltaTime,否则一下子会超过1
            canvasGroup.alpha += alphaSpeed * Time.deltaTime;
            if (canvasGroup.alpha >= 1)
            {
                canvasGroup.alpha = 1;
            }
        }else if (!isShow &&canvasGroup.alpha>0)
        {
            //淡出效果 透明度1-》0
            canvasGroup.alpha -= alphaSpeed * Time.deltaTime;
            if (canvasGroup.alpha <= 0)
            {
                canvasGroup.alpha = 0;
                if(callback!=null) callback.Invoke();
            }
        }
    }


}

UIMangaer代码如下:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager
{
    public enum ani //这个必须是公开的,因为下面使用它的方法是公开的
    {
        fade,//淡入淡出
        none //表示没有动画
    }
    //创建一个变量来存动画的类型,选择的是淡入淡出的效果
    ani animationType = ani.fade;
    private Transform canvasTrans;
    //只实例化一次 静态成员变量返回该实例对象
    public static UIManager Instance = new UIManager();

    //创建一个字典来存储 string代表面板,basePanle代表脚本类,因为所有的派生类都可以使用基类basePanle表示
    private Dictionary<string,basePanle> palneDic = new Dictionary<string,basePanle>();
    //将每个面板拆分成一个个预制件,需要的时候使用,不需要的时候不显示

    //因为一旦canvas显示了说明ui管理器开始运作了,可以在构造方法里面进行初始化canvas
    //创建一个构造方法
    private UIManager()
    {
        //使用克隆一个canvas  注意的是这里要使用GameObject.的方式,因为这里没有继承MonoBehaviour
        GameObject canvas = GameObject.Instantiate(Resources.Load<GameObject>("UI/Canvas"));
        //面板应该是canvas的孩子:面板.transform.parent = canvas.transform
        canvasTrans = canvas.transform;
        //当我场景切换的时候可能界面还是保存的,也就说不能直接销毁
        GameObject.DontDestroyOnLoad(canvas); //跳转场景的时候不销毁canvas
    }
    //显示的方法:设计思想:我们等一下每一个预制体挂载到一个面板脚本上,
    //这个面板脚本的积累就是basePanle,等一下面板名我们直接使用类名就好了
    //注意:预制件的名字最好和脚本文件的名字一样
    public T showpanle<T>() where T : basePanle //限制面板必须是继承basePanle
    {
        //通过泛型的名字来控制是否显示 那这里就要获取泛型的名字
        string pathName = typeof(T).Name; //获取泛型对应的名字
        //创建一个面板,确定是否在字典中
        if (palneDic.ContainsKey(pathName))
        {
            //如果有说明已经显示了,就直接返回
            return palneDic[pathName] as T; //需要的是T类型,但是字典里面存储的是basePanle类型,这时候需要使用语法糖转化成T类型
        }
        //如果没有显示过 那么需要创建一个对象来作为canvas的孩子,同时往字典添加键值对,字典中存储的都是当前系那是的面板
        GameObject panel = GameObject.Instantiate(Resources.Load<GameObject>("UI/"+pathName));
        //将当前的面板加入字典,成为其中的一员
        //panel.transform.parent = canvasTrans;
        panel.transform.SetParent(canvasTrans, false); //false表示相对于父元素
        //添加字典当中
        palneDic.Add(pathName, panel.GetComponent<T>());
        //调用淡入方法
        panel.GetComponent<T>().showMe(); //T代表的就是它挂载的脚本

        return panel.GetComponent<T>();
    }
    //隐藏面板
    //如果不传入参数,我会使用默认参数fade,如果传入参数的话,我们就会覆盖,如果是传入none的话,我们就什么都不要
    public void hidePanle<T>(ani type =ani.fade)where T:basePanle
    {
        string panleName = typeof(T).Name;
        //判断他有没有这个面板
        if (palneDic.ContainsKey(panleName))
        {
            //移除对象,从字典中删除
            T panle = palneDic[panleName] as T; //转化为T类型,拿到对象上的脚本
            switch (type)
            {
                case ani.fade: //表示的是淡入淡出的效果
                    //采用匿名函数来实现
                    panle.hideMe(() =>    //(参数) =>{函数体}
                    {
                        //删除对象,从字典中移除
                        GameObject.Destroy(panle.gameObject);
                        palneDic.Remove(panleName);
                    });
                    break;
                case ani.none://ani.none表示都没有动画
                    GameObject.Destroy(panle.gameObject);
                    palneDic.Remove(panleName);
                    break;
            }
        }
    }

    //获取面板
    public T getPanle<T>()where T :basePanle
    {
        string panleName = typeof(T).Name;
        if (palneDic.ContainsKey(panleName))
        {
            return palneDic[panleName] as T;
        }
        return null;
    }
}

同时新建Main.cs脚本文件,将脚本文件挂载到新建好的空对象Mian中,可以作为我们的启动项,当我们运行项目的时候,会运行到Main对象挂载好的Main脚本文件,通过Main脚本文件

    UIManager.Instance.showpanle<BeginPanle>();

来访问UImanager当中实现的淡出效果

Main.cs脚本文件:

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Main : MonoBehaviour
{
    void Start()
    {
        /*UIManager.Instance.showpanle<LoginPanle>();
        StartCoroutine(del()); //使用协程实现淡出效果*/
        UIManager.Instance.showpanle<BeginPanle>();
    }

    // Update is called once per frame
    void Update()
    {

    }

}

4.最终效果如下:

封面.gif