Unity3D开发塔防游戏案例个人总结

什么是塔防游戏?

  • 塔防游戏(Tower Defense game,简称TD),即指一类通过在地图上建造炮塔或类似建筑物,以阻止游戏中敌人进攻的策略型游戏.
    像这样
  • 比如:植物大战僵尸 保卫萝卜 防御觉醒等

Unity3d开发塔防游戏的步骤

  • 创建游戏地图 ,使用Cube代替炮塔可放置的位置
  • MapCube.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class MapCube : MonoBehaviour
{
    //保存当前cube身上的炮台
    [HideInInspector]
    public GameObject turretGo;
    //炮台数据
    [HideInInspector]
    public TurretData turretData;
    //是否升级了
    [HideInInspector]
    public bool isUpgraded = false;
    //建造特效
    public GameObject buildEffect;
    //渲染组件
    private Renderer renderer;

    void Start()
    {
        renderer = GetComponent<Renderer>();
    }

    public void BuildTurret(TurretData turretData)
    {
        this.turretData = turretData;
        isUpgraded = false;
        turretGo = GameObject.Instantiate(turretData.turretPrefab, transform.position, Quaternion.identity);
        GameObject effect = GameObject.Instantiate(buildEffect, transform.position, Quaternion.identity);
        //延时1.5秒销毁特效
        Destroy(effect, 1.5f);
    }

    public void UpgradeTurret()
    {
        if (isUpgraded == true) return;

        Destroy(turretGo);
        isUpgraded = true;
        turretGo = GameObject.Instantiate(turretData.turretUpGradedPrefab, transform.position, Quaternion.identity);
        GameObject effect = GameObject.Instantiate(buildEffect, transform.position, Quaternion.identity);
        Destroy(effect, 1.5f);
    }

    public void DestroyTurret()
    {
        Destroy(turretGo);
        isUpgraded = false;
        turretGo = null;
        turretData = null;
        GameObject effect = GameObject.Instantiate(buildEffect, transform.position, Quaternion.identity);
        Destroy(effect, 1.5f);
    }

    void OnMouseEnter()
    {
        //当前位置无炮台,且当前鼠标不在UI上
        if (turretGo == null && EventSystem.current.IsPointerOverGameObject() == false)
        {
            renderer.material.color = Color.red;
        }
    }
    void OnMouseExit()
    {
        renderer.material.color = Color.white;
    }
}
  • 创建敌人行走的路径,拐弯处使用空物体代替WayPoints
  • 创建敌人生成点和终点
  • 创建敌人生成代码
  • EnemySpawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemySpawner : MonoBehaviour {
    //敌人存活的数量
    public static int CountEnemyAlive = 0;
    //敌人每一波的数据数组
    public Wave[] waves;
    //起始点
    public Transform START;
    //每一波的间隔时间
    public float waveRate = 3F;
    void Start () {
        //开启一个协程
        StartCoroutine(SpawnEnemy());
    }
    //生成敌人的协程
    IEnumerator SpawnEnemy()
    {
        foreach (Wave wave in waves)
        {
            for (int i = 0; i < wave.count; i++)
            {
                //在开始点生成敌人
                GameObject.Instantiate(wave.enemyPrefab, START.position, Quaternion.identity);
                //敌人的数量当然要增加了
                CountEnemyAlive++;
                //控制每一个敌人的生成间隔时间
                if(i != wave.count - 1)
                yield return new WaitForSeconds(wave.rate);
            }
            //这里我还没弄明白
            while(CountEnemyAlive > 0)
            {
                yield return 0;
            }
            //控制每一波敌人的生成间隔时间
            yield return new WaitForSeconds(waveRate);

        }
    }
}

上面的代码中使用了协程,如果不懂可以看看这篇文章
- 创建炮塔Turret

炮塔类有的属性:
1.攻击速率(每秒攻击几次,或者多少秒攻击1次)
2.子弹
3.在范围内的敌人列表(为什么需要这个呢?因为炮塔最先攻击先进入范围内的敌人,当敌人不在范围内的时候,需要把敌人移除)
4.攻击的时间(记录攻击速率,每一个攻击间隔执行一次攻击)
Turret.cs

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

