【unity之IMGUI实践】敌方逻辑封装实现【六】

👨💻个人主页:@元宇宙-秩沅
👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 秩沅 原创
👨💻 收录于专栏:unityUI专题篇

⭐通用API实现抽象行为封装【五】⭐
文章目录
- ⭐通用API实现抽象行为封装【五】⭐
- 🎶前言
- 🎶(==A==)UML
- 🎶(==B==)需求分析
- 🎶(==C==)行为实现——炮台的自动检测并攻击
- 🎶(==D==)行为实现——敌军坦克的移动路线和检测攻击
- 总结:
🎶前言


🅰️
🎶(A)UML

🎶(B)需求分析


🎶(C)行为实现——炮台的自动检测并攻击

😶🌫️:步骤实现
1.炮台的行为逻辑封装:旋转,触发检测,发射炮弹及特效
2.检测玩家后自动瞄准攻击
3.玩家扣血,更新血条,触发保护罩特效及死亡
——————————————
涉及到四个脚本
炮台封装
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 炮台的行为逻辑实现
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class battery : TankFather
{public AudioSource shootMusic; //发射音效public GameObject shootball; //发射的子弹类型public float shootSpeed = 1000f; //子弹的速度 public Transform shootTransform; //发射的组件信息public bool shootSwitch = false;//射击检测参数public Transform player; //闯入者private float endTime = 8f; //子弹发射间隔的时间private void Start(){//属性初始化赋值Head = transform.GetChild(0);maxBlood = 500;nowBlood = 500;attack = 20; HeadSpeed = 50;//射击音效关闭shootMusic.enabled = false;}private void Update(){ if (shootSwitch == false) //不停的旋转{Head.transform.Rotate(Vector3.up * HeadSpeed * Time.deltaTime);} else {Head.transform.LookAt(player);//倒计时发射子弹endTime = Mathf.MoveTowards(endTime, 0, 0.1f);if(endTime <= 0){Fire();endTime = 3f;}} }//玩家进入范围内就开始射击private void OnTriggerEnter(Collider other){if(other.tag == "Player"){shootSwitch = true;player = other.transform;}}//受伤检测private void OnTriggerStay(Collider other){float off = Vector3.Distance(other.transform.position, transform.position);if (other.gameObject.tag == "bullet" && off < 2){//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合BulletMove ball = other.gameObject.GetComponent<BulletMove>();TankFather ballTank = ball.Tank.GetComponent<TankFather>();//当子弹不是自己打的到自己身上的时候if (ballTank.tag != gameObject.tag){//扣血Heart(ballTank);}}}//玩家出去后就停止射击private void OnTriggerExit(Collider other){if (other.tag == "Player"){shootSwitch = false;}}//开火重写public override void Fire(){//开启射击音效shootMusic.enabled = true;shootMusic.Play();GameObject ball = Instantiate(shootball, shootTransform.position , shootTransform.rotation);BulletMove movScript = ball.GetComponent<BulletMove>();Rigidbody shootBall = ball.GetComponent<Rigidbody>();shootBall.AddForce(shootTransform .transform.forward * shootSpeed );movScript.Tank =gameObject ; //声明子弹是由谁打出去的}}
坦克基类更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能: 坦克基类——集中子类相同点
//___________创建者:______秩沅______
//___________________________________
//-------------------------------------
public abstract class TankFather : MonoBehaviour
{//攻击和防御相关public int attack;public int defence; public float nowBlood;public float maxBlood;//移动和转速相关public int moveSpeed;public int RotateSpeed;public int HeadSpeed;public Transform Head;//击败特效public GameObject diedEffect;//收到伤害打开保护罩的特效public GameObject ProtectEffectMain;public GameObject ProtectEffectOther;private void Awake(){// ProtectEffectMain = Resources.Load<GameObject>(@"Prefabs/OherResoure/Protect1");// ProtectEffectOther = Resources.Load<GameObject>(@"Prefabs/OherResoure/Protect2");}//受伤行为public virtual void Heart(TankFather other){//当攻击力大于防御力时才生效if (other.attack - defence > 0){nowBlood -= (other.attack - defence);}if (nowBlood <= 0){nowBlood = 0;Death();}if (gameObject.tag == "Player")//如果是主玩家才更新血条{//更新血条GamePlane.SingleInstance.UpdataBlood(maxBlood, nowBlood);//实例化保护罩的特效 GameObject eff = Instantiate(ProtectEffectMain, transform.position, transform.rotation);Destroy(eff,1f);}}//死亡行为public virtual void Death(){//将特效实例化相关逻辑GameObject effect = Instantiate(diedEffect, this.transform.position ,this.transform.rotation);AudioSource soudClip = effect.GetComponent<AudioSource>();soudClip.enabled = MusicContol.SingleMusicContol.nowMusicData.soundSwitch;soudClip.volume = MusicContol.SingleMusicContol.nowMusicData.soundRoll ;soudClip.mute = false;soudClip.playOnAwake = true;//死亡后展示死亡面板if (gameObject.tag == "Player"){Destroy(gameObject, 2F);DiedPlane.SingleInstance.Show();}elseDestroy(gameObject);}//开火行为public abstract void Fire(); //子类中每一个的开火方式都不同,作为抽象方法}
主坦克类更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能: 坦克的移动和旋转
//___________创建者:_______秩沅_______
//_____________________________________
//-------------------------------------
public class MainTank : TankFather
{//主坦克专有特征public Weapon nowWeapon;//特征属性初始化private void Awake(){Head = transform.GetChild(1).GetChild(0);maxBlood = 1000;nowBlood = 1000;attack = 30;defence = 10;moveSpeed = 5;RotateSpeed = 50;HeadSpeed = 500;}private void Update(){//坦克的移动 = 大小*方向transform.Translate(Input.GetAxis("Vertical") *Vector3.forward*moveSpeed *Time.deltaTime );//坦克的旋转 = 大小*轴向transform.Rotate(Input.GetAxis("Horizontal") *Vector3.up *RotateSpeed *Time .deltaTime );//头部炮管的旋转 = 大小*轴向Head.Rotate(Input.GetAxis ("Mouse X") *Vector3.up*HeadSpeed*Time .deltaTime );//左键发射炮弹if(Input.GetMouseButtonDown(0)){Fire();}}//捡武器行为public void ChangeWeapon(GameObject weapon){if (nowWeapon != null) nowWeapon.Vanish(); //销毁当前武器nowWeapon = weapon.GetComponent<Weapon>(); //头部留有存放武器的位置weapon.gameObject.transform.position = Head.GetChild(0).transform.position ;weapon.gameObject.transform.rotation = Head.GetChild(0).transform.rotation;weapon.gameObject.transform.SetParent(Head.GetChild(0));attack += nowWeapon.attack;}//开火行为重写public override void Fire() {nowWeapon.Shoot(); }//被子弹打到private void OnTriggerEnter(Collider other){if(other.tag == "bullet"){try{//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合BulletMove ball = other.GetComponent<BulletMove>();TankFather ballTank = ball.Tank.GetComponent<TankFather>();//当子弹不是自己打的到自己身上的时候if (ballTank.tag != "Player"){//扣血Heart(ballTank);}}catch{throw;}}}}
子弹发射更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 子弹的逻辑相关
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class BulletMove : MonoBehaviour
{public GameObject Tank; //挂载在哪个坦克上public GameObject DeidEffect;public AudioSource distorySound; //销毁的音效private void Start(){}//子弹的销毁及特效private void OnTriggerEnter(Collider other){if (other.CompareTag("Environment")|| other.CompareTag("Enemy")){if (DeidEffect != null){GameObject eff = Instantiate(DeidEffect, transform.position, transform.rotation);//音效控制distorySound = eff.GetComponent<AudioSource>();distorySound.enabled = MusicContol.SingleMusicContol.nowMusicData.soundSwitch;distorySound.volume = MusicContol.SingleMusicContol.nowMusicData.soundRoll;eff.AddComponent<SelfDestroy>();}Destroy(this.gameObject,2f); } }}
🎶(D)行为实现——敌军坦克的移动路线和检测攻击

😶🌫️:步骤实现
- 1.指定移动位置,设置朝向
- 2.行为逻辑封装。开火,受伤
- 3.自动检测闯入者
———— --------------————
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能:敌方坦克逻辑封装
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class EnemyTank:TankFather
{//随机移动点的位置数组public Transform[] randomPosition;//目标位置private Transform target;//目标坦克public Transform Player;//检测范围public float distance = 10f;public AudioSource shootMusic; //发射音效public GameObject shootball; //发射的子弹类型public float shootSpeed = 1000f; //子弹的速度 public Transform[] shootTransform; //发射的组件信息public bool shootSwitch = false; private float endTime = 3f; //子弹发射间隔的时间private void Start(){//属性初始化赋值maxBlood = 500;nowBlood = 500;attack = 30;HeadSpeed = 50;//射击音效关闭shootMusic.enabled = false;moveSpeed = 10f;//先随机整一个目标点RandomPosition();}private void Update(){ transform.LookAt(target);//始终超自己的正方向移动transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); //当距离差不多相等时,再随机目标点if(Vector3.Distance(transform .position ,target .position)< 0.5f){RandomPosition();}//范围检测if (Vector3 .Distance(transform .position ,Player.position )<= distance && Player !=null ){//炮口瞄准玩家Head.transform.LookAt(Player);//倒计时发射子弹endTime = Mathf.MoveTowards(endTime, 0, 0.1f);if (endTime <= 0){Fire();endTime = 3f;} }}//随机指向一个移动点public void RandomPosition(){if (randomPosition.Length != 0)target = randomPosition[Random.Range(0, randomPosition.Length)];}//触发检测private void OnTriggerEnter(Collider other){if (other.gameObject.tag == "bullet" ){//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合BulletMove ball = other.gameObject.GetComponent<BulletMove>();TankFather ballTank = ball.Tank.GetComponent<TankFather>();//当子弹不是自己打的到自己身上的时候if (ballTank.tag != gameObject.tag){//扣血Heart(ballTank);}}}public override void Fire(){//开启射击音效shootMusic.enabled = true;shootMusic.Play();for (int i = 0; i < shootTransform.Length ; i++){GameObject ball = Instantiate(shootball, shootTransform[i].position, shootTransform[i].rotation);BulletMove movScript = ball.GetComponent<BulletMove>();Rigidbody shootBall = ball.GetComponent<Rigidbody>();shootBall.AddForce(shootTransform[i].transform.forward * shootSpeed);movScript.Tank = gameObject; //声明子弹是由谁打出去的}}}
问题:
1.受到伤害,开启了保护罩但是不扣血
2.敌方坦克,原地打转,未按规定路线移动
解决:
1.子弹检测逻辑错误
2.位置空点绑定在对象身上变成了子对象因此无法达到效果
总结:

- 1.检测触发的方式:①触发器检测②向量距离检测
- 2.多点指定移动,加入向量距离判断,重合的机率小,故此不能 A物体距离 == B物体距离
- 3.子坦克继承了父类脚本,引用传递时直接用父类即可获得该子类,(原因父类名字相同,但是子类名字不同,无法确定,所以里氏替换作用在此体现)
⭐相关文章⭐
⭐【2023unity游戏制作-mango的冒险】-6.关卡设计
⭐【2023unity游戏制作-mango的冒险】-5.攻击系统的简单实现
⭐【2023unity游戏制作-mango的冒险】-4.场景二的镜头和法球特效跟随
⭐【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现
⭐【2023unity游戏制作-mango的冒险】-2.始画面API制作
⭐【2023unity游戏制作-mango的冒险】-1.场景搭建
⭐“狂飙”游戏制作—游戏分类图鉴(网易游学)
⭐本站最全-unity常用API大全(万字详解),不信你不收藏
你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!
相关文章:
【unity之IMGUI实践】敌方逻辑封装实现【六】
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:uni…...
llvm向用户抛出warning、error信息
1、抛出error信息并终止程序 使用DiagnosticInfoUnsupported可以向用户抛出error信息并且终止程序,效果如同report_fatal_error、Error。后端用法如下: void xxxx::reportErrorMsg(const MachineFunction &MF)const {const Function &F MF.ge…...
微服务学习笔记-----Nacos安装教程(Windows和Linux版本)
Nacos安装教程 Nacos安装指南1.Windows安装1.1.下载安装包1.2.解压1.3.端口配置1.4.启动1.5.访问 2.Linux安装2.1.安装JDK2.2.上传安装包2.3.解压2.4.端口配置2.5.启动 3.Nacos的依赖 Nacos安装指南 1.Windows安装 开发阶段采用单机安装即可。 1.1.下载安装包 在Nacos的Git…...
程序员面试系列,docker常见面试题
原文链接 什么是Docker?它的主要作用是什么?Docker和虚拟机之间有什么区别?Docker的主要组件有哪些?Docker镜像和容器的区别是什么?如何构建Docker镜像?请简要描述构建过程。如何创建和启动一个Docker容器…...
Linux centos7.x系统将/home磁盘分配给/
1.解除挂载并删除/home卷 umount /home如果出现以下报错 : 可以使用以下命令查看哪些进程在占用 fuser -mv /home杀死这些进程就行 kill -9 进程号然后再执行umount /home就可以成功了 , 同时执行以下命令把逻辑卷删除了 lvremove /dev/centos/home…...
根据数组元素为对象,对元素对象的某一属性进行排序
前言: 开发过程中,前端难免需要对数据进行操作,比如比较常见的操作就是对数组元素进行排序 对数组元素对基本类型的进行排序 const arr [2,4,1,3,9,5]arr.sort((a,b)>a-b) //[1, 2, 3, 4, 5, 9] arr.sort((a,b)>b-a) //[9, 5, 4, 3,…...
mysql(三)用户权限管理
目录 前言 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、删除用户 前言 为什么要设置用户权限? MySQL设置用户管理权限的主要目的是为了确保数据库的安全性和数据的机密性。以下是一些原因: 1. 安全性:MySQL是一个开源的关系型…...
字节JAVA岗位面试总结汇总
主要拷打了 redis+mysql+网络+系统+java+算法,面试问题主要集中在 mysql、redis、网络这三部门, Redis 相关 介绍一下redis数据库? Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 Redis…...
29-使用RocketMQ做削峰处理
1、初识RocketMQ 1.1、Apache 下载RocketMQ https://downloads.apache.org/rocketmq/ 1.2、RocketMQ官方网站 https://rocketmq.apache.org/zh/ 1.3、RocketMQ在GitHub文档 https://github.com/alibaba/spring-cloud-alibaba/wiki/RocketMQ 1.4、RocketMQ官方网站文档 …...
ELK 使用kibana查询和分析nginx日志
背景:使用kibana查询和分析nginx请求日志,方便开发人员查询系统日志和分析系统问题。 setp 1、定义Index patterns 2、定义Discover(Search 查询数据) 3、定义Visualizations 3.1 定义Vertical Bar 3.2 、Choose a source 3.3、定义图表 4、定义…...
mybatisplus自定义xml的sql语句进行自动分页
1、xxxMapper.xml定义 <select id"leftJoinPageList" resultMap"MonitoringDataResult"parameterType"com.ktt.carbon.verification.domain.bo.MonitoringDataBo">SELECT d.* from carbon_monitoring_data d LEFT JOIN carbon_monitoring…...
ChatGPT:人工智能开启智能交流新篇章
一、ChatGPT:智能交流的新里程碑 ChatGPT是OpenAI基于GPT技术的最新版本,采用深度学习模型,通过预训练和微调的方式,使其能够理解和生成自然语言,从而实现与人类更自然、流畅的对话和交流。 二、ChatGPT的技术原理与优…...
关于anki的一些思考
文章目录 通常情况下选择什么模板制卡?一张填空卡片的填空数量到底要多少才合适? 通常情况下选择什么模板制卡? 通常情况是指知识是以一段文字的形式呈现,而不是这些:单词、选择题、成语等(这些都可以定制…...
【动态规划刷题 1 】 第N个泰波那契数 三步问题
第N个泰波那契数 链接: 第N个泰波那契数 1137 . 第 N 个泰波那契数 泰波那契序列 Tn 定义如下: T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2 给你整数 n,请返回第 n 个泰波那契数 Tn 的值。 示例 1: 输入:…...
【踩坑】三种方式解决 Homebrew failing to install - fatal: not in a git directory
问题描述 解决方法一 添加安全目录,没有测试。 git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew- git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-cask 解决方法二 取消挂载这…...
零信任安全解决方案
什么是零信任 零信任网络架构 (ZTNA) 或零信任安全是一种新的组织网络安全方法。它旨在修复传统基于边界的安全性中的缺陷并简化网络设计。 它以“永不信任,始终验证”的原则运作。这意味着,无论用户或设备位于何处,…...
如何创建高级 CSS 下拉菜单
效果展示 实现思路及部分代码 1、定义整体页面结构 从上述的效果展示图可以看出,页面的整体结构应该需要一个总菜单容器来装载父级菜单项,并且对应的父级菜单项应该有对应的菜单子项。子菜单是分类的话,我们还需要额外在扩展对应的容器来装…...
java中判断list是否为空
java中判断list是否为空是日常代码中经常遇到的问题。最近发现一个Utils提供的方法可以一步判断。 废话不多说,直接上代码! ArrayList<String> arrayList new ArrayList<>(); System.out.println("集合1:" Collecti…...
龙芯3A5000板卡在高性能工作站的应用方案-迅为电子
将龙芯3A5000应用于高性能工作站时,可以考虑以下方案: 多核计算能力:龙芯3A5000拥有多核心处理器,具备强大的计算能力。在高性能工作站中,可以利用多核心的处理能力来支持复杂的工程设计、科学计算和数据处理任务。…...
WebSocket心跳机制
WebSocket是HTML5开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。 1、创建webSocket // Create WebSocket connection. const sock…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
Python的__call__ 方法
在 Python 中,__call__ 是一个特殊的魔术方法(magic method),它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时(例如 obj()),Python 会自动调用该对象的 __call__ 方法…...
