Unity类银河恶魔城学习记录8-5 p81 Blackhole duration源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码、

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

Blackhole_Skill_Controller.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class Blackhole_Skill_Controller : MonoBehaviour
{
    [SerializeField] private GameObject hotKeyPrefab;
    [SerializeField] private List<KeyCode> KeyCodeList;

    private float maxSize;//最大尺寸
    private float growSpeed;//变大速度
    private float shrinkSpeed;//缩小速度
    private float blackholeTimer;

    private bool canGrow = true;//是否可以变大
    private bool canShrink;//缩小
    private bool canCreateHotKeys = true;专门控制后面进入的没法生成热键
    private bool cloneAttackReleased;


    private int amountOfAttacks = 4;
    private float cloneAttackCooldown = .3f;
    private float cloneAttackTimer;

    private List<Transform> targets = new List<Transform>();
    private List<GameObject> createdHotKey = new List<GameObject>();

    public bool playerCanExitState { get; private set; }

    
    public void SetupBlackhole(float _maxSize,float _growSpeed,float _shrinkSpeed,int _amountOfAttacks,float _cloneAttackCooldown,float _blackholeDuration)
    {
        maxSize = _maxSize;
        growSpeed = _growSpeed;
        shrinkSpeed = _shrinkSpeed;
        amountOfAttacks = _amountOfAttacks;
        cloneAttackCooldown = _cloneAttackCooldown;
        blackholeTimer = _blackholeDuration;
    }

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

        if(blackholeTimer <= 0)
        {
            blackholeTimer = Mathf.Infinity;//防止重复检测
            if (targets.Count > 0)//只有有target才释放攻击
            {
                ReleaseCloneAttack();//释放攻击
            }
            else
               
                FinishBlackholeAbility();//缩小黑洞
        }

        if (Input.GetKeyDown(KeyCode.R)&& targets.Count > 0)
        {
            ReleaseCloneAttack();
        }

        CloneAttackLogic();

        if (canGrow && !canShrink)
        {
            //这是控制物体大小的参数
            transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(maxSize, maxSize), growSpeed * Time.deltaTime);
            //类似MoveToward,不过是放大到多少大小 https://docs.unity3d.com/cn/current/ScriptReference/Vector2.Lerp.html
        }
        if (canShrink)
        {
            transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(0, 0), shrinkSpeed * Time.deltaTime);

            if (transform.localScale.x <= 1f)
            {
                Destroy(gameObject);
            }
        }
    }

    private void ReleaseCloneAttack()
    {
        cloneAttackReleased = true;
        canCreateHotKeys = false;

        DestroyHotKeys();
        PlayerManager.instance.player.MakeTransprent(true);
    }

    private void CloneAttackLogic()
    {
        if (cloneAttackTimer < 0 && cloneAttackReleased&&amountOfAttacks>0)
        {
            cloneAttackTimer = cloneAttackCooldown;

            int randomIndex = Random.Range(0, targets.Count);


            //限制攻击次数和设置攻击偏移量
            float _offset;

            if (Random.Range(0, 100) > 50)
                _offset = 1.5f;
            else
                _offset = -1.5f;
 
            SkillManager.instance.clone.CreateClone(targets[randomIndex], new Vector3(_offset, 0, 0));
            amountOfAttacks--;


            if (amountOfAttacks <= 0)
            {
                Invoke("FinishBlackholeAbility", 0.5f);
            }
        }
    }

    private void FinishBlackholeAbility()
    {
        DestroyHotKeys();
        canShrink = true;
        cloneAttackReleased = false;
        playerCanExitState = true;
        
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.GetComponent<Enemy>()!=null)
        {
            collision.GetComponent<Enemy>().FreezeTime(true);
            CreateHotKey(collision);
        }
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.GetComponent<Enemy>() != null)
        {
            collision.GetComponent<Enemy>().FreezeTime(false);
           
        }
    }

    private void CreateHotKey(Collider2D collision)
    {
        if(KeyCodeList.Count == 0)//当所有的KeyCode都被去除,就不在创建实例
        {
            return;
        }

        if(!canCreateHotKeys)//这是当角色已经开大了,不在创建实例
        {
            return;
        }
        
        //创建实例
        GameObject newHotKey = Instantiate(hotKeyPrefab, collision.transform.position + new Vector3(0, 2), Quaternion.identity);

        //将实例添加进列表
        createdHotKey.Add(newHotKey);


        //随机KeyCode传给HotKey,并且传过去一个毁掉一个
        KeyCode choosenKey = KeyCodeList[Random.Range(0, KeyCodeList.Count)];

        KeyCodeList.Remove(choosenKey);

        Blackhole_Hotkey_Controller newHotKeyScript = newHotKey.GetComponent<Blackhole_Hotkey_Controller>();

        newHotKeyScript.SetupHotKey(choosenKey, collision.transform, this);
    }
    public void AddEnemyToList(Transform _myEnemy)
    {
        targets.Add(_myEnemy);
    }

    //销毁Hotkey
    private void DestroyHotKeys()
    {

        if(createdHotKey.Count <= 0)
        {
            return;
        }
        for (int i = 0; i < createdHotKey.Count; i++)
        {
            Destroy(createdHotKey[i]); 
        }

    }
    
}

Blackhole_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Blackhole_Skill : Skill
{

    [SerializeField]private float maxSize;//最大尺寸
    [SerializeField] private float growSpeed;//变大速度
    [SerializeField] private float shrinkSpeed;//缩小速度

    [SerializeField] private GameObject blackholePrefab;
    [Space]

    [SerializeField] private float blackholeDuration;
    [SerializeField] int amountOfAttacks = 4;
    [SerializeField] float cloneAttackCooldown = .3f;


    



    Blackhole_Skill_Controller currentBlackhole;

    public override bool CanUseSkill()
    {
        return base.CanUseSkill();
    }

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

        GameObject newBlackhole = Instantiate(blackholePrefab,player.transform.position,Quaternion.identity);

        currentBlackhole = newBlackhole.GetComponent<Blackhole_Skill_Controller>();

        currentBlackhole.SetupBlackhole(maxSize,growSpeed,shrinkSpeed,amountOfAttacks,cloneAttackCooldown,blackholeDuration);
    }

    protected override void Start()
    {
        base.Start();
    }

    protected override void Update()
    {
        base.Update();
    }

    public bool SkillCompleted()
    {
        if(currentBlackhole == null)
         return false;
        if (currentBlackhole.playerCanExitState)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
Player.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Player : Entity
{
    [Header("Attack Details")]
    public Vector2[] attackMovement;//每个攻击时获得的速度组
    public float counterAttackDuration = .2f;
    


    public bool isBusy{ get; private set; }//防止在攻击间隔中进入move
    //
    [Header("Move Info")]
    public float moveSpeed;//定义速度,与xInput相乘控制速度的大小
    public float jumpForce;
    public float swordReturnImpact;//在player里设置swordReturnImpact作为击退的参数

    [Header("Dash Info")]
    [SerializeField] private float dashCooldown;
    private float dashUsageTimer;//为dash设置冷却时间,在一定时间内不能连续使用
    public float dashSpeed;//冲刺速度
    public float dashDuration;//持续时间
    public float dashDir { get; private set; }


    
    
    #region 定义States
    public PlayerStateMachine stateMachine { get; private set; }
    public PlayerIdleState idleState { get; private set; }
    public PlayerMoveState moveState { get; private set; }
    public PlayerJumpState jumpState { get; private set; }
    public PlayerAirState airState { get; private set; }
    public PlayerDashState dashState { get; private set; }
    public PlayerWallSlideState wallSlide { get; private set; }
    public PlayerWallJumpState wallJump { get; private set; }
    


    public PlayerPrimaryAttackState primaryAttack { get; private set; }
    public PlayerCounterAttackState counterAttack { get; private set; }

    public PlayerAimSwordState aimSword { get; private set; }
    public PlayerCatchSwordState catchSword { get; private set; }

    public PlayerBlackholeState blackhole { get; private set; }


    public SkillManager skill { get; private set; }
    public GameObject sword{ get; private set; }//声明sword

   
    #endregion
    protected override void Awake()
    {

        base.Awake();
        stateMachine = new PlayerStateMachine();
        //通过构造函数,在构造时传递信息
        idleState = new PlayerIdleState(this, stateMachine, "Idle");
        moveState = new PlayerMoveState(this, stateMachine, "Move");
        jumpState = new PlayerJumpState(this, stateMachine, "Jump");
        airState = new PlayerAirState(this, stateMachine, "Jump");
        dashState = new PlayerDashState(this, stateMachine, "Dash");
        wallSlide = new PlayerWallSlideState(this, stateMachine, "WallSlide");
        wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");//wallJump也是Jump动画


        primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
        counterAttack = new PlayerCounterAttackState(this, stateMachine, "CounterAttack");

        aimSword = new PlayerAimSwordState(this,stateMachine, "AimSword");
        catchSword = new PlayerCatchSwordState(this, stateMachine, "CatchSword");
        blackhole = new PlayerBlackholeState(this, stateMachine, "Jump");

        //this 就是 Player这个类本身
    }//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)
    protected override void Start()
    {
        base.Start();
        stateMachine.Initialize(idleState);
        skill = SkillManager.instance;

    }

    protected override void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update

    {
        base.Update();
        stateMachine.currentState.Update();//反复调用CurrentState的Update函数
        CheckForDashInput();
        
    }
    public void AssignNewSword(GameObject _newSword)//保持创造的sword实例的函数
    {
        sword = _newSword;
    }

    public void CatchTheSword()//通过player的CatchTheSword进入,及当剑消失的瞬间进入
    {
        stateMachine.ChangeState(catchSword);
        Destroy(sword);
    }
    
    public IEnumerator BusyFor(float _seconds)//https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
    {
        isBusy = true;
        yield return new WaitForSeconds(_seconds);
        isBusy = false;
    
    }//p39 4.防止在攻击间隔中进入move,通过设置busy值,在使用某些状态时,使其为busy为true,抑制其进入其他state
     //IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
    public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
    //从当前状态拿到AnimationTrigger进行调用的函数

    public void CheckForDashInput()
    {

        
        if (IsWallDetected())
        {
            return;
        }//修复在wallslide可以dash的BUG
        if (Input.GetKeyDown(KeyCode.LeftShift) && skill.dash.CanUseSkill())//将DashTimer<0 的判断 改成DashSkill里的判断
        {

            
            dashDir = Input.GetAxisRaw("Horizontal");//设置一个值,可以将dash的方向改为你想要的方向而不是你的朝向
            if (dashDir == 0)
            {
                dashDir = facingDir;//只有当玩家没有控制方向时才使用默认朝向
            }
            stateMachine.ChangeState(dashState);
        }

    }//将Dash切换设置成一个函数,使其在所以情况下都能使用
    
   
    
}

PlayerBlackholeState.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerBlackholeState : PlayerState
{
    private float flyTime = .4f;//飞行时间
    private bool skillUsed;//技能是否在被使用
    private float defaultGravity;

    public PlayerBlackholeState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void AnimationFinishTrigger()
    {
        base.AnimationFinishTrigger();
    }

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

        skillUsed = false;
        stateTimer = flyTime;
        defaultGravity = rb.gravityScale;
        rb.gravityScale = 0;
    }

    public override void Exit()
    {
        base.Exit();
        rb.gravityScale = defaultGravity;
        player.MakeTransprent(false);
    }

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

        //使角色释放技能后能飞起来
        if (stateTimer > 0)
        {
            rb.velocity = new Vector2(0, 15);
        }

        if(stateTimer < 0)
        {
            rb.velocity = new Vector2(0, -.1f);

            if(!skillUsed)
            {
                if(player.skill.blackhole.CanUseSkill())//创建实体
                skillUsed = true;
            }
        }

        if(player.skill.blackhole.SkillCompleted())
        {
            stateMachine.ChangeState(player.airState);
        }
    }
    
    
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UL1642标准_锂聚合物电池亚马逊测试报告

