【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…...
Shiro RememberMe反序列化漏洞深度解析与实战利用
1. 这个漏洞不是“老古董”,而是理解Java安全边界的活教材很多人看到CVE-2016-4437,第一反应是“Shiro都淘汰了,还讲这个干啥?”——我去年在给一家做政企内部系统的客户做渗透复测时,就遇到过一个上线三年的审批平台&…...
BetterJoy完整配置指南:5分钟让Switch手柄在PC上完美运行
BetterJoy完整配置指南:5分钟让Switch手柄在PC上完美运行 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.c…...
Claude本地化部署终极方案(企业级容器化全栈手册):支持Anthropic API兼容、流式响应、模型热切换与RBAC权限隔离
更多请点击: https://codechina.net 第一章:Claude本地化部署的架构全景与企业级价值定位 Claude本地化部署并非简单地将模型权重下载后运行,而是一套融合推理引擎优化、安全沙箱隔离、API网关治理与可观测性集成的端到端架构体系。其核心目…...
第三卷第4章:原型模式设计思想
第三卷第4章:原型模式设计思想 目录介绍 01.案例引入与思考 1.1 痛点场景 1.2 它哪里不舒服 1.3 引出本篇主角 02.原型模式介绍 2.1 原型模式由来 2.2 原型模式定义...
WarcraftHelper终极指南:魔兽争霸3兼容性问题一站式解决方案
WarcraftHelper终极指南:魔兽争霸3兼容性问题一站式解决方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为《魔兽争霸3》在现代电…...
AI IDE 革命:程序员正在被重新定义
很多开发者第一次使用 Cursor 的 CtrlK 或 Composer(高级多文件编辑模式)时,都会有一种强烈的、甚至让人有些脊背发凉的冲击感。 因为: 它已经不再是那个我们熟悉的、只能在原地等待光标落下的: “代码自动补全插件&am…...
Unity塔防底层架构:ScriptableObject驱动的数据契约设计
1. 这不是“又一个塔防模板”,而是塔防开发的底层操作系统我第一次在Asset Store点开Tower Defense Toolkit 4(TDTK-4)的预览图时,下意识划走了——界面太“干净”了,没有炫酷的粒子特效演示,没有满屏飞舞的…...
对比不同模型在创意生成任务中的效果与token消耗差异
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比不同模型在创意生成任务中的效果与token消耗差异 在为一场创意大赛准备素材时,我们面临一个常见的选择:…...
使用libusb-win32驱动复活老旧USB硬件:以Elektor Magic Eye为例
1. 项目概述:让老硬件在新时代焕发新生手头有一台十多年前的《Elektor》杂志上刊登的“Magic Eye EM84”复古VFD显示屏项目,想把它接到Windows 10电脑上当个酷炫的CPU占用率显示器,却发现官方提供的“AVR309”USB驱动在新系统上彻底罢工了。这…...
机器学习力场攻克Peierls相变动力学:从对称性描述符到畴生长标度律
1. 项目概述:当机器学习遇见Peierls相变在凝聚态物理和材料科学的前沿,我们常常被一个核心问题所困扰:如何精确地模拟那些由电子和晶格(原子)强烈耦合所驱动的复杂动力学过程?这类系统,比如电荷…...
