【用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.rhkb.cn/news/204334.html

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

相关文章

java三大集合类--List

List Set Map 一、List 几个小问题&#xff1a; 1、接口可以被继承吗&#xff1f;&#xff08;可以&#xff09; 2、接口可以被多个类实现吗&#xff1f;&#xff08;可以&#xff09; 3、以下两种写法有什么区别&#xff1f; //List list1new List();是错误的因为List()…

ZKP15.2 Formal Methods in ZK (Part I)

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 15: Secure ZK Circuits via Formal Methods (Guest Lecturer: Yu Feng (UCSB & Veridise)) 15.2 Formal Methods in ZK (Part I) Circuits Workflow Source Code: Witness Generation and ConstraintsWitness Generatio…

Java零基础——SpringMVC篇

1.SpringMVC介绍 SpringMVC是Spring框架中的一个组件&#xff0c;是一个轻量级的web的MVC框架&#xff0c;充当controller,其本质就是一个Servlet。 1.1 传统Servlet的不足 每个请求&#xff0c;都需要定义一个Servlet。虽然可以在service方法中&#xff0c;根据业务标识进行…

HCIP---MPLS---LDP

文章目录 目录 文章目录 前言 一.LDP基本工作机制 LDP工作原理概述 LDP对等体&#xff1a; 二.本地LDP会话自动建立过程 三.LDP优化 PHP机制&#xff1a; 四.LDP配置 总结 前言 MPLS 基于标签转发表进行转发&#xff0c;与路由表类似&#xff0c;标签转发表有两种获取渠道&a…

【Rust】快速教程——自定义类型、数字转枚举、Cargo运行

前言 超过一定的年龄之后&#xff0c;所谓人生&#xff0c;无非是一个不断丧失的过程而已。宝贵的东西&#xff0c;会像梳子豁了齿一样从手中滑落下去。你所爱的人会一个接着一个&#xff0c;从身旁悄然消逝。——《1Q84》 \;\\\;\\\; 目录 前言自定义类型数字转枚举Cargo.tom…

【LeetCode刷题-链表】--86.分隔链表

86.分隔链表 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ class…

前端学习--React(3)

一、Redux 集中状态管理工具&#xff0c;不需要react即可使用&#xff0c;每个store的数据都是独立于组件之外的 vue小链接&#xff1a;vuex/pinia 基本使用 Redux将数据修改流程分成三个概念&#xff0c;state、action和reducer state - 一个对象 存放我们管理的数据状态 a…

某东大厂面试js手写题【手写代码附带注释,放心食用,博主亲测】

文章目录 前言js实现push方法js实现订阅发布手写防抖节流手写reduce方法深拷贝es5去重数组多维数组去重排序简单递归实现树形结构输出遍历后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;前端面试 &#x1f431;‍&#x1f453;博主在前…

Linux僵死进程及文件操作

1.僵死进程(僵尸进程)&#xff1a; 1.僵死进程产生的原因或者条件: 什么是僵死进程? 当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程. 简而言之,就是子进程先结束,并且父进程没有获取它的退出码; 那么僵死进程产生的原因或者条件就是:子进…

直接插入排序和希尔排序

前言 我们前面几期介绍了线性和非线性的基本数据结构。例如顺序表、链表、栈和队列、二叉树等~&#xff01;本期和接下来的几期我们来详解介绍各个排序的概念、实现以及性能分析&#xff01; 本期内容 排序的概念以及其运用 常见的排序算法 直接插入排序 希尔排序 一、排序的…

vue2项目从0搭建(三):配置环境变量及对应的webpack配置

前言 实际业务开发中,一个项目很可能会同时配置好几套环境。 比如:常规开发环境,开发测试环境,正式的测试环境,预发测试环境,客户甲的生产环境,客户乙的生产环境,通用生产环境,独立应用环境,微前端环境,大屏专用环境,移动端环境。 一女多嫁的实际业务场景,就需要我们进行多样…

安卓用SQLite数据库存储数据

什么是SQLite&#xff1f; SQLite是安卓中的轻量级内置数据库&#xff0c;不需要设置用户名和密码就可以使用。资源占用较少&#xff0c;运算速度也比较快。 SQLite支持&#xff1a;null&#xff08;空&#xff09;、integer&#xff08;整形&#xff09;、real&#xff08;小…

第29期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

Linux篇:文件系统

一、共识原理&#xff1a; 文件文件内容文件属性 磁盘上存储文件存文件的内容&#xff08;数据块&#xff09;存文件的属性&#xff08;inode&#xff09; Linux的文件在磁盘中存储是将属性和内容分开存储的。 二、硬件简述&#xff1a; 1. 认识硬件 磁盘&#xff1a;唯一的一…

混合云案例:利用 Databend Cloud 高效加速私有 Databend 的策略与实施

背景 Databend 是一款基于对象存储的存算分离湖仓产品&#xff0c;已成为云上大数据分析中高效且低成本的首选解决方案。目前&#xff0c;Databend 在多个用户场景中得到广泛应用&#xff0c;包括&#xff1a; 新媒体行业数据分析及大屏数据展示云上 CDH 替代以减少本地磁盘和…

Deep Image Prior

深度图像先验 论文链接&#xff1a;https://sites.skoltech.ru/app/data/uploads/sites/25/2018/04/deep_image_prior.pdf 项目链接&#xff1a;https://github.com/DmitryUlyanov/deep-image-prior Abstract 深度卷积网络已经成为一种流行的图像生成和恢复工具。一般来说&a…

web:[ZJCTF 2019]NiZhuanSiWei1

题目 点进题目&#xff0c;网页显示如下&#xff0c;需要代码审计 $_GET["text"]和$_GET["file"]来获取传入的两个参数text和file。使用isset()函数来检查$text变量是否已设置并且不为null。如果设置了并且不为null&#xff0c;则执行下面的逻辑。在下面的…

汽车电子 -- 车载ADAS之LCA(变道辅助系统)

相关法规文件: LCA: ISO 17387-2008 Intelligent transport systems — Lane change decision aid systems 一、变道辅助系统 LCA &#xff08;Lane Change Assist&#xff09; LCA 系统&#xff08;变道辅助系统&#xff09;监测后方相邻车道区域&#xff0c;如果有车辆在后…

《融合SCADA系统数据的天然气管道泄漏多源感知技术研究》误报数据识别模型开发

数据处理不作表述。因为我用的是处理后的数据&#xff0c;数据点这。 文章目录 工作内容1CC040VFD电流VFD转速压缩机转速反馈进出口差压 紧急截断阀开到位进出电动阀开到位发球筒电筒阀开到位收球筒电动阀开到位电动阀2005开到位越站阀开到位 工作内容2工作内容3 工作内容1 任…

Java小游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayLis…