欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Unity3D的塔防游戏

程序员文章站 2022-03-29 14:40:41
...

课题主要内容

设计建议塔防游戏,实现规定敌人移动路线,在塔的基座的基础上升级塔、卖掉塔、更换塔,来射击敌人。
要求:1、基于c#编程语言实现;
2、发射子弹攻击敌人;
记录分数,判定游戏成功与否。

课题研究方案

基于Android平台进行开发,开发工具使用Unity3D 3.7 、 PhotoshopCS6、Visual Studio 2019。
游戏UI设计与制作主要用PhotoshopCS6,包括游戏场景的背景、个性化按钮、游戏信息的显示等贴图。
游戏的模型建立使用Unity3D 开发工具,包括地图制作、环境制作、粒子效果、模型的物理特性等。
游戏中最核心部分脚本代码的编写需要使用Visual Studio 2019编辑工具,代码的语言选用比较简单易操作的C#语言。将脚本指定给游戏模型,再将各种类型参数连接,完成游戏设计方案

功能要求

此为塔防游戏,即地图一端会自动产生敌人到另一端,在中间部位玩家可按照自己的思路放置炮塔来阻击敌人的前进,一旦炮塔的放置位置不对,或者所选择的炮塔攻击力不够的话,便阻止不了敌人的前进,那么敌人很容易就能逃脱,玩家便输了。所以这类策略游戏不仅可以使玩家娱乐,还能使玩家的智力得到很好地提升,为此,要求此游戏要给玩家尽量大的个人发挥空间。

游戏描述

1.敌人从地图的一端进入,经过某个特定的路径后最终达到目的地(通常是地图相反的一端)。
2.玩家沿着路径放置一些防御炮塔,在敌人经过时朝他们开火。敌人一波一波的过来,玩家需要不断放置更多的防御工事,同时升级这些炮塔。
3.要赢得游戏,玩家得挺过1分钟,并且得分大于等于200分。
4.本游戏设计只设置玩家得分和游戏时间,而不设置宝物。并且本游戏中的关卡不会在此体现出来,不同关卡知识地图不同,开始时系统排出的出兵方式不同,其他都一样。故只对一个关卡进行分析。

游戏场景

基于Unity3D的塔防游戏
基于Unity3D的塔防游戏
基于Unity3D的塔防游戏

GameController模块

public class GameController : MonoBehaviour
{
    public static bool GameIsOver;
    void Start()
    {
        GameIsOver = false;
    }
    void Update()
    {
        if (GameIsOver)
        {
            return;
        }
        if (Convert.ToInt16(Time.time) == 60)
        {
            if (Bullet.grade >= 200)
            {
                GameReturn();
            }
            else
            {
                GameEnd();
            }
        }
    }
    private void GameEnd()
    {
        GameIsOver = true;
        Global.GetInstance().GetEvent().Invoke(EventEnum.failureMenu, gameObject);
        Time.timeScale = 0;
    }
    private void GameReturn()
    {
        Global.GetInstance().GetEvent().Invoke(EventEnum.successMenu, gameObject);
        Time.timeScale = 0;
    }
}

Enemy模块

public class diren : MonoBehaviour
{
    public GameObject pathObject;
    public GameObject enemyPrefab;
    public GameObject enemy;
private float currentAddEnemyTime = 0.0f;
    public float addEnemyDutacion = 0.0f;
    private ObjectPool enemyPool = new ObjectPool();
    private List<GameObject> enemyList = new List<GameObject>();
    void Start()
    {
        for(int i = 0;i < 10;i++)
        {
            GameObject enemy = this.CreateEnemy();
            enemyPool.PushObject(enemy);
        }
        Global.GetInstance().SetEnemyController(gameObject);
    }
GameObject CreateEnemy()
    {
        GameObject enemy = Instantiate(enemyPrefab);
        enemy.transform.parent = this.transform;
        enemy.transform.GetComponent<dr>().SetObjectPool(enemyPool);
        return enemy;
    }
    public List<GameObject> GetEnemyList()
    {
        return enemyList;
    }
    void AddEnemy()
    {
        GameObject enemy = enemyPool.GetObject();
        if(enemy == null)
        {
            enemy = this.CreateEnemy();
        }
        enemy.SetActive(true);
enemy.transform.parent = transform;
        enemy.transform.position = pathObject.transform.GetChild(0).transform.position;
        enemy.transform.GetComponent<dr>().InitWithData(pathObject, gameObject);   
           this.enemyList.Add(enemy);
    }
    void Update()
    {
        if(this.currentAddEnemyTime >= addEnemyDutacion)
        {
            this.AddEnemy();
            this.currentAddEnemyTime = 0.0f;
        }
        else
        {
            this.currentAddEnemyTime += Time.deltaTime;
        }
    }
    public void EnemyEnd(GameObject enemy)
    {
        enemyList.Remove(enemy);
        Debug.Log("enemy list" + enemyList.Count);
    }
}

