【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏3(附项目源码)

文章目录

  • 本节最终效果
  • 前言
  • 近战武器
  • 控制近战武器生成
  • 升级增加武器伤害和数量
  • 查找离主角最近的敌人
  • 子弹预制体
  • 生成子弹
  • 发射子弹
  • 参考
  • 源码
  • 完结

本节最终效果

在这里插入图片描述

前言

本节紧跟着上一篇,主要实现武器功能。

近战武器

新增Bullet,子弹脚本

public class Bullet : MonoBehaviour
{public float damage; // 子弹的伤害值/// <summary>/// 初始化子弹的属性/// </summary>/// <param name="damage">伤害值</param>public void Init(float damage){this.damage = damage; // 设置子弹的伤害值}
}

新增近战武器预制体,添加触发器,挂载脚本,配置参数
在这里插入图片描述

修改Enemy敌人脚本,添加触发器检测

void OnTriggerEnter2D(Collider2D collision)
{if (!collision.CompareTag("Bullet")) return;health -= collision.GetComponent<Bullet>().damage;if (health > 0){}else{Dead();}
}void Dead()
{gameObject.SetActive(false);
}

效果,敌人触碰死亡
在这里插入图片描述

控制近战武器生成

配置近战武器进对象池
在这里插入图片描述

新增Weapon。控制武器/子弹的生成

public class Weapon : MonoBehaviour
{public int id; // 武器/子弹的IDpublic int prefabId; // 武器/子弹预制体的IDpublic float damage; // 武器/子弹的伤害值public int count; // 发射武器/子弹的数量public float speed; // 武器旋转的速度void Start(){Init(); // 初始化武器属性}void Update(){switch (id){case 0:transform.Rotate(Vector3.back, speed * Time.deltaTime); // 绕z轴旋转武器break;default:break;}}/// <summary>/// 初始化武器/子弹属性/// </summary>public void Init(){switch (id){case 0:speed = 150; // 设置武器旋转的速度Batch();break;default:break;}}/// <summary>/// 批量配置武器属性/// </summary>void Batch(){for (int index = 0; index < count; index++){Transform bullet = GameManager.instance.pool.Get(prefabId).transform; // 从对象池中获取武器预制体的实例bullet.parent = transform; // 设置武器的父级为武器Vector3 rotvec = Vector3.forward * 360 * index / count; // 计算武器的旋转角度,使其均匀分布在圆周上bullet.Rotate(rotvec); // 设置武器的旋转角度bullet.Translate(bullet.up * 1.5f, Space.World); // 将武器沿着自身的y轴方向向前移动一定距离bullet.GetComponent<Bullet>().Init(damage); // 初始化武器的属性}}
}

挂载配置参数
在这里插入图片描述
单武器效果
在这里插入图片描述
多武器效果
在这里插入图片描述
在这里插入图片描述

升级增加武器伤害和数量

修改Weapon

