1.实现创建水晶并且能与水晶进行交换位置的能力

创建好水晶的预制体,添加动画控制器,传入待机和爆炸的动画

创建Crystal_Skill_Control脚本:

挂载在水晶预制体上

    private float crystalExstTime;//水晶存在时间

    public void SetupCrystal(float _crystalDuration)
{
crystalExstTime = _crystalDuration;
}

    private void Update()
{
crystalExstTime -= Time.deltaTime;

        if(crystalExstTime < 0 )
{
SelfDestroy();//超时自毁
}
}

    public void SelfDestroy() => Destroy(gameObject);

创建Crystal_Skill脚本:

挂载在技能管理器上,并在SkillManage脚本上初始化

    [SerializeField] private float crystalDuration;//传入上面的控制脚本
[SerializeField] private GameObject crystalPrefab;//预制体
private GameObject currentCrystal;

    public override void UseSkill()
{
base.UseSkill();

        if(currentCrystal==null)//不存在则创建
{
currentCrystal =Instantiate(crystalPrefab,player.transform.position,Quaternion.identity);

            Crystal_Skill_Control newcrystalScript= currentCrystal.GetComponent<Crystal_Skill_Control>();

            newcrystalScript.SetupCrystal(crystalDuration);

        }
else//如果场上有水晶则传送玩家并销毁水晶
{
player.transform.position = currentCrystal.transform.position;

            Destroy(currentCrystal);
}
}

Player脚本:

        if(Input.GetKeyDown(KeyCode.F)) //update中
{
skill.crystal.CanbeUsed();
}

2.实现水晶爆炸和变大的功能

给水晶爆炸动画选取中间一帧调用伤害函数,在结束添加帧事件调用自毁函数

动画控制器添加触发Explode

Crystal_Skill_Control脚本:

 private Animator anim  =>GetComponent<Animator>();//获取碰撞器和动画器
private CircleCollider2D cd =>GetComponent<CircleCollider2D>();

private bool canExplode;//是否可以爆炸
private bool canMove;//是否可以移动
private bool canGrow=false;//是否可以变大

 private float moveSpeed;
private float growSpeed=5f;//增大速度

    public void SetupCrystal(float _crystalDuration,bool _canExplode,bool _canMove,float _moveSpeed)
{
crystalExstTime = _crystalDuration;
canExplode = _canExplode;
canMove = _canMove;
moveSpeed = _moveSpeed;

    }

        if(canGrow)//update()中
{
transform.localScale = Vector2.Lerp(transform.localScale,new Vector3(3,3),growSpeed*Time.deltaTime);//变大

        }

    public void AnimationExplodeEvent()//伤害事件
{
Collider2D[] collider2Ds = Physics2D.OverlapCircleAll(transform.position,cd.radius);//用碰撞器的半径

        foreach (var hit in collider2Ds)
{
if (hit.GetComponent<Enemy>() != null)
{
hit.GetComponent<Enemy>().Damage();
}
}
}

    public  void FinishCrystal()
{
if (canExplode)//如果可以爆炸
{
canGrow = true;//设置变大
anim.SetTrigger("Explode");//播放爆炸动画
}
else
{
SelfDestroy();
}
}

Crystal_Skill脚本:

    [Header("Explode crystal")]
[SerializeField] private bool canExplode;


    [Header("Moving crystal")]
[SerializeField] private bool canMove;
[SerializeField] private float moveSpeed;

        else//修改
{
Vector2 playerPos= player.transform.position;

            player.transform.position = currentCrystal.transform.position;

            currentCrystal.transform.position = playerPos;//交换水晶与玩家

            currentCrystal.GetComponent<Crystal_Skill_Control>().FinishCrystal();
}

3.实现水晶的移动

Skill脚本:

    protected virtual Transform FindClosetEnemy(Transform _checkTransform)//这是之前写克隆攻击时用到的代码,现将它放在skill上,用于找到指定组件附近最近的敌人
{
Collider2D[] collider2Ds = Physics2D.OverlapCircleAll(_checkTransform.position, 25);
float closestEnemyDistance = Mathf.Infinity;
Transform closestEnemy = null;
foreach (var hit in collider2Ds)
{

            if (hit.GetComponent<Enemy>() != null)
{
float distanceToEnemy = Vector2.Distance(_checkTransform.position, hit.transform.position);

                if (distanceToEnemy < closestEnemyDistance)
{
closestEnemyDistance = distanceToEnemy;
closestEnemy = hit.transform;
}
}
}

        return closestEnemy;
}

自行修改克隆攻击脚本中的一些代码

Crystal_Skill_Control脚本:

private Transform closestTarget;//最近的敌人目标

        if (canMoveToEnemy)
{
transform.position =Vector2.MoveTowards(transform.position,closestTarget.position,moveSpeed*Time.deltaTime);//移动

            if(Vector2.Distance(transform.position,closestTarget.position)<1f )//距离小于1时自毁
{
FinishCrystal();
canMoveToEnemy = false;
}
}

Crystal_Skill脚本:

        if(currentCrystal==null)
{
currentCrystal =Instantiate(crystalPrefab,player.transform.position,Quaternion.identity);

            Crystal_Skill_Control newcrystalScript= currentCrystal.GetComponent<Crystal_Skill_Control>();

            newcrystalScript.SetupCrystal(crystalDuration,canExplode,canMoveToEnemy,moveSpeed,FindClosetEnemy(currentCrystal.transform));//传入上面函数返回的最近敌人

        }
else
{
if (canMoveToEnemy)//水晶移动时不可以换位
{
return;
}

            Vector2 playerPos= player.transform.position;

            player.transform.position = currentCrystal.transform.position;

            currentCrystal.transform.position = playerPos;

            currentCrystal.GetComponent<Crystal_Skill_Control>().FinishCrystal();
}

4.实现多晶体

玩家可以拥有多个晶体并且可以一次性使用它们

Crystal_Skill脚本:


    [Header("Multi Stacking crystal")]
[SerializeField] private bool canMultiStack;//是否可以使用多晶体
[SerializeField] private int amountofCrystal;//晶体数量
[SerializeField] private float MultiCrystalCooldown;//冷却时间
[SerializeField] private List<GameObject> crystalLeft=new List<GameObject>();//预备储存晶体的列表

        if(canMultiCrystal())//update中
{
return;
}

 private bool canMultiCrystal()//是否能够发射多晶体
{
if(canMultiStack)
{
if(crystalLeft.Count>0)//如果列表里有晶体
{
cooldown = 0;//可以连发
GameObject crystaclToSpawn = crystalLeft[crystalLeft.Count-1];//取最后一个晶体
GameObject newCrystal =Instantiate(crystaclToSpawn,player.transform.position,Quaternion.identity);//生成

             crystalLeft.Remove(crystaclToSpawn);//从列表中移除
Crystal_Skill_Control newcrystalScript = newCrystal.GetComponent<Crystal_Skill_Control>();

             newcrystalScript.SetupCrystal(crystalDuration, canExplode, canMoveToEnemy, moveSpeed, FindClosetEnemy(newCrystal.transform));

             if(crystalLeft.Count<=0)//无晶体重新填装
{
cooldown = MultiCrystalCooldown;//设置冷却
RefillCrystal();
}


             return true;
}
}
return false;
}

    public void RefillCrystal()//填装晶体
{
for(int i = 0;i<amountofCrystal;i++)
{
crystalLeft.Add(crystalPrefab);
}
}

5.实现发射晶体的时间窗口

即当玩家只发射一颗晶体时,经过一定时间后也会进入冷却并重新填装晶体

Crystal_Skill脚本:

[SerializeField] private float useTimeWindow;//延迟窗口时间

    public void RefillCrystal()
{
int  amountToAdd=amountofCrystal-crystalLeft.Count;//确保填装数等于设定的数
for(int i = 0;i<amountToAdd;i++)
{
crystalLeft.Add(crystalPrefab);
}
}

    private void ResetAbility()//重置
{
if (coolDownTime > 0)//如果已经在冷却则返回
return;

        cooldown = MultiCrystalCooldown;
RefillCrystal();
}

 if(crystalLeft.Count>0)
{
if(amountofCrystal==crystalLeft.Count)//当发射出第一颗时延迟调用
{
Invoke("ResetAbility", useTimeWindow);
}

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

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

相关文章

在vscode 如何运行a.nut 程序(Squirrel语言)

在 VS Code 中运行 Squirrel 语言编写的 .nut 程序&#xff0c;需要先配置 Squirrel 运行环境并安装相关插件&#xff0c;具体步骤如下&#xff1a; 一、安装 Squirrel 解释器 Squirrel 程序需要通过其官方解释器 squirrel 或 sq 执行&#xff0c;首先需要安装解释器&#xf…

【数据结构】生活中的数据结构:从吃饭与编程看栈与队列思维

生活中的数据结构&#xff1a;从吃饭与编程看栈与队列思维 在软件开发的世界里&#xff0c;栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;是两种基础的数据结构&#xff0c;它们以不同的顺序管理数据&#xff1a;栈遵循后进先出&#xff08;LIFO&#x…

牛客——接头密匙

题目链接&#xff1a;牛客--接头密匙 该题是一个很显然的前缀树问题&#xff0c;只需要构建a中所有数组对应的前缀树&#xff0c;之后求b所处前缀个数即可。关于前缀树的构建&#xff0c;可以观看左老师算法讲解045的视频&#xff0c;简单来讲就是用特殊字符将实际数据隔开&…

【Linux基础知识系列】第六十三篇 - 文件编辑器基础:vim

在 Linux 系统中&#xff0c;文本编辑器是系统管理员和开发人员不可或缺的工具。vim 是一个功能强大的文本编辑器&#xff0c;广泛应用于 Linux 系统中。它支持多种编辑模式&#xff0c;提供了丰富的文本编辑功能&#xff0c;适用于编写代码、配置文件和文档。掌握 vim 的基本使…

音频驱动的视觉特效:粒子、动画与Shader的融合技术

音频驱动视觉效果的实现与应用1. 引言在互动媒体、游戏和数字艺术领域&#xff0c;音频数据实时控制视觉元素已成为核心技术&#xff0c;它能创造沉浸式体验&#xff0c;增强用户参与感。例如&#xff0c;音乐会可视化或VR游戏中&#xff0c;音频信号驱动粒子流动、动画变化和S…

机器学习环境配置

【终极指南】吃透机器学习环境配置&#xff1a;从Conda、CUDA到Docker容器化 大家好&#xff01;在机器学习的旅程中&#xff0c;一个稳定、可复现的环境是成功的基石。 第一部分&#xff1a;核心理念——为何环境配置如此重要&#xff1f; 任何机器学习模型的运行&#xff0c;…

【14】大恒相机SDK C#开发 ——Bitmap.UnlockBits()什么意思?有什么用?bmpData.Scan0;什么意思?有什么用?

文章目录1 Bitmap.UnlockBits()2 bmpData.Scan01 Bitmap.UnlockBits() 在 C# 中&#xff0c;Bitmap.UnlockBits() 方法的作用是解锁通过 Bitmap.LockBits() 方法锁定的位图数据&#xff0c;并释放相关的位图数据结构。 当你使用 Bitmap.LockBits() 方法锁定位图数据时&#x…

什么是doris

文章目录简介使用场景Apache Doris 主要应用于以下场景&#xff1a;实时数据分析&#xff1a;湖仓融合分析&#xff1a;半结构化数据分析&#xff1a;Apache Doris 的核心特性详细请看官方文档&#xff1a; Apache Doris介绍简介 Apache Doris 是一款基于 MPP 架构的高性能、实…

python+pyside6的简易画板

十分简单的一个画板程序&#xff0c;用QLabel控件作为画布&#xff0c;在画布上可以画出直线、矩形、填充矩形、园&#xff0c;椭园、随手画、文本等内容。将原先发布的画板程序中的画文本方法修改成了原位创建一编辑框&#xff0c;编辑框失去焦点后&#xff0c;即将文本画在画…

【数据可视化-76】从释永信被查,探索少林寺客流量深度分析:Python + Pyecharts 炫酷大屏可视化(含完整数据和代码)

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

WPF TreeView自带自定义滚动条

放在TreeView.Resources中&#xff1a;<Style TargetType"ScrollBar"><Setter Property"Stylus.IsPressAndHoldEnabled" Value"false"/><Setter Property"Stylus.IsFlicksEnabled" Value"false"/><Set…

MongoDB 详细用法与 Java 集成完整指南

MongoDB 详细用法与 Java 集成完整指南 目录 MongoDB 基础概念MongoDB 安装与配置MongoDB Shell 基本操作Java 环境准备Java MongoDB 驱动集成连接配置基本 CRUD 操作高级查询操作索引操作聚合管道事务处理Spring Boot 集成最佳实践 1. MongoDB 基础概念 1.1 核心概念对比 …

【Flutter3.8x】flutter从入门到实战基础教程(四):自定义实现一个自增的StatefulWidget组件

fluttet中实现一个自定义的StatefulWidget组件&#xff0c;可以在数据变化后&#xff0c;把最新的页面效果展示给客户 实现效果实现代码 pages文件夹下新加一个counter_page.dart文件 class CounterPage extends StatefulWidget {const CounterPage({super.key});overrideState…

[AI8051U入门第十三步]W5500实现MQTT通信

前言 学习目标: 1、学习MQTT协议 2、了解MQTT数据帧格式 3、自己编写MQTT程序 4、调试MQTT程序一、MQTT协议介绍 MQTT(Message Queuing Telemetry Transport) 是一种轻量级的 发布/订阅(Pub/Sub) 消息传输协议,专为 低带宽、高延迟或不可靠网络 环境设计,广泛应用于 物…

四、基于SpringBoot,MVC后端开发笔记

整合第三方技术&#xff1a; 1、整合Junit (1)名称&#xff1a;SpringBootTest (2)类型&#xff1b;测试类注解 (3)位置&#xff1a;测试类定义上方 (4)作用&#xff1a;设置Junit加载的SpringBoot启动类 (5)相关属性&#xff1a;classes&#xff1a;设置SpringBoot启动类 2、整…

深入讲讲异步FIFO

一、异步 FIFO 的基本概念1.1 定义与核心作用异步 FIFO&#xff08;Asynchronous FIFO&#xff09;是一种读写时钟完全独立的先进先出&#xff08;First-In-First-Out&#xff09;数据缓冲器&#xff0c;主要用于跨时钟域数据传输场景。在数字系统中&#xff0c;当两个模块工作…

linux81 shell通配符:[list],‘‘ ``““

shell 文件处理工具 grep 别名显示颜色 grep --colorauto ‘root’ passwd alias grep‘grep --colorauto’ vim /etc/bashrc alias grep‘grep --colorauto’ source /etc/bashrc [rootsamba tmp]# grep --colorauto root 2.txt root:x:0:0:root:/root:/bin/bash operator:x:1…

CMake、CMakeLists.txt 基础语法

前言 代码变成可执行文件&#xff0c;叫做编译&#xff08;compile&#xff09;&#xff1b;先编译这个&#xff0c;还是先编译那个&#xff08;即编译的安排&#xff09;&#xff0c;叫做构建&#xff08;build&#xff09;。CMake是最常用的构建工具&#xff0c;诞生于1977年…

《文明5》错误代码0xc0000142修复方法

只要是错误代码为0xc0000142&#xff1f;不管是哪种错误&#xff0c;都是一样的。 修复方法有很多&#xff0c;我先推荐个人认为比较好用的修复方法 方式一&#xff1a;第三方软件修复&#xff1a; 地址在这里获取&#xff1a;修复软件点这里 添加图片注释&#xff0c;不超过 …

【Java面试题】缓存穿透

什么是缓存穿透 缓存穿透是指当秒杀请求在Redis中未命中缓存时&#xff0c;系统会转而查询数据库。若数据库中也不存在该数据&#xff0c;大量此类请求将直接冲击数据库&#xff0c;造成数据库负载激增。解决方案 缓存空值 当我们查询数据库发现数据库当中也不存在该数据时&…