Unity【入门】小项目坦克大战


文章目录

1、开始场景

1、场景装饰

RotateObj

csharp 复制代码
using UnityEngine;

public class RotateObj : MonoBehaviour
{
    public float rotateSpeed = 15;
    void Update()
    {
        transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);
    }
}

2、开始界面

BasePanel

csharp 复制代码
using UnityEngine;

public class BasePanel<T> : MonoBehaviour where T:class
{
    //两个关键的静态成员
    //私有的静态成员变量(声明) 基础Mono不能new
    private static T instance;
    //公共的静态成员属性或方法(获取)
    //public static T Instance
    //{
    //    get
    //    {
    //        return instance;
    //    }
    //}
    public static T Instance => instance;
    //instance赋值,为确保挂载的唯一性,自己定义一个规范
    private void Awake()
    {
        instance = this as T;
    }
    public virtual void ShowMe()
    {
        this.gameObject.SetActive(true);
    }
    public virtual void HideMe()
    {
        this.gameObject.SetActive(false);
    }
}

BeginPanel

csharp 复制代码
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 通过类名快速得到脚本
/// </summary>
public class BeginPanel : BasePanel<BeginPanel>
{
    // 声明公共的成员变量来关联各个控件
    public CustomGUIButton btnBegin;
    public CustomGUIButton btnSetting;
    public CustomGUIButton btnQuit;
    public CustomGUIButton btnRank;
    void Start()
    {
        //锁定鼠标在窗口内
        //Cursor.lockState = CursorLockMode.Confined;
        //监听一次按钮点击过后的内容
        btnBegin.clickEvent += () => 
        {
            SceneManager.LoadScene("GameScene");
        };
        btnSetting.clickEvent += () =>
        {
            SettingPanel.Instance.ShowMe();
            HideMe();
        };
        btnQuit.clickEvent += () =>
        {
            Application.Quit();
        };
        btnRank.clickEvent += () =>
        {
            RankPanel.Instance.ShowMe();
            Instance.HideMe();
        };
    }
}

3、设置界面

GameDataMgr

csharp 复制代码
/// <summary>
/// 游戏数据管理类,是一个单例模式对象
/// </summary>
public class GameDataMgr
{
    private static GameDataMgr instance = new GameDataMgr();
    public static GameDataMgr Instance { get => instance; }
    //设置信息对象
    public MusicData musicData;
    //排行榜数据对象
    public RankList rankData;
    private GameDataMgr()
    {
        //初始化游戏数据
        musicData = PlayerPrefsDataMgr.Instance.LoadData(typeof(MusicData), "Music_Key") as MusicData;
        //第一次进入游戏的默认值
        if (!musicData.notFirst)
        {
            musicData.notFirst = true;
            musicData.isOpenBK = true;
            musicData.isOpenSound = true;
            musicData.bkValue = 1;
            musicData.soundValue = 1;
            PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music_Key");
        }

        //初始化读取排行榜数据
        rankData = PlayerPrefsDataMgr.Instance.LoadData(typeof(RankList),"Rank_key") as RankList;
    }

    //提供一个添加数据到排行榜中的方法
    public void AddRankInfo(string name,int score,float time)
    {
        rankData.list.Add(new RankInfo(name,score,time));
        //排序
        rankData.list.Sort((a, b) => a.time < b.time ? -1 : 1);
        //移除第10条之后的数据
        for (int i = rankData.list.Count-1; i >= 10; i--)
        {
            rankData.list.RemoveAt(i);
        }
        //存储
        PlayerPrefsDataMgr.Instance.SaveData(rankData, "Rank_key");
    }

    public void OpenOrCloseBKMusic(bool isOpen)
    {
        musicData.isOpenBK = isOpen; //改变是否开启状态
        //控制开关
        BKMusic.Instance.ChangeOpen(isOpen);
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music_Key"); //存储
    }
    public void OpenOrCloseSound(bool isOpen)
    {
        musicData.isOpenSound = isOpen; //改变
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music_Key"); //存储
    }
    public void ChangeBKValue(float value)
    {
        musicData.bkValue = value;
        BKMusic.Instance.ChangeValue(value);
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music_Key");
    }
    public void ChangeSoundValue(float value)
    {
        musicData.soundValue = value;
        PlayerPrefsDataMgr.Instance.SaveData(musicData, "Music_Key");
    }
}

