Unity-塔防游戏源码


本文提供全流程,中文翻译。

Chinar坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

1

有耐心的朋友可以跳转到SiKi学院,观看视频:SiKi学院

SiKi学院——是本人发现的网络教程做的很完善的网络课堂,推荐大家多学,多看

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;/// <summary>
/// 建筑物控制脚本
/// </summary>
public class BuildManager : MonoBehaviour
{public  TurretData StandarTurretData;  //标准炮塔数据public  TurretData MissileTurretData;  //导弹炮塔数据public  TurretData LaserTurretData;    //激光炮塔数据private TurretData SelectedTurretData; //当前选择的炮塔(即将要建造的炮台)private MapCube    _selectedMapCube;   //当前选择的游戏炮台private int        Money = 1000;       //金币public  Text       MoneyText;          //金币文本框public  Animator   MoneyAnimator;public  GameObject UpgradeCanvas;public  Button     ButtonUpGrade;private Animator   UpgradeCanvasAnimator;void Start(){UpgradeCanvasAnimator = UpgradeCanvas.GetComponent<Animator>();}void Update(){//容错,炮台的建造,需要满足2个条件if (SelectedTurretData != null && Input.GetMouseButtonDown(0)) //如果鼠标右键按下;{if (EventSystem.current.IsPointerOverGameObject() == false) //检测鼠标在不在UI上。{//射线Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//被照射物体RaycastHit hit;//是否照射到物体                  (射线,被照射物体,射线长度,MapCuber层的物体)bool isCollider = Physics.Raycast(ray, out hit, 1000, LayerMask.GetMask("MapCube"));if (isCollider){MapCube mapcube = hit.collider.GetComponent<MapCube>(); //得到点击的mapcube//如果底板上 没有炮塔,则可以创建if (mapcube.TurretGo == null){//可以创建,然后判断钱够不够,if (Money >= SelectedTurretData.Cost){ChangeMoney(-SelectedTurretData.Cost);   //减少钱mapcube.BuildTurret(SelectedTurretData); //创建炮塔}else{//提示钱不够MoneyAnimator.SetTrigger("Flicker");}}else if (mapcube.TurretGo != null){//选择的是否是同一个炮台&&UI升级框是否显示if (mapcube.TurretGo == _selectedMapCube && UpgradeCanvas.activeInHierarchy){StartCoroutine(HideUpGradeUi());}else{Vector3 upgraded = new Vector3(mapcube.transform.position.x, mapcube.transform.position.y + 2.6f, mapcube.transform.position.z);//升级ShowUpGradeUI(upgraded, mapcube.IsUpgraded);}//选择的炮台,被赋值_selectedMapCube = mapcube;}}}}}public void OnStandarSelected(bool isOn){if (isOn){SelectedTurretData = StandarTurretData;}}public void OnMissileSelected(bool isOn){if (isOn){SelectedTurretData = MissileTurretData;}}public void OnLaserSelected(bool isOn){if (isOn){SelectedTurretData = LaserTurretData;}}/// <summary>/// 金钱的变动/// </summary>/// <param name="change"></param>private void ChangeMoney(int change = 0){Money          += change;      //金币的变动MoneyText.text =  "¥" + Money; //金币文本框赋值}/// <summary>/// 显示升级按钮/// </summary>/// <param name="pos"></param>/// <param name="isDisableUp"></param>private void ShowUpGradeUI(Vector3 pos, bool isDisableUp = false) //是否禁用升级按钮{StopCoroutine(HideUpGradeUi());UpgradeCanvas.SetActive(false); //显示按钮UpgradeCanvas.transform.position = pos;UpgradeCanvas.SetActive(true);             //显示按钮ButtonUpGrade.interactable = !isDisableUp; //是否可以交互/  false}/// <summary>/// 隐藏升级按钮/// </summary>IEnumerator HideUpGradeUi(){UpgradeCanvasAnimator.SetTrigger("Hide");yield return new WaitForSeconds(0.6f);UpgradeCanvas.SetActive(false);}/// <summary>/// 点击升级按钮,升级炮塔/// </summary>public void OnUpGradeButtonDown(){if (Money >= _selectedMapCube._turretData.Cost) //钱够不够{ChangeMoney(-_selectedMapCube._turretData.Cost);_selectedMapCube.UpGradeTurret();}else{MoneyAnimator.SetTrigger("Flicker");}StartCoroutine(HideUpGradeUi());}/// <summary>/// 点击拆按钮。拆炮塔/// </summary>public void OnDestroyButtonDown(){_selectedMapCube.DestroyTurret();StartCoroutine(HideUpGradeUi());}
}