void Update()
{//。。。//测试if (Input.GetKeyDown(KeyCode.Space)){LevelUp(20, 5);}
}/// <summary>
/// 批量配置武器属性
/// </summary>
void Batch()
{for (int index = 0; index < count; index++){Transform bullet;if (index < transform.childCount){bullet = transform.GetChild(index);}else{bullet = GameManager.instance.pool.Get(prefabId).transform;// 从对象池中获取武器预制体的实例bullet.parent = transform;// 设置武器的父级为武器}//。。。}
}

效果
在这里插入图片描述

查找离主角最近的敌人

新增Scanner

public class Scanner : MonoBehaviour
{public float scanRange; // 扫描范围public LayerMask targetLayer; // 目标层public RaycastHit2D[] targets; // 扫描到的目标public Transform nearestTarget; // 最近的目标void FixedUpdate(){targets = Physics2D.CircleCastAll(transform.position, scanRange, Vector2.zero, 0, targetLayer); // 在扫描范围内发射圆形光线,获取扫描到的目标nearestTarget = GetNearest();}// 获取最近的目标Transform GetNearest(){Transform result = null; // 初始化最近的目标为nullfloat diff = scanRange; // 初始化最小距离为100,用于后面比较foreach (RaycastHit2D target in targets){Vector3 myPos = transform.position; // 获取自身位置Vector3 targetPos = target.transform.position; // 获取目标位置float curDiff = Vector3.Distance(myPos, targetPos); // 计算自身与目标的距离if (curDiff < diff) // 如果当前目标距离比之前的最小距离还小,说明这个目标更近{diff = curDiff; // 更新最小距离result = target.transform; // 更新最近的目标}}return result; // 返回最近的目标}//场景窗口可视化射线private void OnDrawGizmos(){Gizmos.DrawWireSphere(transform.position, scanRange);Gizmos.color = Color.red;}
}

挂载脚本,配置参数
在这里插入图片描述

效果,获取了离自己最近的敌人
在这里插入图片描述

子弹预制体

在这里插入图片描述

对象池挂载子弹
在这里插入图片描述

生成子弹

修改Weapon

float timer;
Player player;void Start()
{player = GameManager.instance.player;Init(); // 初始化武器属性
}void Update()
{switch (id){//。。。default:timer += Time.deltaTime;if (timer > speed){timer = 0f;Fire();}break;}
}/// <summary>
/// 初始化武器/子弹属性
/// </summary>
public void Init()
{switch (id){//。。。default:speed = 0.3f;break;}
}//发射子弹
void Fire()
{if (!player.scanner.nearestTarget) return;Transform bullet = GameManager.instance.pool.Get(prefabId).transform;bullet.position = transform.position;
}

修改Player,获取最近的敌人数据

[NonReorderable]
public Scanner scanner;scanner = GetComponent<Scanner>();

配置子弹生成容器及数据
在这里插入图片描述
效果,每0.3秒生成一个子弹
在这里插入图片描述

发射子弹

修改Bullet

Rigidbody2D rigid;
private int per; // 子弹的穿透次数void Awake()
{rigid = GetComponent<Rigidbody2D>(); // 获取子弹的刚体组件
}public void Init(float damage, int per, Vector3 dir)
{this.damage = damage; // 初始化子弹的伤害值this.per = per; // 初始化子弹的穿透次数if (per > -1){rigid.velocity = dir * 15f; // 如果子弹具有穿透次数,则设置子弹的初始速度和方向}
}void OnTriggerEnter2D(Collider2D collision)
{if (!collision.CompareTag("Enemy") || per == -1) return; // 如果碰撞物体不是敌人或子弹没有穿透次数,直接返回per--; // 穿透次数减一if (per == -1){rigid.velocity = Vector2.zero; // 如果穿透次数减到-1,即没有穿透能力了,将子弹的速度设为零gameObject.SetActive(false); // 将子弹设为非激活状态,使其隐藏或回收}
}

修改Weapon

void Batch()
{//。。。bullet.GetComponent<Bullet>().Init(damage, -1, Vector3.zero); // 初始化武器的属性}
}// 发射子弹
void Fire()
{if (!player.scanner.nearestTarget) return; // 如果玩家的扫描器没有最近的目标,直接返回Vector3 targetPos = player.scanner.nearestTarget.position; // 获取最近目标的位置Vector3 dir = targetPos - transform.position; // 计算从当前位置指向目标位置的方向向量dir = dir.normalized; // 将方向向量归一化,使其成为单位向量Transform bullet = GameManager.instance.pool.Get(prefabId).transform; // 从对象池中获取一个子弹对象bullet.position = transform.position; // 设置子弹的初始位置为当前位置bullet.rotation = Quaternion.FromToRotation(Vector3.up, dir); // 将子弹的朝向调整为指向目标位置的方向bullet.GetComponent<Bullet>().Init(damage, count, dir); // 初始化子弹的伤害值、穿透次数和初始速度方向
}

效果
在这里插入图片描述

修改Weapon,升级测试

//测试
if (Input.GetKeyDown(KeyCode.Space))
{LevelUp(10, 1);
}

效果,升级后子弹具有了一定穿透性
在这里插入图片描述

参考

【视频】https://www.youtube.com/watch?v=MmW166cHj54&list=PLO-mt5Iu5TeZF8xMHqtT_DhAPKmjF6i3x

源码

源码在最后一节

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Shell编程基础 – for循环

Shell编程基础 – for循环 Shell Scripting Essentials - for Loop 大多数编程语言都有循环的概念和语句。如果想重复一个任务数十次&#xff0c;无论是输入数十次&#xff0c;还是输出数十次&#xff0c;对用户来说都不现实。 因此&#xff0c;我们考虑如何用好Bash Shell编…

单片机BootLoader是咋回事?

BootLoader的定义&#xff1a; CPU进入APP之前运行的一小段程序代码就叫做BootLoader。它是由程序员编写的&#xff0c;作用是更新应用程序。这也就说明了只有BootLoader的单片机才可以升级。有的产品有升级的需要就需要BootLoader了。 单片机的启动过程可以这么叙述&#xff…

什么是路由抖动?该如何控制

路由器在实现不间断的网络通信和连接方面发挥着重要作用&#xff0c;具有所需功能的持续可用的路由器可确保其相关子网的良好性能&#xff0c;由于网络严重依赖路由器的性能&#xff0c;因此确保您的路由器不会遇到任何问题非常重要。路由器遇到的一个严重的网络问题是路由抖动…

使用 watch+$nextTick 解决Vue引入组件无法使用问题

问题描述&#xff1a; 很多时候我们都需要使用第三方组件库&#xff0c;比如Element-UI&#xff0c;Swiper 等等。 如果我们想要在这些结构中传入自己从服务器请求中获取的数据就会出现无法显示的问题。 比如我们在下面的Swiper例子中&#xff0c;我们需要new Swiper 才能让…

【华为OD题库-043】二维伞的雨滴效应-java

题目 普通的伞在二维平面世界中&#xff0c;左右两侧均有一条边&#xff0c;而两侧伞边最下面各有一个伞坠子&#xff0c;雨滴落到伞面&#xff0c;逐步流到伞坠处&#xff0c;会将伞坠的信息携带并落到地面&#xff0c;随着日积月累&#xff0c;地面会呈现伞坠的信息。 1、为了…

mysql主从复制-redis集群扩容缩容、缓存优化(缓存更新策略、穿透,击穿,雪崩)、mysql主从搭建、django实现读写分离

基于Docker实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 1.2 集群缩容 2 缓存优化 2.1 缓存更新策略 2.2 穿透&#xff0c;击穿&#xff0c;雪崩 3 mysql主从搭建 4 django实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 # 6台机器&#xff0c;3个节点集群# 8台机器&am…

第12关 精通K8s下的Ingress-Nginx控制器:生产环境实战配置指南

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维&#xff0c;这节课带来k8s的流量入口ingress&#xff0c;作为业务对外服务的公网入口&#xff0c;它的重要性不言而喻&#xff0c;大家一定要仔细阅读&#xff0c;跟着博哥的教程一步步实操去理…

HTML5语法总结大全(持续更新中~)

参考书籍&#xff1a; 《HTML与CSS3基础教程》 参考视频&#xff1a; HTML5完整教学通俗易懂 2023新版前端Web开发HTML5CSS3移动web视频教程&#xff0c;前端web入门首选黑马程序员 参考网站&#xff1a; w3school 文章目录 零.开发环境准备1.需要的工具2.Vscode所需要插件3.其…

智能优化算法应用:基于混合蛙跳算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于混合蛙跳算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于混合蛙跳算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.混合蛙跳算法4.实验参数设定5.算法结果6.参考…

Snagit 2024.0.1(Mac屏幕截图软件)

Snagit 2024是一款屏幕截图工具&#xff0c;可以帮助用户轻松捕获、编辑和分享屏幕截图。该工具在Mac上运行&#xff0c;旨在满足用户对于屏幕截图的各种需求。 Snagit 2024支持屏幕录制功能&#xff0c;可以录制摄像头和麦克风等外部设备&#xff0c;让用户录制更加全面的视频…

Redis基本操作及使用

&#x1f4d1;前言 本文主要是【Redis】——Redis基本操作及使用的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

springboot 自定义starter逐级抽取

自定义starter 背景:各个组件需要引入starter 还有自己的配置风格 –基本配置原理 &#xff08;1&#xff09;自定义配置文件 导入配置可以在配置文件中自动识别&#xff0c;提示 导入依赖后可以发现提示 &#xff08;2&#xff09;配置文件实现 –让配置文件对其他模块生…

酵母双杂交服务专题(二)

在理解了蛋白互作关系基础之上&#xff0c;为了解析它们的互作机制&#xff0c;往往还需要对其上下游通路上的基因进行分析。蛋白质之间的相互作用通过促进或抑制下游基因的转录&#xff0c;从而影响细胞的一系列生命过程。酵母单杂交技术是一种研究蛋白和DNA相互作用的常用手段…

5面试题--redis

慢查询⽇志&#xff1a;⽤于记录执⾏时间超过给定时⻓的命令请求&#xff0c;⽤户可以通过这个功能产⽣的⽇志来监视和 优化查询速度。 布隆过滤器&#xff1a;⼆进制数组进⾏存储&#xff0c;若判断元素存在则可能实际存在&#xff0c;若判断不存在则⼀定不存在。 redis中inc…

C语言——一个数如果恰好等于它的因子之和,这个数就称为“完全数”。

一个数如果恰好等于它的因子之和,这个数就称为“完全数”。例如,6的因子是 1、2、3,而6123。因此6是一个完全数。编程找出 1000 之内的所有完全数。 #include <stdio.h> int main() {int i, j, sum;for (i 1; i < 1000; i) {sum 0; //这一步很重要&#xff0c;每…

Ubuntu:安装Powershell

Powershell的安装与使用&#xff1a; 1&#xff09;安装Powershell&#xff1a;在终端依次运行以下命令即可&#xff1a; $ sudo apt-get update $ sudo apt-get install -y wget apt-transport-https software-properties-common $ wget -q "https://packages.microsof…

【Linux驱动开发】环境搭建Linux驱动开发环境

环境搭建Linux驱动开发环境 1. 简单描述2. 资源3. 安装4. 基本操作和设置 1. 简单描述 基于讯为电子rk3568教程 2. 资源 下载 VMware Workstation Pro 17 链接 Ubuntu 桌面版&#xff08;64位&#xff09; 链接 3. 安装 需要选择自定义硬件&#xff08;内存大于16g 硬盘500g…

java: Internal error in the mapping processor: java.lang.NullPointerException

启动java项目出错&#xff0c;其他人工程没有问题&#xff0c;别着急。 java: Internal error in the mapping processor: java.lang.NullPointerException at org.mapstruct.ap.internal.processor.DefaultVersionInformation.createManifestUrl(DefaultVersionInformation.j…

御云出海记|巴西市场,数字化转型与地区增长的新篇章

在11月的阳光下&#xff0c;巴西圣保罗的热情与活力成为了南半球市场的缩影&#xff0c;尤其是在华为云巴西峰会上。 云峰会亮点 11月22日&#xff0c;圣保罗举办的华为云巴西峰会成为了当地科技界的焦点。此次峰会聚集了数百位政府官员、行业领袖、专家学者&#xff0c;共同讨…

Facebook的这份开源协议使React四面楚歌

如果你觉得一些科技公司看起来很美好&#xff0c;每天都在“改变世界”……你应该看看他们的用户条款和法律文书&#xff0c;藏污纳垢之严重令人震惊。 最近&#xff0c;百度和阿里巴巴内部的软件工程团队不约而同做了一件事——弃用 React。 解释下&#xff1a; React 是一个…