SettingPanel

csharp 复制代码
using UnityEngine;
using UnityEngine.SceneManagement;

public class SettingPanel : BasePanel<SettingPanel>
{
    //声明成员变量 关联控件
    public CustomGUISlider sliderMusic;
    public CustomGUISlider sliderSound;

    public CustomGUIToggle togMusic;
    public CustomGUIToggle togSound;

    public CustomGUIButton btnClose;

    void Start()
    {
        //监听对应的事件,处理逻辑
        sliderMusic.changeValue += (value) => GameDataMgr.Instance.ChangeBKValue(value);
        sliderSound.changeValue += (value) => GameDataMgr.Instance.ChangeSoundValue(value);
        togMusic.changeValue += (value) => GameDataMgr.Instance.OpenOrCloseBKMusic(value);
        togSound.changeValue += (value) => GameDataMgr.Instance.OpenOrCloseSound(value);

        btnClose.clickEvent += () =>
        {
            HideMe();
            //判断当前所在场景
            if(SceneManager.GetActiveScene().name == "BeginScene")
                //把隐藏的开始界面重新显示
                BeginPanel.Instance.ShowMe();
        };
        HideMe();
        //this.gameObject.SetActive(false);
    }
    public void UpdatePanelInfo()
    {
        //更新设置信息
        MusicData data = GameDataMgr.Instance.musicData;
        sliderMusic.nowValue = data.bkValue;
        sliderSound.nowValue = data.soundValue;
        togMusic.isSel = data.isOpenBK;
        togSound.isSel = data.isOpenSound;
    }
    public override void ShowMe()
    {
        base.ShowMe();
        UpdatePanelInfo(); //更新设置信息
    }
    public override void HideMe()
    {
        base.HideMe();
        Time.timeScale = 1;
    }
}

4、音效数据逻辑

MusicData

csharp 复制代码
/// <summary>
/// 音效数据类,用于存储音乐设置相关的信息
/// </summary>
public class MusicData
{
    //背景音乐
    public bool isOpenBK;
    //音效
    public bool isOpenSound;

    public float bkValue;
    public float soundValue;

    public bool notFirst;
}

5、排行榜界面

RankPanel

csharp 复制代码
using System.Collections.Generic;

public class RankPanel : BasePanel<RankPanel>
{
    //关联public的控件对象
    public CustomGUIButton btnClose;

    private List<CustomGUILable> labRank = new List<CustomGUILable>();
    private List<CustomGUILable> labPlayer = new List<CustomGUILable>();
    private List<CustomGUILable> labScore = new List<CustomGUILable>();
    private List<CustomGUILable> labTime = new List<CustomGUILable>();
    void Start()
    {
        for (int i = 1; i <= 10; i++)
        {
            //通过路径/找到子对象的子对象
            //labRank.Add(transform.Find("labRank/labRank" + i).GetComponent<CustomGUILable>());
            labPlayer.Add(transform.Find("labPlayer/labPlayer" + i).GetComponent<CustomGUILable>());
            labScore.Add(transform.Find("labScore/labScore" + i).GetComponent<CustomGUILable>());
            labTime.Add(transform.Find("labTime/labTime" + i).GetComponent<CustomGUILable>());
        }
        //print("排名" + labRank.Count);
        print("玩家" + labPlayer.Count);
        print("分数" + labScore.Count);
        print("通关时间" + labTime.Count);

        //处理事件监听逻辑
        btnClose.clickEvent += () =>
        {
            HideMe();
            BeginPanel.Instance.ShowMe();
        };
        //GameDataMgr.Instance.AddRankInfo("测试", 100, 7232);
        HideMe();
    }
    public override void ShowMe()
    {
        base.ShowMe();
        UpdatePanelInfo();
    }
    public void UpdatePanelInfo()
    {
        //处理根据排行榜数据更新面板
        //获取GameDataMgr中的排行榜列表,用于更新
        List<RankInfo> list = GameDataMgr.Instance.rankData.list;
        //根据列表更新面板数据
        for (int i = 0; i < list.Count; i++)
        {
            labPlayer[i].content.text = list[i].name;
            labScore[i].content.text = list[i].score.ToString();

            int time = (int)list[i].time;
            labTime[i].content.text = "";

            if (time / 3600 > 0)
            {
                labTime[i].content.text += time / 3600 + "时";
            }
            if (time % 3600 / 60 > 0 || labTime[i].content.text != "")
            {
                labTime[i].content.text += time % 3600 / 60 + "分";
            }
            labTime[i].content.text += time % 60 + "秒";
        }
    }
}

