Unity 3D游戏-塔防类游戏源码:重要方法和功能的实现
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游戏-塔防类游戏源码:重要方法和功能的实现相关推荐
- Ant Buster蚂蚁大作战(塔防类游戏经典)
蚂蚁大作战在塔防类Flash游戏上绝对称得上是精品,游戏主要靠升级而非海塔战术来推动,小蚂蚁们的AI也是很不错的,哪里一旦出现漏洞,就会乘机穿过去,音乐恰到好处,尤其是偷到蛋糕后的那一阵奸笑;)--- ...
- unity3D游戏开发实战原创视频讲座系列9之塔防类游戏开发第一季
解说文件夹 塔防游戏0基础篇... 第一讲 游戏演示和资源介绍... 第二讲 游戏场景的完毕... 第三讲 预制体的制作... 第四讲 敌人的随机产生和按路径行走... 第五讲 塔防工具的产 ...
- 微信小程序做塔防类游戏
开发一款塔防游戏需要以下步骤: 设计游戏规则和关卡设计,包括塔防类型.敌人类型.塔类型.升级系统等. 使用微信开发者工具创建新的小程序项目. 使用小程序框架(WXML.WXSS和JavaScript) ...
- 【邪恶古堡】一款手机游戏|塔防类|主角是反派/魔王|敌人是勇士/英雄|需要救公主|放置陷阱/障碍|乱入|安卓|苹果
邪恶古堡 游戏介绍: <邪恶古堡>是一款第一反派视角塔防手游,游戏中,多种陷阱,N套组合供玩家挑战,且多种惊魂主题供玩家挑战!其需要玩家扮演魔王,将公主囚禁在城堡,并在路上设置了各种陷阱和 ...
- python小游戏——塔防小游戏代码开源
♥️作者:小刘在这里 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放,愿所有的美好,再疫情结束后如约而至. 目录 一.效 ...
- 使用Unity3D引擎制作塔防类游戏(二)
时隔这么久,终于写完了关于兵营的大部分功能,写完的同时,还要感慨一下,从头做一个游戏真的好难啊,到现在也只写完一个一级的兵营,问题也不少,写出来分享一下,目前的代码不是很高深,要是有更好的写法,也请不 ...
- wp7使用Cocos2d-X for XNA制作一个塔防类游戏 (二)在游戏中加入地图和怪物。(上)
地图编辑器的使用 首先先来介绍一下使用地图编辑器tIDE Tile Map Editor来生成TMX文件.tIDE Tile Map Editor的下载地址 http://tide.codeplex ...
- python小游戏 塔防小游戏设计与实现
文章目录 0 项目简介 1 游戏介绍 2 实现效果 3 Pygame介绍 4 原理和实现 4.1 环境配置 4.2 游戏界面说明 4.3 游戏主逻辑 4.4 游戏开始界面 4.5 游戏选择界面 4.6 ...
- 如何在unity中制作塔防游戏
塔防游戏非常流行,毫无疑问--没有什么比看着自己的防御消灭讨厌的侵略者更让人满足!在这两部分教程中,用unity来制作一个塔防游戏! 将会学习怎样...... 创建一波敌人 让它们跟随线路点 ...
- android 小游戏源码_Python入门太难?不如从玩塔防小游戏开始,玩通关就能学会编程...
我一直认为,在python入门阶段学习基础理论,太枯燥.所以我们整理了很多有关python的项目案例,有详细教程还有源码,希望能帮助更多对python感兴趣的人. 这是其中一个适合入门的Python项 ...
最新文章
- 台哥原创:java 扫雷源码
- Linux查看CPU,内存,GPU,进程,版本,系统内核信息
- 4种实例 advice aop_Java动态代理在Spring的应用:AOP编程与动态代理知识
- 技术管理:技术负责人所需的四个核心能力
- url过滤怎么解除_Shiro-实战(四)---过滤器机制
- crm采用soap删除记录
- python分布式事务_分布式事务的管理--atomikos
- CVPR 2020丨基于范例的精细可控图像翻译CoCosNet,一键生成你心目中的图像
- 双11即将来临,淘宝内测“购物车分享”功能
- Python int与string 的转换
- 拓端tecdat|R语言stan泊松回归Poisson regression
- 制作 Pidgin QQ 表情包
- 练习题12-外观数列
- 微信小程序获取用户Ip地址
- ALCOA+CCEA原则(数据完整性标准)
- 用户互动功能,微信商城系统
- 刘强东最牛女助理任CHO:颜值不输奶茶妹妹,32岁成京东内部二号人物………...
- ORM框架——SqlSugar
- 练习-Java分支结构综合练习二之物流运费计算
- Editplus扩展程序的删除
热门文章
- 计算机被管理员限制怎么解除,Win10系统管理员账户被禁用如何解除?
- windows2008server实现端口映射代理
- 【git】git的删除命令与如何删除仓库文件的方法
- MySQL:explain结果中Extra:Impossible WHERE noticed after reading const tables
- 河南理工计算机课程表,河南理工大学张威的课程表.doc
- python音频转文字腾讯_Python生成腾讯云实时音视频的UserSig签名
- 使用JAVA编程实现多人聊天室(多线程实践)
- 关于图片格式的选择,jpg、png、gif、svg
- 象棋马走日步数计算流程图
- 计算机英语总结800,高三英语教师工作总结800字(通用5篇)