unity应用实例——从头撸一个全新的FPS游戏(5)

这篇文章进行对游戏ui逻辑的总结。

在上一篇机器人的控制脚本创建完成后,可以给机器人添加一个血条的效果,在机器人的游戏物体下创建一个画布,并添加一个slider,只保留其中的Fill Area,把其他的删掉,如图。

将Fill中的image修改为红色,然后给slider添加一个脚本,主要功能是让slider的value的值与血量占比相当

using UnityEngine;
using UnityEngine.UI;
public class follower : MonoBehaviour
{
    [SerializeField]
    private float m_offsety;
    public Transform m_robot;
    private float m_robotinithp;//机器人初始的hp

    private void Start()
    {
        m_robotinithp = m_robot.gameObject.GetComponent<RobotController>().M_hp;
    }
    private void Update()
    {
        //确定血条位置
        gameObject.transform.position = 
            new Vector3(m_robot.position.x, m_robot.position.y + m_offsety, m_robot.position.z);
        //根据实际情况扣血
        gameObject.GetComponent<Slider>().value=
            ((m_robot.gameObject.GetComponent<RobotController>().M_hp / m_robotinithp));
    }
}

然后对该画布的Canvas组件中的Render Mode进行如图设置:

创建一个新的相机,将它拖入Canvas组件中的Render Camera,在第三篇文章中的gamemanager类中拥有该相机的引用,名为m_secondcamera,并将其与主相机同步。这样子就相当与每个机器人都拥有一个与血量相当slider,并且它时刻面向玩家的视角,形成血条的效果。

血条设置好以后,创建多个scene存储关卡(关卡数+1个),把每个scene的地图自己div一下,将多个机器人放置其中并设置好巡逻点。然后开始进行ui脚本的创建。

首先是第一个scene也就是主菜单,创建一个名为UI的空物体,在它下面创建三个画布,再为每个画布添加各种功能对象,如图:

创建脚本进行管理,挂在ui上

using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class menuui : MonoBehaviour {

    public GameObject m_setcanvas;
    public GameObject m_Authorcanvas;
    public GameObject m_volumeslider;

    private void Start()
    {
        m_setcanvas.SetActive(false);
        m_Authorcanvas.SetActive(false);

        m_volumeslider.GetComponent<Slider>().value = datamanager.m_volume;
    }
    private void Update()
    {
        //音量调节
        datamanager.m_volume = m_volumeslider.GetComponent<Slider>().value;
    }

    //下面的方法全都挂在不同的Button上
    public void OnStart()
    {
        SceneManager.LoadScene(1);
    }
   public void OnExit()
    {
        Application.Quit();
    }

    public void OnSetOpen()
    {
        m_setcanvas.SetActive(true);
    }
    public void OnSetClose()
    {
        m_setcanvas.SetActive(false);
    }
    public void OnAuthorOpen()
    {
        m_Authorcanvas.SetActive(true);
    }
    public void OnAuthorClose()
    {
        m_Authorcanvas.SetActive(false);
    }
}

还创建一个空物体负责播放bgm,也挂一个脚本控制音量,在其他scene中也有这个物体

using UnityEngine;

public class bgm : MonoBehaviour {	

	void Update ()
    {
        gameObject.GetComponent<AudioSource>().volume = datamanager.m_volume;
    }
}

然后是开始游戏后的ui,之前在创建武器系统时做了一部分,现在补充完整

创建脚本对其进行管理

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

//游戏界面状态
enum PlayUiState
{
    BATTLE,
    END,
    SET
}

public class playui : MonoBehaviour
{

    private PlayUiState m_state;//当前界面状态

    private gun m_gun;
    private playerhp m_playerhp;
    private player m_player;
    private gamemanager m_manager;

    public GameObject m_hptext;//获取画布中的一个text
    public GameObject m_bulletText;//子弹数文本
    public GameObject m_snipertexture;//瞄准时加载的图片
    public GameObject m_aimtexture;
    public GameObject m_time;
    public GameObject m_endcanvas;
    public GameObject m_endtext;
    public GameObject m_playerstatetext;
    public GameObject m_hurtimage;
    public GameObject m_warningtext;
    public GameObject m_scoretext;
    public GameObject m_setcanvas;
    public GameObject m_bgm;
    public GameObject m_volumeslider;
    public GameObject m_mouseslider;

    private Color m_flashcolor; //记录受伤图片的色彩值
    public float m_flashspeed = 2;

    private float m_musictime = 0;//记录音乐播放位置
    private bool m_dead = false;
    private float m_finaltime = 0;

    void Start()
    {
        m_state = PlayUiState.BATTLE;

        m_player = FindObjectOfType<player>();
        m_playerhp = FindObjectOfType<playerhp>();
        m_manager = FindObjectOfType<gamemanager>();


        m_playerhp.diedelegate += OnDie;//添加委托事件

        
        m_volumeslider.GetComponent<Slider>().value = datamanager.m_volume;
        m_mouseslider.GetComponent<Slider>().value = datamanager.m_mosen;

        //记录当前设置好的受伤图片的颜色值
        m_flashcolor = m_hurtimage.GetComponent<Image>().color;
        //将受伤图片先设置为透明
        m_hurtimage.GetComponent<Image>().color = Color.clear;

        m_setcanvas.SetActive(false);
        m_endcanvas.SetActive(false);
        m_hurtimage.SetActive(true);
        m_playerstatetext.SetActive(false);
        m_warningtext.SetActive(false);

        //若是第一关 为玩家显示提示
        if (datamanager.M_gamelevel == 1)
        {
            StartCoroutine(FirstWarning());
        }

        Cursor.visible = false;//隐藏鼠标
    }