6、排行榜数据逻辑

RankInfo

csharp 复制代码
using System.Collections.Generic;

/// <summary>
/// 排行榜单条数据
/// </summary>
public class RankInfo
{
    public string name;
    public int score;
    public float time;
    public RankInfo() { }
    public RankInfo(string name, int score, float time)
    {
        this.name = name;
        this.score = score;
        this.time = time;
    }
}
/// <summary>
/// 排行榜列表
/// </summary>
public class RankList
{
    public List<RankInfo> list;
}

7、背景音乐

BKMusic

csharp 复制代码
using UnityEngine;

public class BKMusic : MonoBehaviour
{
    private static BKMusic instance;
    public static BKMusic Instance => instance;
    public AudioSource audioSource;
    void Awake()
    {
        //初始化 赋值
        instance = this;
        //得到自己依附的游戏对象上挂载的音频源脚本
        audioSource = GetComponent<AudioSource>();
        //初始化已经设置好的信息
        ChangeValue(GameDataMgr.Instance.musicData.bkValue);
        ChangeOpen(GameDataMgr.Instance.musicData.isOpenBK);
    }
    /// <summary>
    /// 改变背景音乐大小
    /// </summary>
    /// <param name="value"></param>
    public void ChangeValue(float value)
    {
        audioSource.volume = value;
    }
    /// <summary>
    /// 开启背景音乐
    /// </summary>
    /// <param name="isOpen"></param>
    public void ChangeOpen(bool isOpen)
    {
        //关闭 mute(静音)
        audioSource.mute = !isOpen;
    }
}

2、游戏场景

1、游戏界面

GamePanel

csharp 复制代码
using UnityEngine;

public class GamePanel : BasePanel<GamePanel>
{
    //获取控件
    public CustomGUILable labScore;
    public CustomGUILable labTime;
    public CustomGUIButton btnQuit;
    public CustomGUIButton btnSetting;
    public CustomGUITexture texHP;
    public float hpW = 300;
    [HideInInspector]
    public int nowScore = 0; //分数记录
    [HideInInspector]
    public float nowTime = 0;
    private int time;

    void Start()
    {
        //锁定鼠标在窗口内
        Cursor.lockState = CursorLockMode.Confined;
        //监听界面上的一些控件操作
        btnQuit.clickEvent += () =>
        {
            QuitPanel.Instance.ShowMe();
            Time.timeScale = 0;
        };
        btnSetting.clickEvent += () =>
        {
            SettingPanel.Instance.ShowMe();
            Time.timeScale = 0;
        };

        //AddScore(100);
        //UpdataHP(300, 30);
    }

    void Update()
    {
        nowTime += Time.deltaTime;

        time = (int)nowTime;
        labTime.content.text = "";

        if (time / 3600 > 0)
        {
            labTime.content.text += time / 3600 + "时";
        }
        if (time % 3600 / 60 > 0 || labTime.content.text != "")
        {
            labTime.content.text += time % 3600 / 60 + "分";
        }
        labTime.content.text += time % 60 + "秒";
    }
    /// <summary>
    /// 更新得分的方法
    /// </summary>
    /// <param name="score"></param>
    public void AddScore(int score)
    {
        nowScore = score;
        //更新界面
        labScore.content.text = score.ToString();
    }
    /// <summary>
    /// 更新血条的方法
    /// </summary>
    /// <param name="maxHP"></param>
    /// <param name="HP"></param>
    public void UpdataHP(int maxHP,int HP)
    {
        texHP.guiPos.width = (float)HP/maxHP * hpW;
    }
}

2、基础场景搭建

CubeObj

csharp 复制代码
using UnityEngine;