EnemyController模块

public class dr : MonoBehaviour
{
    private List<Vector3> pathList = new List<Vector3>();
    private int pathIndex = 0;
    private Vector3 targetPos = Vector3.zero;
    private ObjectPool enemyPool = null;
    private GameObject enemyController = null;
void Start()
    {
        
}
 public void SetObjectPool(ObjectPool pool)
    {
        enemyPool = pool;
}
    void Update()
    {
      if(pathList.Count!=0&&targetPos.Equals(Vector3.zero)&&pathIndex<pathList.Count)
        {
            targetPos = pathList[pathIndex];
        }
        if(!targetPos.Equals(Vector3.zero))
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPos, 0.08f);
        }
        
        float distance = Vector3.Distance(transform.position, targetPos);
        if(distance < 0.1f)
        {
            pathIndex ++;
            targetPos = Vector3.zero;
            if(pathIndex == pathList.Count)
            {
                this.enemyController.transform.GetComponent<diren>().EnemyEnd(gameObject);
                enemyPool.PushObject(gameObject);
            }
        }
    }
    public void InitWithData(GameObject path,GameObject ctl )
    {
        this.enemyController = ctl;
        for (int i = 0; i < path.transform.childCount; i++)
        {
            pathList.Add(path.transform.GetChild(i).transform.position);
        }
}
}

TowerBase模块

public class TowerBase : MonoBehaviour
{
    void Start()
    {}
    void Update()
    {}
    public void OnMouseDown()
    {
        Global.GetInstance().GetEvent().Invoke(EventEnum.BuildMenu, gameObject);
    }
}

Tower模块