2

using UnityEngine;/// <summary>
/// 子弹类脚本
/// </summary>
public class Bullet : MonoBehaviour
{public  int       Damage = 50; //伤害public  float     Speed  = 20; //速度private Transform Target;      //目标public  GameObject ExplosionEffectPrefab;    //子弹特效private float      DistanceArriveTarget = 2; //子弹于目标物体,向量长度void Start(){}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) //向量的长度magnitude{//子弹打到敌人,掉血Target.GetComponent<Enemy>().TakeDamage(Damage);Die();}}private void Die(){//实例化特效GameObject effect = Instantiate(ExplosionEffectPrefab, transform.position, transform.rotation) as GameObject;//删除特效Destroy(effect, 1f);//销毁子弹Destroy(this.gameObject);}/// <summary>/// 设置目标/// /// </summary>/// <param name="_target"></param>public void SetTarget(Transform _target){this.Target = _target;}
}

3

using UnityEngine;
using System.Collections;
using UnityEngine.UI;/// <summary>
/// 敌人脚本
/// </summary>
public class Enemy : MonoBehaviour
{//位置数组private Transform[] positions;//下标,从0开始private int index = 0;//速度public float Speed = 10;public float Hp = 150;private float TotalHp; //总HPpublic GameObject ExplosionEffect; //敌人爆炸特效private Slider HpSlider;void Start(){positions = WayPoints.positions;TotalHp = Hp;HpSlider = GetComponentInChildren<Slider>();}void Update(){Move();}void Move(){//下标越界,就跳出;if (index > positions.Length - 1) return;//找一个方向,(目标位置-当前位置).normalized 取得这个向量的单位向量 ;transform.Translate((positions[index].position - transform.position).normalized * Time.deltaTime * Speed);//判断 两点 之间的距离if (Vector3.Distance(positions[index].position, transform.position) < 0.5f){index++;}if (index > positions.Length - 1){ReachDestination();}}/// <summary>/// ReachDestination 到达 目的地 销毁/// </summary>void ReachDestination(){Destroy(this.gameObject);GameManager.instance.Failed();}/// <summary>/// 监听销毁敌人/// </summary>void OnDestroy(){EnemySpawner.CountEnemyAlive--;}/// <summary>/// 敌人受到伤害/// </summary>/// <param name="damage"></param>public void TakeDamage(float damage){if (Hp <= 0) return;                    //死了不处理Hp             -= damage;               //减少血量HpSlider.value =  (float) Hp / TotalHp; //血条if (Hp <= 0){Die();}}private void Die(){GameObject effect = Instantiate(ExplosionEffect, transform.position, transform.rotation) as GameObject;Destroy(effect, 1.5f);Destroy(this.gameObject);}
}

4

using UnityEngine;
using System.Collections;/// <summary>
/// 敌人生成控制脚本
/// </summary>
public class EnemySpawner : MonoBehaviour
{//属性面板public Wave[] Waves;//生成位置public Transform StartTran;//孵化间隔public float WaveRate = 0.2f;//存活敌人的数量public static int CountEnemyAlive = 0;private Coroutine coroutine;void Start(){coroutine = StartCoroutine(SpawnEnemy());}/// <summary>/// 敌人孵化器/// </summary>/// <returns></returns>IEnumerator SpawnEnemy(){//遍历所有Waves中的 数组foreach (Wave wave in Waves){for (int i = 0; i < wave.Count; i++){//实例化预设物(每一波敌人的预设物,开始位置,无旋转的)旋转前的初始角GameObject.Instantiate(wave.EnemyPrefab, StartTran.position, Quaternion.identity);CountEnemyAlive++; //存活数量增加if (i != wave.Count - 1) //检测生成是否完毕{//时间间隔yield return new WaitForSeconds(wave.Rate);}}//当存活数量大于0while (CountEnemyAlive > 0){yield return 0; //暂停0帧,不执行下边代码}//每一波暂停 WaveRate 秒yield return new WaitForSeconds(WaveRate);}}/// <summary>/// 停止生成/// </summary>public void Stop(){StopCoroutine(coroutine);}
}