public class CubeObj : MonoBehaviour
{
    //奖励预设体关联
    public GameObject[] rewardObjects;
    //死亡特效关联
    public GameObject deadEff;
    private void OnTriggerEnter(Collider other)
    {
        //50%几率创建奖励
        int rangeInt = Random.Range(0, 100);
        if(rangeInt < 70)
        {
            //根据箱子位置随机创建一个奖励预设体
            rangeInt = Random.Range(0,rewardObjects.Length);
            Instantiate(rewardObjects[rangeInt],transform.position,transform.rotation);
        }
        //创建特效预设体
        GameObject effObj = Instantiate(deadEff, transform.position, transform.rotation);
        //控制音效
        AudioSource audioS = effObj.GetComponent<AudioSource>();
        audioS.volume = GameDataMgr.Instance.musicData.soundValue;
        audioS.mute = !GameDataMgr.Instance.musicData.isOpenSound;
        Destroy(gameObject);
    }
}

QuitPanel

csharp 复制代码
using UnityEngine;
using UnityEngine.SceneManagement;

public class QuitPanel : BasePanel<QuitPanel>
{
    public CustomGUIButton btnQuit;
    public CustomGUIButton btnGoOn;
    public CustomGUIButton btnClose;
    void Start()
    {
        HideMe();

        btnQuit.clickEvent += () =>
        {
            SceneManager.LoadScene("BeginScene");
        };
        btnGoOn.clickEvent += () =>
        {
            HideMe();
        };
        btnClose.clickEvent += () =>
        {
            HideMe();
        };
    }
    public override void HideMe()
    {
        base.HideMe();
        Time.timeScale = 1.0f;
    }
}

奖励 PropReward

csharp 复制代码
using UnityEngine;
public enum E_PropType
{
    Atk, Def, MaxHp, Hp,
}
public class PropReward : MonoBehaviour
{
    public E_PropType type = E_PropType.Atk;
    public int changeVaule = 2;
    public GameObject getEff;
    private void OnTriggerEnter(Collider other)
    {
        //玩家才能获取属性奖励
        if (other.CompareTag("Player"))
        {
            //得到玩家脚本
            PlayerObj player = other.GetComponent<PlayerObj>();
            switch (type)
            {
                case E_PropType.Atk:
                    player.atk += changeVaule;
                    break;
                case E_PropType.Def:
                    player.def += changeVaule;
                    break;
                case E_PropType.MaxHp:
                    player.maxHp += changeVaule;
                    GamePanel.Instance.UpdataHP(player.maxHp, player.hp);
                    break;
                case E_PropType.Hp:
                    player.hp += changeVaule;
                    if (player.hp > player.maxHp)
                        player.hp = player.maxHp;
                    GamePanel.Instance.UpdataHP(player.maxHp, player.hp);
                    break;
            }
            //创建特效
            //获得武器的特效
            GameObject eff = Instantiate(getEff, transform.position, transform.rotation);
            AudioSource audioS = eff.GetComponent<AudioSource>();
            audioS.volume = GameDataMgr.Instance.musicData.soundValue;
            audioS.mute = !GameDataMgr.Instance.musicData.isOpenSound;
            Destroy(gameObject);
        }
    }
}

武器奖励 WeaponReward

csharp 复制代码
using UnityEngine;

public class WeaponReward : MonoBehaviour
{
    //随机武器
    public GameObject[] weaponObj;
    //武器特效
    public GameObject getEff;
    
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            //获取武器
            int index = Random.Range(0, weaponObj.Length);
            //得到PlayerObj脚本
            PlayerObj player = other.GetComponent<PlayerObj>();
            //切换武器
            player.ChangeWeapon(weaponObj[index]);

            //获得武器的特效
            GameObject eff = Instantiate(getEff, transform.position, transform.rotation);
            AudioSource audioS = eff.GetComponent<AudioSource>();
            audioS.volume = GameDataMgr.Instance.musicData.soundValue;
            audioS.mute = !GameDataMgr.Instance.musicData.isOpenSound;

            Destroy(gameObject);
        }
    }
}

3、坦克基类

TankBaseObj

csharp 复制代码
using UnityEngine;

public abstract class TankBaseObj : MonoBehaviour
{
    public int atk;
    public int def;
    public int maxHp;
    public int hp;

    public Transform tankHead;

    public float moveSpeed = 10;
    public float roundSpeed = 100;
    public float headRoundSpeed = 100;

    //死亡特效
    public GameObject deadEff;