UL1642标准_锂聚合物电池亚马逊测试报告 什么是锂聚合物电池UL1642标准&#xff1f; UL1642 认证要求涵盖旨在用于技术人员可更换或用户可更换应用的锂离子电池。UL1642 认证要求是为了避免锂离子电池在产品中工作时发生火灾或爆炸的风险。 锂聚合物电池 UL是Underwriters L…

Devin:首位人工智能软件工程师的介绍

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

2024春招看了上百份程序员简历,这个工具写的简历最好!(附模板)

你们在制作简历时&#xff0c;是不是基本只关注两件事&#xff1a;简历模板&#xff0c;还有基本信息的填写。 当你再次坐下来更新你的简历时&#xff0c;可能会发现自己不自觉地选择了那个“看起来最好看的模板”&#xff0c;填写基本信息&#xff0c;却没有深入思考如何使简历…

DataWhale公开课笔记2:Diffusion Model和Transformer Diffusion

Stable Diffusion和AIGC AIGC是什么 AIGC的全称叫做AI generated content&#xff0c;AlGC (Al-Generated Content&#xff0c;人工智能生产内容)&#xff0c;是利用AI自动生产内容的生产方式。 在传统的内容创作领域中&#xff0c;专业生成内容&#xff08;PGC&#xff09;…

Python数值方法在工程和科学问题解决中的应用

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 随着计算机技术的不断发展&#xff0c;Python作…

UI设计中的图标的分类,功能性图标

图标的分类 既然知道了图标的作用和重要性&#xff0c;那么接下来&#xff0c;就要进一步了解在工作中我们要设计哪些图标。图标可以划分成三种大类:功能性图标、装饰性图标、启动图标。 功能性图标 功能图标是具有指代意义且具有功能标识的图形&#xff0c;它不仅是一种图形&a…

代码随想录算法训练营第day41|背包理论基础、416. 分割等和子集

目录 a.背包理论基础——01背包 1.二维数组的01背包表示 2.一维滚动数组表示 b. 416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; a.背包理论基础——01背包 背包问题分类&#xff1a; 对于面试的话&#xff0c;其实掌握01背包&#xff0c;和完全背包&#xff…