5

using UnityEngine;
using UnityEngine.EventSystems;/// <summary>
/// 地图版块控制脚本
/// </summary>
public class MapCube : MonoBehaviour
{[HideInInspector]                             //不显示在 Inspector 面板public                   GameObject TurretGo; //保存当前Cube身上的炮台[HideInInspector] public TurretData _turretData;public                   GameObject BuildEffect;private Renderer CubeRenderer;[HideInInspector] public bool IsUpgraded; //MapCub上的炮塔是否升级过void Start(){CubeRenderer = GetComponent<Renderer>();}/// <summary>/// 点击创建炮塔/// </summary>/// <param name="turretPrefab"></param>public void BuildTurret(TurretData turretData){this._turretData = turretData;IsUpgraded       = false;//创建炮塔,位置,旋转,强转TurretGo             = Instantiate(turretData.TurretPrefab, transform.position, Quaternion.identity) as GameObject;GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;Destroy(effectobj, 1f);}/// <summary>/// 升级炮台/// </summary>/// <param name="turretgo"></param>public void UpGradeTurret(){if (IsUpgraded == true) return; //容错Destroy(TurretGo);              //删除低级炮塔IsUpgraded = true;              //升级状态变化//创建炮塔,位置,旋转,强转TurretGo             = Instantiate(_turretData.TurretUpGradedPrefab, transform.position, Quaternion.identity) as GameObject;GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;}/// <summary>/// 拆除炮台/// </summary>public void DestroyTurret(){Destroy(TurretGo);GameObject effectobj = Instantiate(BuildEffect, transform.position, Quaternion.identity) as GameObject;IsUpgraded           = false; //升级状态变化TurretGo             = null;_turretData          = null;}/// <summary>/// 鼠标移入/// </summary>private void OnMouseEnter(){//Cube上没有炮台,且,鼠标没有放在UI上if (TurretGo == null && EventSystem.current.IsPointerOverGameObject() == false){CubeRenderer.material.color = Color.red; //变红}}/// <summary>/// 鼠标移出/// </summary>private void OnMouseExit(){CubeRenderer.material.color = Color.white; //变红}
}

6

using UnityEngine;/// <summary>
/// 炮塔模型类
/// </summary>
[System.Serializable] //可序列化
public class TurretData
{//炮塔预设物public GameObject TurretPrefab;//花费public int Cost;//炮塔升级预设物public GameObject TurretUpGradedPrefab;//升级炮塔花费public int CostUpGraded;//默认枚举类型public TurretType Type;
}/// <summary>
/// 枚举一个炮塔类
/// </summary>
public enum TurretType
{StandardTurret, //标准MissileTurret,  //导弹LaserTurret     //激光
}

7

using UnityEngine;
using System.Collections.Generic;/// <summary>
/// 炮塔控制脚本类
/// </summary>
public class Turret : MonoBehaviour
{private List<GameObject> Enemys         = new List<GameObject>(); //进入方位的敌人public  float            AttackRateTime = 1;                      //攻击间隔private float            Timer          = 0;                      //计时器public  GameObject       BulletPrefab;                            //子弹 预设物public  Transform        FirePos;public  Transform        Head;public  bool             UseLaser   = false; //默认攻击方式public  float            DamageRate = 70;    //激光炮塔,持续伤害 速率。每秒70点伤害public  LineRenderer     LaseRenderer;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;//敌人数量大于0,且满足间隔时间if (Enemys.Count > 0 && Timer >= AttackRateTime){Timer = 0;Attack();}}else if (Enemys.Count > 0){if (LaseRenderer.enabled == false) LaseRenderer.enabled = true;if (Enemys[0] == null){UpDateEnemys();}if (Enemys.Count > 0){//激光炮塔朝向LaseRenderer.SetPositions(new Vector3[] {FirePos.position, Enemys[0].transform.position});//激光炮塔攻击Enemys[0].GetComponent<Enemy>().TakeDamage(DamageRate * Time.deltaTime);LaserEffect.SetActive(true);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);LaseRenderer.enabled = false;}}/// <summary>/// 攻击方法/// </summary>private void Attack(){if (Enemys[0] == null){UpDateEnemys();}if (Enemys.Count > 0){//实例化子弹GameObject bullet = Instantiate(BulletPrefab, FirePos.position, FirePos.rotation) as GameObject;//子弹 指向目标bullet.GetComponent<Bullet>().SetTarget(Enemys[0].transform);}else{Timer = AttackRateTime; //下次来敌人,直接攻击}}/// <summary>/// 进入区域/// </summary>/// <param name="col"></param>private void OnTriggerEnter(Collider col){if (col.tag == "Enemy"){Enemys.Add(col.gameObject);}}/// <summary>/// 离开区域/// </summary>/// <param name="col"></param>private void OnTriggerExit(Collider col){if (col.tag == "Enemy"){Enemys.Remove(col.gameObject);}}/// <summary>/// 更新集合/// </summary>private void UpDateEnemys(){//用来存空元素下标  的数组List<int> EmptyIndex = new List<int>();//移除所有为空的元素,遍历进入范围的敌人数组长度。for (int i = 0; i < Enemys.Count; i++){if (Enemys[i] == null){EmptyIndex.Add(i);}}//移除 所有空元素for (int i = 0; i < EmptyIndex.Count; i++){//由于Enemys移除元素,下标会变动。所以减去,移除的个数;Enemys.RemoveAt(EmptyIndex[i] - i);}}
}