    public abstract void Fire();
    public virtual void Wound(TankBaseObj other)
    {
        //伤害计算
        int dmg = other.atk - this.def;
        if (dmg <= 0)
            return;
        this.hp -= dmg;
        if (this.hp <= 0)
        {
            hp = 0;
            this.Dead();
        }
            
    }
    public virtual void Dead()
    {
        Destroy(gameObject);
        if (deadEff != null)
        {
            //实例化对象(特效)的位置和角度
            GameObject effObj = Instantiate(deadEff, transform.position, transform.rotation);
            //获取该对象的音频
            AudioSource audioSource = effObj.GetComponent<AudioSource>();
            audioSource.volume = GameDataMgr.Instance.musicData.soundValue;
            audioSource.mute = !GameDataMgr.Instance.musicData.isOpenSound;
            audioSource.Play();
        }
    }
}

特效销毁 AutoDestroy

csharp 复制代码
using UnityEngine;

public class AutoDestroy : MonoBehaviour
{
    public float time = 2;
    void Start()
    {
        Destroy(gameObject, time);
    }
}

子弹 BulletObj

csharp 复制代码
using UnityEngine;

public class BulletObj : MonoBehaviour
{
    //移动速度
    public float moveSpeed = 50;
    //子弹所有者
    public TankBaseObj fatherObj;
    //特效对象
    public GameObject effObj;

    void Update()
    {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
    }

    private void OnTriggerEnter(Collider other)
    {
        //子弹打到Cube
        if (other.CompareTag("Cube") ||
            //Monster发出的子弹打到玩家
            other.CompareTag("Player") && fatherObj.CompareTag("Monster") ||
            //Player发出的子弹打到Monster
            other.CompareTag("Monster") && fatherObj.CompareTag("Player"))
        {
            //伤害判断
            //通过里氏判断让父类获取脚本
            TankBaseObj obj = other.GetComponent<TankBaseObj>();
            if (obj != null)
                obj.Wound(fatherObj);

            //子弹爆炸特效
            if (effObj != null)
            {
                //创建爆炸特效
                GameObject eff = Instantiate(effObj, transform.position, transform.rotation);
                //修改音效的音量
                //获取音效对象
                AudioSource audioSource = eff.GetComponent<AudioSource>();
                audioSource.volume = GameDataMgr.Instance.musicData.soundValue;
                audioSource.mute = !GameDataMgr.Instance.musicData.isOpenSound;
                Destroy(gameObject);
            }
        }
    }
    //设置子弹所有者
    public void SetFather(TankBaseObj obj)
    {
        fatherObj = obj;
    }
}

武器 WeaponObj

csharp 复制代码
using UnityEngine;

public class WeaponObj : MonoBehaviour
{
    //实例化子弹对象
    public GameObject bullet;
    //发射位置
    public Transform[] shootPos;
    //武器的拥有者
    public TankBaseObj fatherObj;
    
    //设置子弹所有者
    public void SetFather(TankBaseObj obj)
    {
        fatherObj = obj;
    }
    public void Fire()
    {
        //根据位置创建子弹
        for (int i = 0; i < shootPos.Length; i++)
        {
            //创建子弹
            GameObject obj = Instantiate(bullet, shootPos[i].position, shootPos[i].rotation); ;
            //获取子弹所有者
            BulletObj bulletObj = obj.GetComponent<BulletObj>();
            bulletObj.SetFather(fatherObj);

            //补 刚体里的Constraints为轴向约束
        }
    }
}

4、主玩家相关

PlayerObj

csharp 复制代码
using UnityEngine;

public class PlayerObj : TankBaseObj
{
    //当前装备的武器
    public WeaponObj nowWeapon;
    //武器安装位置
    public Transform weaponPos;