public class Tower : MonoBehaviour
{
    public GameObject body;public float attackDistance;
    public float attackDuraction;public GameObject bulletPos;
    public GameObject bulletPrefab; private float currentAttackTime;
    private ObjectPool bulletPool = new ObjectPool();
    private Color currentColor;private int towerLevel = 0;
    private List<Color> levelColor = new List<Color>();
    private GameObject targetEnemy = null;
    GameObject enemyController = Global.GetInstance().GetEnemyController();
    void Start()
    {
        levelColor.Add(Color.blue);
        levelColor.Add(Color.red);
        levelColor.Add(Color.black);
        currentColor = body.transform.GetComponent<MeshRenderer>().material.color;
        for(int i = 0;i < 5;i ++)
        {
            GameObject obj = this.CreateBullet();
            bulletPool.PushObject(obj);
        }
    }
    GameObject CreateBullet()
    {
        GameObject bullet = Instantiate(bulletPrefab);
        bullet.transform.position = this.bulletPos.transform.position;
        bullet.transform.GetComponent<Bullet>().SetObjectPool(bulletPool);
        bullet.transform.parent = transform.parent;
        return bullet;
    }
    void AddBullet(GameObject target)
    {
        GameObject bullet = bulletPool.GetObject();
        if(bullet == null)
        {
            bullet = this.CreateBullet();
        }
        bullet.SetActive(true);
        bullet.transform.position = bulletPos.transform.position;
        bullet.transform.GetComponent<Bullet>().SetTarget(target);
    }
    void Update()
    {
        if (targetEnemy == null)
{  List<GameObject>enemyList=enemyController.transform.GetComponent<diren>().GetEnemyList();
            for(int i = 0;i < enemyList.Count;i ++)
            {
GameObject enemy = enemyList[i];
                Vector3 enemyPos = enemy.transform.position;
                Vector3 towerPos = transform.position;
                float dis = Vector3.Distance(enemyPos,towerPos);
                if(dis < attackDistance)
                {
                    this.targetEnemy = enemy;
                }
            }
        }
        else
        {
            if(this.currentAttackTime > this.attackDistance)
            {
                this.AddBullet(this.targetEnemy);
                this.currentAttackTime = 0.0f;
            }
            else
            {
                this.currentAttackTime += Time.deltaTime;
            }
            Vector3 towerV = new Vector3(0, 0, 1);
            Vector3 enemyV = this.targetEnemy.transform.position - transform.position;
            float angle = Vector3.SignedAngle(towerV, enemyV,Vector3.up);
            transform.rotation = Quaternion.AngleAxis(angle,Vector3.up);
Vector3 enemyPos = this.targetEnemy.transform.position;
            Vector3 towerPos = this.transform.position;
            float dis = Vector3.Distance(enemyPos, towerPos);
            if(dis > this.attackDistance)
            {
                this.targetEnemy = null;
            }
        }
    }
    public void OnMouseDown()
{        
Global.GetInstance().GetEvent().Invoke(EventEnum.ShowUpdateMenu, gameObject);
    }
    public void UpdateLevel()
    {
        if(towerLevel == 3)
        {
            return;
        }
            towerLevel++;
            this.body.transform.GetComponent<MeshRenderer>().material.color= levelColor[towerLevel - 1];
            currentColor = levelColor[towerLevel - 1];
    }
}

TowerController模块

public class TowerController : MonoBehaviour
{
    public List<GameObject> towerPrefabList;
    void Start()
    {
        Global.GetInstance().GetEvent().AddListener(ProcessEvent);
    }
    void ProcessEvent(EventEnum eventType, GameObject obj)
    {
        switch(eventType)
        {
            case EventEnum.BuildTower1:
                this.BuildTower(towerPrefabList[0],obj);
                break;
            case EventEnum.BuildTower2:
                this.BuildTower(towerPrefabList[1],obj);
 break;
            default:
                break;
        }
    }
    void BuildTower(GameObject obj,GameObject tb)
    {
        GameObject tower = Instantiate(obj);
        tower.transform.parent = transform;
        tower.transform.position = tb.transform.position;
    }
    void Update()
    {}
}

Bullet模块

public class Bullet : MonoBehaviour
{
public static int grade = 100;public int timer = 1; private static Bullet instance;
private ObjectPool bulletPool = null; private GameObject targetEnemy = null;
   public static Bullet getInstance
    {
        get
        {
            if (instance == null)
            {
                instance = new Bullet();
            }
            return instance;
        }
    }
    void Start()
    { }
    [System.Obsolete]
    void Update()
    {
        timer -= Convert.ToInt16(Time.deltaTime);
        if(timer <= 0)
        {
            timer = 1;
        }
        if(this.targetEnemy != null && this.targetEnemy.active == true)
        {
            Vector3 enemyPos = this.targetEnemy.transform.position;
            Vector3 bulletPos = transform.position;
            float dis = Vector3.Distance(enemyPos, bulletPos);
            transform.position = Vector3.MoveTowards(bulletPos,enemyPos,0.1f);
            if(dis < 0.5)
            {
                bulletPool.PushObject(gameObject);
                this.targetEnemy = null;
                grade = grade + 10;
            }
        }
    }
    public void SetObjectPool(ObjectPool pool)
    {
        bulletPool = pool;
    }
    public void SetTarget(GameObject target)
    {
        this.targetEnemy = target;
    }
}

UIController 模块

public class UIController : MonoBehaviour
{
    public GameObject buileMenu;public GameObject updateMenu;
    public GameObject successMenu;public GameObject failureMenu;
    public GameObject targetObject;public GameObject textback;
    void Start()
    {
        Global.GetInstance().GetEvent().AddListener(ProcessEvent);
    }
    void ProcessEvent(EventEnum eventType, GameObject obj)
    {
        this.targetObject = obj;
        switch(eventType)
        {
            case EventEnum.BuildMenu:
                this.ShowBuileMenu(obj);
                break;
            case EventEnum.ShowUpdateMenu:
                this.ShowUpdateMenu(obj);
                break;
            case EventEnum.successMenu:
                this.ShowsuccessMenu(obj);
                break;
            case EventEnum.failureMenu:
                this.ShowfailureMenu(obj);
                break;
            default:
                break;
        }
 }
    void ShowUpdateMenu(GameObject obj)
    {
        this.buileMenu.SetActive(false);this.updateMenu.SetActive(true);
        this.updateMenu.transform.position= Camera.main.WorldToScreenPoint(obj.transform.position);
    }
    void ShowBuileMenu(GameObject obj)
    {
        this.updateMenu.SetActive(false); this.buileMenu.SetActive(true);
        this.buileMenu.transform.position= Camera.main.WorldToScreenPoint(obj.transform.position);
    }

    void ShowsuccessMenu(GameObject obj)
    {
        this.successMenu.SetActive(true);
    }
    void ShowfailureMenu(GameObject obj)
    {
        this.failureMenu.SetActive(true);
    }
    public void OnButtonClick(string data)
    {
        Debug.Log("button click ="+data);
        switch(data)
        {
            case "build-tower-1":
                if (Bullet.grade >= 100)
                {
                    Global.GetInstance().GetEvent().Invoke(EventEnum.BuildTower1, this.targetObject);
                    this.buileMenu.SetActive(false);
                    Bullet.grade = Bullet.grade - 100;
                }
                else
                {
                    this.buileMenu.SetActive(false);
                }
                break;
            case "build-tower-2":
                if (Bullet.grade >= 100)
                {
                    Global.GetInstance().GetEvent().Invoke(EventEnum.BuildTower2, this.targetObject);
                    this.buileMenu.SetActive(false);
                    Bullet.grade = Bullet.grade - 100;
                }
                else
                {
                     this.buileMenu.SetActive(false);
                }
                break;
            case "update":
                if (Bullet.grade >= 100)
                {
                   this.targetObject.transform.GetComponent<Tower>().UpdateLevel();
                    this.updateMenu.SetActive(false);
                    Bullet.grade = Bullet.grade - 100;
                }
                else
                {
                    this.buileMenu.SetActive(false);
                }
                break;
            case "sell":
                Destroy(this.targetObject);
                this.updateMenu.SetActive(false);
                Bullet.grade = Bullet.grade + 50;
                break;
            default:
                break;
        }
}
}

CM 模块

public class CM : MonoBehaviour
{
    public AudioClip music;public AudioSource back;
    public float moveSpeed = 200f;private int t = 0;
    void Start()
    {
        back = this.GetComponent<AudioSource>();
        back.loop = true; //设置循环播放  
        back.volume = 0.5f;//设置音量最大,区间在0-1之间
        back.clip = music;
        back.Play(); //播放背景音乐
     }
void Update()
    {
        float x = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
        float z = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
        transform.Translate(x, 0, z);
 }
    public void OnButtonClick(string data)
    {
        switch (data)
        {
            case "musicbutton":
                ++t;
                if(t % 2 == 1)
                {
                    back.Stop();
                }
                else
                    back.Play();
                break; 
             default:
                break;
        }
    }
}

TextShow 模块

public class TextShow : MonoBehaviour
{
public float timer = 1.0f;
 void Start()
    { }
    void Update()
    {
        timer -= Time.deltaTime;
        GameObject.Find("Canvas/time").GetComponent<Text>().text = "时间:" + Convert.ToInt16(Time.time);
        GameObject.Find("Canvas/grade").GetComponent<Text>().text = "分数:" + Bullet.grade;
    }
}

最后有需要的朋友可以下载看看:基于Unity3D的塔防游戏

相关标签: 实训