8

using UnityEngine;
using System.Collections;/// <summary>
/// 玩家视角控制脚本
/// </summary>
public class ViewController : MonoBehaviour
{public float Speed      = 1;   //速度public float MouseSpeed = 249; //速度void Start(){}void Update(){//获取水平和垂直参数float h     = Input.GetAxis("Horizontal");float v     = Input.GetAxis("Vertical");float mouse = Input.GetAxis("Mouse ScrollWheel") * MouseSpeed;//控制移动,并根据时间平滑移动,根据世界坐标移动transform.Translate(new Vector3(h * Speed, mouse, v * Speed) * Time.deltaTime, Space.World);}
}

9

using UnityEngine;/// <summary>
/// 保存每一波敌人生成所需要的属性
/// </summary>
[System.Serializable] //可以被序列化的属性
public class Wave
{public GameObject EnemyPrefab; //敌人public int        Count;       //数量public float      Rate;        //时间间隔
}

10

有耐心的朋友可以跳转到SiKi学院,观看视频:SiKi学院

using UnityEngine;/// <summary>
/// 路径导航脚本
/// </summary>
public class WayPoints : MonoBehaviour
{//拐点,数组public static Transform[] positions;void Awake(){//找到当前,挂载脚本物体下的,子物体数量positions = new Transform[transform.childCount];//依次遍历所有子物体,得到依次的位置for (int i = 0; i < positions.Length; i++){positions[i] = transform.GetChild(i);}}
}

1 —— 云服务器超全购买流程 (新手必备!)

2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)

3—— Windows 服务器配置、运行、建站一条龙 !

4 —— Linux 服务器配置、运行、建站一条龙 !


<script type="math/tex" id="MathJax-Element-2"> </script>
技术交流群:806091680 ! Chinar 欢迎你的加入


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址>