Sharding sphere分库分表

需要物理自己实现分表分库&#xff0c;然后通过配置文件配置。 配置文件&#xff1a; 需要配置多个数据源&#xff0c;主从表的关系【默认主表修改&#xff0c;从表读取】&#xff0c;定义分库的策略【比如User id】和分表【表Id】的策略 分库和分表策略&#xff1a;分库策略…

浅谈LockBit勒索病毒

在数字时代&#xff0c;随着科技的飞速发展&#xff0c;网络安全问题愈发凸显。恶意软件和勒索软件等网络威胁正不断演变&#xff0c;其中一款备受关注的勒索软件就是LockBit。 LockBit是一种高度复杂且具有破坏性的勒索软件。与传统的勒索软件相比&#xff0c;LockBit在其攻击…

外包干了5天,技术明显退步。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入南京某软件公司&#xff0c;干了接近2年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了2年的功能测试&…

国产AI视频技术迎来新成员Etna,4K 60帧 15秒超高清视频

国内AI视频技术领域传来好消息&#xff0c;一款名为Etna的AI视频生成工具引起了业界的广泛关注。这款由七火山公司开发的技术&#xff0c;号称能够实现15秒4K 60帧的超高清视频生成&#xff0c;让人眼前一亮&#xff01; &#x1f680; 国产技术的崛起 Etna的问世&#xff0c;…

【软考高项】【论文专题】- 5 - 论文写作思路梳理

目录 一、软考论文考什么&#xff1f; 二、我在项目中做什么&#xff1f; 三、项目做什么&#xff1f; 四、 项目小白常见雷区 五、如何写的不像是模版&#xff1f; 一、软考论文考什么&#xff1f; 《考试大纲》指出&#xff1a;根据试卷上给出的论文题目&#xff0c;选择…

【Linux】常用指令大全 [万字详解!建议收藏记忆!]

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

IDEA如何切换git账户

一、首先设置idea的密码不保存 二、找到你的windos的凭据管理器&#xff0c;直接在电脑里面搜索就行。 把已经有的git的凭据删掉&#xff0c;然后重启IDEA&#xff0c;拉取代码&#xff0c;就会弹框来让你输入账号。 注意&#xff1a;将系统弹出的账号密码框关掉&#xff0c;…

docker之自己制作jdk镜像

一&#xff0c;下载想要制作的镜像的对应jdk&#xff08;自行下载&#xff09;&#xff0c;本文使用jdk17&#xff08;因为自己的springboot项目时在jdk17下开发的&#xff0c;悲&#xff01;&#xff01;&#xff01;&#xff0c;再加上没有在官网上找到对应镜像&#xff0c;只…

C# danbooru Stable Diffusion 提示词反推 Onnx Demo

目录 说明 效果 模型信息 项目 代码 下载 C# danbooru Stable Diffusion 提示词反推 Onnx Demo 说明 模型下载地址&#xff1a;https://huggingface.co/deepghs/ml-danbooru-onnx 效果 模型信息 Model Properties ------------------------- ----------------------…

腾讯云轻量服务器地域选择方法整理,选择不能修改!

腾讯云轻量应用服务器地域如何选择&#xff1f;地域就近选择&#xff0c;北方选北京地域、南方选广州地域&#xff0c;华东地区选上海地域。广州上海北京地域有什么区别&#xff1f;哪个好&#xff1f;区别就是城市地理位置不同&#xff0c;其他的差不多&#xff0c;不区分好坏…

Qt中QCheckBox的三种状态设置

首先启用QCheckbox的tristate属性 //启用QCheckBox的tristate属性&#xff0c;使checkbox有三种状态。例&#xff1a; questionCheckBox->setTristate(true);//使用setCheckState(Qt::CheckState state)函数设置checkbox当前的状态。例&#xff1a; //Qt::CheckState是枚举…

运行springboot项目提示:java: 错误: 不支持发行版本 18、java: 错误: 无效的源发行版:18

java: 错误: 不支持发行版本 18 解决方法&#xff1a;修改字节码版本&#xff0c;可以多试几次。 java: 错误: 无效的源发行版&#xff1a;18 解决方法&#xff1a; 出现这些错误原因&#xff1a; spring版本与jdk版本不对应 我的spring boot版本是3.2.2&#xff0c;对应的j…

2024腾讯云轻量应用服务器地域有什么区别?哪个好?

腾讯云轻量应用服务器地域如何选择&#xff1f;地域就近选择&#xff0c;北方选北京地域、南方选广州地域&#xff0c;华东地区选上海地域。广州上海北京地域有什么区别&#xff1f;哪个好&#xff1f;区别就是城市地理位置不同&#xff0c;其他的差不多&#xff0c;不区分好坏…