    void Update()
    {
        //控制前进后退 1.Transform 位移 2.Input 轴向输入检测
        transform.Translate(Input.GetAxis("Vertical") * Vector3.forward * moveSpeed * Time.deltaTime);
        //控制旋转 1.Transform 旋转 2.Input 轴向输入检测
        transform.Rotate(Input.GetAxis("Horizontal") * Vector3.up * roundSpeed * Time.deltaTime);
        //鼠标左右移动 控制炮台旋转
        tankHead.transform.Rotate(Input.GetAxis("Mouse X") * Vector3.up * headRoundSpeed * Time.deltaTime);
        //开火
        if (Input.GetMouseButtonDown(0))
        {
            Fire();
        }
    }
    public override void Fire()
    {
        if (nowWeapon != null)
            nowWeapon.Fire();
    }
    public override void Dead()
    {
        //base.Dead();
        Time.timeScale = 0;
        LostPanel.Instance.ShowMe();
    }
    public override void Wound(TankBaseObj other)
    {
        base.Wound(other);
        //更新血条
        GamePanel.Instance.UpdataHP(maxHp, hp);
    }
    /// <summary>
    /// 切换武器
    /// </summary>
    /// <param name="obj">Weapon</param>
    public void ChangeWeapon(GameObject weapon)
    {
        if(nowWeapon != null)
        {
            Destroy(nowWeapon.gameObject);
            nowWeapon = null;
        }
        //实例化随机到的武器       将weaponPos设置为weapon的父对象,false保持缩放大小
        GameObject weaponObj = Instantiate(weapon, weaponPos, false);
        //挂载武器脚本
        nowWeapon = weaponObj.GetComponent<WeaponObj>();
        //设置武器拥有者为Player
        nowWeapon.SetFather(this);
    }
}

摄像机跟随 CameraMove

csharp 复制代码
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    //摄像机目标位置
    public Transform targetPlayer;
    public float H = 17;

    private Vector3 pos;

    void LateUpdate()
    {
        if (targetPlayer == null)
            return;
        //x/z和玩家一样
        pos.x = targetPlayer.position.x;
        pos.z = targetPlayer.position.z;
        //通过外部调整摄像机高度
        pos.y = H;
        transform.position = pos;
    }
}

5、敌人相关

MonsterObj

csharp 复制代码
using UnityEngine;

public class MonsterObj : TankBaseObj
{
    #region 变量
    //当前目标点
    private Transform targetPos;
    //随机用的点,外面关联
    public Transform[] randomPos;
    //敌方坦克盯着的目标
    public Transform lookAtTarget;
    //靠近一定范围自动开火
    public float fireDis = 5;
    //间隔时间
    public float fireOffsetTime = 2;
    private float nowTime = 0;

    //开火位置
    public Transform[] shootPos;
    //子弹预设体位置
    public GameObject bulletObj;
    //血条显示时间
    private float showTime;

    public Texture maxHpBK;
    public Texture hpBK;

    private Rect maxHpRect;
    private Rect hpRect;
    #endregion



    void Start()
    {
        RandomPos();

    }

    void Update()
    {
        //看向自己的目标点
        transform.LookAt(targetPos);
        //不停的往自己的面朝向移动
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
        //判断距离
        if (Vector3.Distance(transform.position, targetPos.position) < 0.1f)
        {
            RandomPos();
        }

        if (lookAtTarget != null)
        {
            tankHead.LookAt(lookAtTarget);
            if (Vector3.Distance(transform.position, lookAtTarget.position) <= fireDis)
            {
                nowTime += Time.deltaTime;
                if (nowTime >= fireOffsetTime)
                {
                    Fire();
                    nowTime = 0;
                }
            }
        }
    }
    private void RandomPos()
    {
        if (randomPos == null)
            return;
        targetPos = randomPos[Random.Range(0, randomPos.Length)];
    }
    public override void Fire()
    {
        for (int i = 0; i < shootPos.Length; i++)
        {
            GameObject obj = Instantiate(bulletObj, shootPos[i].position, shootPos[i].rotation);
            BulletObj bullet = obj.GetComponent<BulletObj>();
            bullet.SetFather(this);
        }
    }
    public override void Dead()
    {
        base.Dead();
        GamePanel.Instance.AddScore(10);
    }
    //血条UI
    private void OnGUI()
    {
        if (showTime > 0)
        {
            showTime -= Time.deltaTime;
            //血条位置:先把世界位置转换成屏幕位置,再转换成GUI位置
            Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position);
            //screenPos.y -= Screen.height;
            //screenPos.y =screenPos.y - Screen.height;

            screenPos.y = Screen.height - screenPos.y;
            //绘制GUI
            maxHpRect.x = screenPos.x - 50;
            maxHpRect.y = screenPos.y - 70;

            maxHpRect.width = 100;
            maxHpRect.height = 15;
            GUI.DrawTexture(maxHpRect, maxHpBK);

            hpRect.x = screenPos.x - 50;
            hpRect.y = screenPos.y - 70;

            hpRect.width = (float)hp / maxHp * 100f;
            hpRect.height = 15;
            GUI.DrawTexture(hpRect, hpBK);
        }
    }
    public override void Wound(TankBaseObj other)
    {
        base.Wound(other);
        showTime = 2;
    }
}