    void Update()
    {
        #region 战斗界面
        if (m_state == PlayUiState.BATTLE)
        {
            m_gun = FindObjectOfType<gun>();

            FreshHpText();
            FreshBulletText();
            ShowAimImage();
            ShowTheTime();

            //当玩家处于休息状态 显示提示
            if (playerstatemanager.m_state == PlayerState.RELAXE)
            {
                m_playerstatetext.GetComponent<Text>().text = "Relaxing...";
                m_playerstatetext.SetActive(true);
            }
            else m_playerstatetext.SetActive(false);

            //将受伤图片的颜色渐变为透明
            m_hurtimage.GetComponent<Image>().color =
                Color.Lerp
                (
                 m_hurtimage.GetComponent<Image>().color,
                 Color.clear,
                 m_flashspeed * Time.deltaTime
                );
            //设置鼠标灵敏度
            datamanager.m_mosen = m_mouseslider.GetComponent<Slider>().value;
            m_player.m_mouserate = datamanager.m_mosen * 5;
            //状态转换
            if (datamanager.M_gamelevel == datamanager.m_maxlevel || m_dead) m_state = PlayUiState.END;
            if (Input.GetKeyUp(KeyCode.Y)) m_state = PlayUiState.SET;

        }
        #endregion

        #region 结束界面
        if (m_state == PlayUiState.END)
        {
            Cursor.visible = true;//显示鼠标

            m_gun.enabled = false;

            m_player.enabled = false;

            m_endcanvas.SetActive(true);

            string score = "";

            if (datamanager.M_gamelevel == datamanager.m_maxlevel)//胜利
            {
                m_endtext.GetComponent<Text>().text = "Victory!";

                //记录游戏时间
                if (m_finaltime == 0)
                    m_finaltime = (int)datamanager.M_playtime;

                score =
                  "杀敌数:" + datamanager.M_gamescore +
                  "\n当前关卡:" + "final" +
                  "\n用时:" + m_finaltime + "s";
            }
            else if (m_dead)//死亡
            {
                m_endtext.GetComponent<Text>().text = "Game Over";

                m_playerhp.diedelegate -= OnDie;//释放委托事件
               
                //记录游戏时间
                if (m_finaltime == 0)
                    m_finaltime = (int)datamanager.M_playtime;

                score =
                    "杀敌数:" + datamanager.M_gamescore +
                    "\n当前关卡:" + datamanager.M_gamelevel +
                    "\n用时:" + m_finaltime + "s";
            }

            m_scoretext.GetComponent<Text>().text = score.ToString();
        }
        #endregion

        #region 设置界面
        if (m_state == PlayUiState.SET)
        {
            m_gun.enabled = false;
            //音乐暂停
            m_musictime = m_bgm.GetComponent<AudioSource>().time;
            m_bgm.GetComponent<AudioSource>().Pause();

            Cursor.visible = true;//显示鼠标

            Time.timeScale = 0;//时间暂停

            m_setcanvas.SetActive(true);
            //声音设置
            datamanager.m_volume = m_volumeslider.GetComponent<Slider>().value;
        }
        #endregion

    }


    void FreshHpText()
    {
        m_hptext.GetComponent<Text>().text = "HP:" + m_playerhp.M_hp.ToString();
    }

    void FreshBulletText()
    {

        m_bulletText.GetComponent<Text>().text = m_gun.Curbulletnum.ToString() + "/"
            + m_gun.Storebulletnum.ToString();
    }

    void ShowAimImage()
    {
        if (sniperscope.m_isaiming)
        {
            m_snipertexture.SetActive(true);
            m_aimtexture.SetActive(false);
        }
        else
        {
            m_snipertexture.SetActive(false);
            m_aimtexture.SetActive(true);
        }
    }

    void OnDie()
    {
        m_dead = true;
    }

    void ShowTheTime()
    {
        int time = (int)m_manager.M_WaitTime;
        if (time == 0)
            m_time.GetComponent<Text>().text = "The door is open!";
        else
            m_time.GetComponent<Text>().text = time.ToString();
    }

    public void HurtEffect()
    {
        m_hurtimage.GetComponent<Image>().color = m_flashcolor;
    }

    //下面两个方法是绑定在Button上的
    public void OnSetClose()
    {
        Cursor.visible = false;

        // 继续播放音乐
        m_bgm.GetComponent<AudioSource>().Play();
        m_bgm.GetComponent<AudioSource>().time = m_musictime;

        Time.timeScale = 1;//时间恢复正常

        m_setcanvas.SetActive(false);
        m_gun.enabled = true;
        
        m_state = PlayUiState.BATTLE;//转换状态

    }
    public void OnExit()
    {
        Application.Quit();
    }
    
    //显示警告,延迟消失
    IEnumerator FirstWarning()
    {
        m_warningtext.GetComponent<Text>().text = "Live and get out";
        m_warningtext.SetActive(true);

        yield return new WaitForSeconds(5f);

        m_warningtext.GetComponent<Text>().text = " ";
        m_warningtext.SetActive(false);
    }
}

因为每个关卡的ui都相同,可以设置为全局ui,在gamemanager中将名为ui的物体DontDestroyOnLoad了就行。

效果如下(结束界面):

ui写完后,这个小游戏就基本完成的差不多了,后面可能还会有些改进和补充,现在已经可以愉快的玩耍了,谢谢观看:)

猜你喜欢

转载自blog.csdn.net/qq_37553152/article/details/82749298