Unity 3D游戏-塔防类游戏源码:重要方法和功能的实现相关推荐

  1. Ant Buster蚂蚁大作战(塔防类游戏经典)

    蚂蚁大作战在塔防类Flash游戏上绝对称得上是精品,游戏主要靠升级而非海塔战术来推动,小蚂蚁们的AI也是很不错的,哪里一旦出现漏洞,就会乘机穿过去,音乐恰到好处,尤其是偷到蛋糕后的那一阵奸笑;)--- ...

  2. unity3D游戏开发实战原创视频讲座系列9之塔防类游戏开发第一季

    解说文件夹 塔防游戏0基础篇... 第一讲  游戏演示和资源介绍... 第二讲  游戏场景的完毕... 第三讲  预制体的制作... 第四讲  敌人的随机产生和按路径行走... 第五讲  塔防工具的产 ...

  3. 微信小程序做塔防类游戏

    开发一款塔防游戏需要以下步骤: 设计游戏规则和关卡设计,包括塔防类型.敌人类型.塔类型.升级系统等. 使用微信开发者工具创建新的小程序项目. 使用小程序框架(WXML.WXSS和JavaScript) ...

  4. 【邪恶古堡】一款手机游戏|塔防类|主角是反派/魔王|敌人是勇士/英雄|需要救公主|放置陷阱/障碍|乱入|安卓|苹果

    邪恶古堡 游戏介绍: <邪恶古堡>是一款第一反派视角塔防手游,游戏中,多种陷阱,N套组合供玩家挑战,且多种惊魂主题供玩家挑战!其需要玩家扮演魔王,将公主囚禁在城堡,并在路上设置了各种陷阱和 ...

  5. python小游戏——塔防小游戏代码开源

    ♥️作者:小刘在这里 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放,愿所有的美好,再疫情结束后如约而至. 目录 一.效 ...

  6. 使用Unity3D引擎制作塔防类游戏(二)

    时隔这么久,终于写完了关于兵营的大部分功能,写完的同时,还要感慨一下,从头做一个游戏真的好难啊,到现在也只写完一个一级的兵营,问题也不少,写出来分享一下,目前的代码不是很高深,要是有更好的写法,也请不 ...

  7. wp7使用Cocos2d-X for XNA制作一个塔防类游戏 (二)在游戏中加入地图和怪物。(上)

    地图编辑器的使用 首先先来介绍一下使用地图编辑器tIDE Tile Map Editor来生成TMX文件.tIDE Tile Map Editor的下载地址  http://tide.codeplex ...

  8. python小游戏 塔防小游戏设计与实现

    文章目录 0 项目简介 1 游戏介绍 2 实现效果 3 Pygame介绍 4 原理和实现 4.1 环境配置 4.2 游戏界面说明 4.3 游戏主逻辑 4.4 游戏开始界面 4.5 游戏选择界面 4.6 ...

  9. 如何在unity中制作塔防游戏

       塔防游戏非常流行,毫无疑问--没有什么比看着自己的防御消灭讨厌的侵略者更让人满足!在这两部分教程中,用unity来制作一个塔防游戏! 将会学习怎样...... 创建一波敌人 让它们跟随线路点 ...

  10. android 小游戏源码_Python入门太难?不如从玩塔防小游戏开始,玩通关就能学会编程...

    我一直认为,在python入门阶段学习基础理论,太枯燥.所以我们整理了很多有关python的项目案例,有详细教程还有源码,希望能帮助更多对python感兴趣的人. 这是其中一个适合入门的Python项 ...

最新文章

  1. 台哥原创:java 扫雷源码
  2. Linux查看CPU,内存,GPU,进程,版本,系统内核信息
  3. 4种实例 advice aop_Java动态代理在Spring的应用:AOP编程与动态代理知识
  4. 技术管理:技术负责人所需的四个核心能力
  5. url过滤怎么解除_Shiro-实战(四)---过滤器机制
  6. crm采用soap删除记录
  7. python分布式事务_分布式事务的管理--atomikos
  8. CVPR 2020丨基于范例的精细可控图像翻译CoCosNet,一键生成你心目中的图像
  9. 双11即将来临,淘宝内测“购物车分享”功能
  10. Python int与string 的转换
  11. 拓端tecdat|R语言stan泊松回归Poisson regression
  12. 制作 Pidgin QQ 表情包
  13. 练习题12-外观数列
  14. 微信小程序获取用户Ip地址
  15. ALCOA+CCEA原则(数据完整性标准)
  16. 用户互动功能,微信商城系统
  17. 刘强东最牛女助理任CHO:颜值不输奶茶妹妹,32岁成京东内部二号人物………...
  18. ORM框架——SqlSugar
  19. 练习-Java分支结构综合练习二之物流运费计算
  20. Editplus扩展程序的删除

热门文章

  1. 计算机被管理员限制怎么解除,Win10系统管理员账户被禁用如何解除?
  2. windows2008server实现端口映射代理
  3. 【git】git的删除命令与如何删除仓库文件的方法
  4. MySQL:explain结果中Extra:Impossible WHERE noticed after reading const tables
  5. 河南理工计算机课程表,河南理工大学张威的课程表.doc
  6. python音频转文字腾讯_Python生成腾讯云实时音视频的UserSig签名
  7. 使用JAVA编程实现多人聊天室(多线程实践)
  8. 关于图片格式的选择,jpg、png、gif、svg
  9. 象棋马走日步数计算流程图
  10. 计算机英语总结800,高三英语教师工作总结800字(通用5篇)