MonsterTower

csharp 复制代码
using UnityEngine;

public class MonsterTower : TankBaseObj
{
    //间隔开火
    //开火间隔时间
    public float fireOffsetTime = 1;
    private float nowtTime = 0;
    //子弹发射位置
    public Transform[] shootPos;
    //关联子弹预设体
    public GameObject bulletObj;

    void Update()
    {
        nowtTime += Time.deltaTime;
        if (nowtTime >= fireOffsetTime)
        {
            Fire();
            nowtTime = 0;
        }
    }
    public override void Fire()
    {
        for (int i = 0; i < shootPos.Length; i++)
        {
            //根据发射位置个数实例化子弹
            GameObject obj = Instantiate(bulletObj, shootPos[i].position, shootPos[i].rotation);
            //获取子弹脚本
            BulletObj bullet = obj.GetComponent<BulletObj>();
            //获取子弹所有者
            bullet.SetFather(this);
        }
    }
    public override void Wound(TankBaseObj other)
    {
        //base.Wound(other); 不用父类的Wound伤害计算方法
    }
}

6、通关点

EndPoint

csharp 复制代码
using UnityEngine;

public class EndPoint : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            //暂停游戏
            Time.timeScale = 0;
            //通过逻辑
            WinPanel.Instance.ShowMe();
        }
    }
}

3、结束界面

1、游戏胜利界面

WinPanel

csharp 复制代码
using UnityEngine;
using UnityEngine.SceneManagement;

public class WinPanel : BasePanel<WinPanel>
{
    public CustomGUIInput inputInfo;
    public CustomGUIButton btnSure;

    void Start()
    {
        //取消游戏暂停
        Time.timeScale = 1;
        //监听将数据记录到排行榜中
        btnSure.clickEvent += () =>
        {
            GameDataMgr.Instance.AddRankInfo(inputInfo.content.text, 
                GamePanel.Instance.nowScore, 
                GamePanel.Instance.nowTime);
            //返回开始界面
            SceneManager.LoadScene("BeginScene");
        };
        HideMe();
    }
}

2、游戏失败界面

LosePanel

csharp 复制代码
using UnityEngine;
using UnityEngine.SceneManagement;

public class LostPanel : BasePanel<LostPanel>
{
    public CustomGUIButton btnBack;
    public CustomGUIButton btnGoOn;
    void Start()
    {
        btnBack.clickEvent += () =>
        {
            Time.timeScale = 1;
            SceneManager.LoadScene("BeginScene");

        };
        btnGoOn.clickEvent += () =>
        {
            Time.timeScale = 1;
            SceneManager.LoadScene("GameScene");
        };
        HideMe();
    }
}

3、游戏打包

相关推荐
Murphy20232 小时前
.net4.0 调用API(form-data)上传文件及传参
开发语言·c#·api·httpwebrequest·form-data·uploadfile·multipart/form-
我曾经是个程序员2 小时前
C#Directory类文件夹基本操作大全
服务器·开发语言·c#
鸿喵小仙女3 小时前
C# WPF读写STM32/GD32单片机Flash数据
stm32·单片机·c#·wpf
一个不正经的林Sir3 小时前
C#WPF基础介绍/第一个WPF程序
开发语言·c#·wpf
码农君莫笑14 小时前
使用blazor开发信息管理系统的应用场景
数据库·信息可视化·c#·.net·visual studio
可喜~可乐16 小时前
C# WPF开发
microsoft·c#·wpf
666和77720 小时前
C#的单元测试
开发语言·单元测试·c#
小码编匠21 小时前
WPF 星空效果:创建逼真的宇宙背景
后端·c#·.net
超龄魔法少女1 天前
[Unity] ShaderGraph动态修改Keyword Enum,实现不同效果一键切换
unity·技术美术·shadergraph
蔗理苦1 天前
2024-12-24 NO1. XR Interaction ToolKit 环境配置
unity·quest3·xr toolkit