/// <summary>
/// 炮塔类
/// </summary>
public class Turret : MonoBehaviour {
    //所有在攻击范围的敌人
    private List<GameObject> enemys = new List<GameObject>();

    void OnTriggerEnter(Collider col)
    {
        if (col.tag == "Enemy")
        {
            enemys.Add(col.gameObject);
        }
    }
    void OnTriggerExit(Collider col)
    {
        if (col.tag == "Enemy")
        {
            enemys.Remove(col.gameObject);
        }
    }
    //多少秒攻击一次
    public float attackRateTime = 1; 
    private float timer = 0;
    //子弹
    public GameObject bulletPrefab;
    //开火位置
    public Transform firePosition;
    //头部
    public Transform head;
    //是否使用激光攻击
    public bool useLaser = false;
    //攻击的每秒伤害
    public float damageRate = 70;
    //激光
    public LineRenderer laserRenderer;
    //激光特效
    public GameObject laserEffect;

    void Start()
    {
        timer = attackRateTime;
    }

    void Update()
    {

        if (enemys.Count > 0 && enemys[0] != null)
        {//让炮塔朝向敌人
            Vector3 targetPosition = enemys[0].transform.position;
            targetPosition.y = head.position.y;
            head.LookAt(targetPosition);
        }
        if (useLaser == false)
        {//使用默认的炮弹攻击敌人
            timer += Time.deltaTime;
            if (enemys.Count > 0 && timer >= attackRateTime)
            {
                timer = 0;
                Attack();
            }
        }
        else if (enemys.Count > 0)
        {
            if (laserRenderer.enabled == false)
                laserRenderer.enabled = true;
            laserEffect.SetActive(true);
            if (enemys[0] == null)
            {
                //当敌人不再范围内时,需要把敌人从数组中移除
                UpdateEnemys();
            }
            if (enemys.Count > 0)
            {
                laserRenderer.SetPositions(new Vector3[] { firePosition.position, enemys[0].transform.position });
                enemys[0].GetComponent<Enemy>().TakeDamage(damageRate * Time.deltaTime);
                laserEffect.transform.position = enemys[0].transform.position;
                Vector3 pos = transform.position;
                pos.y = enemys[0].transform.position.y;
                laserEffect.transform.LookAt(pos);
            }
        }
        else
        {
            laserEffect.SetActive(false);
            laserRenderer.enabled = false;
        }
    }

    void Attack()
    {
        if (enemys[0] == null)
        {
            UpdateEnemys();
        }
        if (enemys.Count > 0)
        {
            GameObject bullet = GameObject.Instantiate(bulletPrefab, firePosition.position, firePosition.rotation);
            bullet.GetComponent<Bullet>().SetTarget(enemys[0].transform);
        }
        else
        {
            timer = attackRateTime;
        }
    }

    void UpdateEnemys()
    {
        List<int> emptyIndex = new List<int>();
        for (int index = 0; index < enemys.Count; index++)
        {
            if (enemys[index] == null)
            {
                emptyIndex.Add(index);
            }
        }

        for (int i = 0; i < emptyIndex.Count; i++)
        {
            //移除索引后,索引会发生变化,所以要减i
            enemys.RemoveAt(emptyIndex[i] - i);
        }
    }
}

接下来分析一下子弹有的属性
1.伤害 damage
2.速度 speed
3.目标点 target
Bullet.cs

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

public class Bullet : MonoBehaviour {
    public int damage = 50;
    public float speed = 20;
    public GameObject explosionEffectPrefab;
    private float distanceArriveTarget = 1.2f;
    private Transform target;
    public void SetTarget(Transform _target)
    {
        this.target = _target;
    }
    void Update()
    {
        if (target == null)
        {
            Die();
            return;
        }
        transform.LookAt(target.position);
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
        Vector3 dir = target.position - transform.position;
        if (dir.magnitude < distanceArriveTarget)
        {
            target.GetComponent<Enemy>().TakeDamage(damage);
            Die();   
        }
    }

    void Die()
    {
        GameObject effect = GameObject.Instantiate(explosionEffectPrefab, transform.position, transform.rotation);
        Destroy(effect, 1);
        Destroy(this.gameObject);
    }
}

猜你喜欢

转载自blog.csdn.net/cre2017/article/details/81266066