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


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

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

    Blackhole_Skill_Controller.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using TMPro;
    4. using UnityEngine;
    5. public class Blackhole_Skill_Controller : MonoBehaviour
    6. {
    7. [SerializeField] private GameObject hotKeyPrefab;
    8. [SerializeField] private List KeyCodeList;
    9. private float maxSize;//最大尺寸
    10. private float growSpeed;//变大速度
    11. private float shrinkSpeed;//缩小速度
    12. private float blackholeTimer;
    13. private bool canGrow = true;//是否可以变大
    14. private bool canShrink;//缩小
    15. private bool canCreateHotKeys = true;专门控制后面进入的没法生成热键
    16. private bool cloneAttackReleased;
    17. private int amountOfAttacks = 4;
    18. private float cloneAttackCooldown = .3f;
    19. private float cloneAttackTimer;
    20. private List targets = new List();
    21. private List createdHotKey = new List();
    22. public bool playerCanExitState { get; private set; }
    23. public void SetupBlackhole(float _maxSize,float _growSpeed,float _shrinkSpeed,int _amountOfAttacks,float _cloneAttackCooldown,float _blackholeDuration)
    24. {
    25. maxSize = _maxSize;
    26. growSpeed = _growSpeed;
    27. shrinkSpeed = _shrinkSpeed;
    28. amountOfAttacks = _amountOfAttacks;
    29. cloneAttackCooldown = _cloneAttackCooldown;
    30. blackholeTimer = _blackholeDuration;
    31. }
    32. private void Update()
    33. {
    34. blackholeTimer -= Time.deltaTime;
    35. cloneAttackTimer -= Time.deltaTime;
    36. if(blackholeTimer <= 0)
    37. {
    38. blackholeTimer = Mathf.Infinity;//防止重复检测
    39. if (targets.Count > 0)//只有有target才释放攻击
    40. {
    41. ReleaseCloneAttack();//释放攻击
    42. }
    43. else
    44. FinishBlackholeAbility();//缩小黑洞
    45. }
    46. if (Input.GetKeyDown(KeyCode.R)&& targets.Count > 0)
    47. {
    48. ReleaseCloneAttack();
    49. }
    50. CloneAttackLogic();
    51. if (canGrow && !canShrink)
    52. {
    53. //这是控制物体大小的参数
    54. transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(maxSize, maxSize), growSpeed * Time.deltaTime);
    55. //类似MoveToward,不过是放大到多少大小 https://docs.unity3d.com/cn/current/ScriptReference/Vector2.Lerp.html
    56. }
    57. if (canShrink)
    58. {
    59. transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(0, 0), shrinkSpeed * Time.deltaTime);
    60. if (transform.localScale.x <= 1f)
    61. {
    62. Destroy(gameObject);
    63. }
    64. }
    65. }
    66. private void ReleaseCloneAttack()
    67. {
    68. cloneAttackReleased = true;
    69. canCreateHotKeys = false;
    70. DestroyHotKeys();
    71. PlayerManager.instance.player.MakeTransprent(true);
    72. }
    73. private void CloneAttackLogic()
    74. {
    75. if (cloneAttackTimer < 0 && cloneAttackReleased&&amountOfAttacks>0)
    76. {
    77. cloneAttackTimer = cloneAttackCooldown;
    78. int randomIndex = Random.Range(0, targets.Count);
    79. //限制攻击次数和设置攻击偏移量
    80. float _offset;
    81. if (Random.Range(0, 100) > 50)
    82. _offset = 1.5f;
    83. else
    84. _offset = -1.5f;
    85. SkillManager.instance.clone.CreateClone(targets[randomIndex], new Vector3(_offset, 0, 0));
    86. amountOfAttacks--;
    87. if (amountOfAttacks <= 0)
    88. {
    89. Invoke("FinishBlackholeAbility", 0.5f);
    90. }
    91. }
    92. }
    93. private void FinishBlackholeAbility()
    94. {
    95. DestroyHotKeys();
    96. canShrink = true;
    97. cloneAttackReleased = false;
    98. playerCanExitState = true;
    99. }
    100. private void OnTriggerEnter2D(Collider2D collision)
    101. {
    102. if(collision.GetComponent()!=null)
    103. {
    104. collision.GetComponent().FreezeTime(true);
    105. CreateHotKey(collision);
    106. }
    107. }
    108. private void OnTriggerExit2D(Collider2D collision)
    109. {
    110. if (collision.GetComponent() != null)
    111. {
    112. collision.GetComponent().FreezeTime(false);
    113. }
    114. }
    115. private void CreateHotKey(Collider2D collision)
    116. {
    117. if(KeyCodeList.Count == 0)//当所有的KeyCode都被去除,就不在创建实例
    118. {
    119. return;
    120. }
    121. if(!canCreateHotKeys)//这是当角色已经开大了,不在创建实例
    122. {
    123. return;
    124. }
    125. //创建实例
    126. GameObject newHotKey = Instantiate(hotKeyPrefab, collision.transform.position + new Vector3(0, 2), Quaternion.identity);
    127. //将实例添加进列表
    128. createdHotKey.Add(newHotKey);
    129. //随机KeyCode传给HotKey,并且传过去一个毁掉一个
    130. KeyCode choosenKey = KeyCodeList[Random.Range(0, KeyCodeList.Count)];
    131. KeyCodeList.Remove(choosenKey);
    132. Blackhole_Hotkey_Controller newHotKeyScript = newHotKey.GetComponent();
    133. newHotKeyScript.SetupHotKey(choosenKey, collision.transform, this);
    134. }
    135. public void AddEnemyToList(Transform _myEnemy)
    136. {
    137. targets.Add(_myEnemy);
    138. }
    139. //销毁Hotkey
    140. private void DestroyHotKeys()
    141. {
    142. if(createdHotKey.Count <= 0)
    143. {
    144. return;
    145. }
    146. for (int i = 0; i < createdHotKey.Count; i++)
    147. {
    148. Destroy(createdHotKey[i]);
    149. }
    150. }
    151. }

    Blackhole_Skill.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class Blackhole_Skill : Skill
    5. {
    6. [SerializeField]private float maxSize;//最大尺寸
    7. [SerializeField] private float growSpeed;//变大速度
    8. [SerializeField] private float shrinkSpeed;//缩小速度
    9. [SerializeField] private GameObject blackholePrefab;
    10. [Space]
    11. [SerializeField] private float blackholeDuration;
    12. [SerializeField] int amountOfAttacks = 4;
    13. [SerializeField] float cloneAttackCooldown = .3f;
    14. Blackhole_Skill_Controller currentBlackhole;
    15. public override bool CanUseSkill()
    16. {
    17. return base.CanUseSkill();
    18. }
    19. public override void UseSkill()
    20. {
    21. base.UseSkill();
    22. GameObject newBlackhole = Instantiate(blackholePrefab,player.transform.position,Quaternion.identity);
    23. currentBlackhole = newBlackhole.GetComponent();
    24. currentBlackhole.SetupBlackhole(maxSize,growSpeed,shrinkSpeed,amountOfAttacks,cloneAttackCooldown,blackholeDuration);
    25. }
    26. protected override void Start()
    27. {
    28. base.Start();
    29. }
    30. protected override void Update()
    31. {
    32. base.Update();
    33. }
    34. public bool SkillCompleted()
    35. {
    36. if(currentBlackhole == null)
    37. return false;
    38. if (currentBlackhole.playerCanExitState)
    39. {
    40. return true;
    41. }
    42. else
    43. {
    44. return false;
    45. }
    46. }
    47. }
    Player.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.VisualScripting;
    4. using UnityEngine;
    5. public class Player : Entity
    6. {
    7. [Header("Attack Details")]
    8. public Vector2[] attackMovement;//每个攻击时获得的速度组
    9. public float counterAttackDuration = .2f;
    10. public bool isBusy{ get; private set; }//防止在攻击间隔中进入move
    11. //
    12. [Header("Move Info")]
    13. public float moveSpeed;//定义速度,与xInput相乘控制速度的大小
    14. public float jumpForce;
    15. public float swordReturnImpact;//在player里设置swordReturnImpact作为击退的参数
    16. [Header("Dash Info")]
    17. [SerializeField] private float dashCooldown;
    18. private float dashUsageTimer;//为dash设置冷却时间,在一定时间内不能连续使用
    19. public float dashSpeed;//冲刺速度
    20. public float dashDuration;//持续时间
    21. public float dashDir { get; private set; }
    22. #region 定义States
    23. public PlayerStateMachine stateMachine { get; private set; }
    24. public PlayerIdleState idleState { get; private set; }
    25. public PlayerMoveState moveState { get; private set; }
    26. public PlayerJumpState jumpState { get; private set; }
    27. public PlayerAirState airState { get; private set; }
    28. public PlayerDashState dashState { get; private set; }
    29. public PlayerWallSlideState wallSlide { get; private set; }
    30. public PlayerWallJumpState wallJump { get; private set; }
    31. public PlayerPrimaryAttackState primaryAttack { get; private set; }
    32. public PlayerCounterAttackState counterAttack { get; private set; }
    33. public PlayerAimSwordState aimSword { get; private set; }
    34. public PlayerCatchSwordState catchSword { get; private set; }
    35. public PlayerBlackholeState blackhole { get; private set; }
    36. public SkillManager skill { get; private set; }
    37. public GameObject sword{ get; private set; }//声明sword
    38. #endregion
    39. protected override void Awake()
    40. {
    41. base.Awake();
    42. stateMachine = new PlayerStateMachine();
    43. //通过构造函数,在构造时传递信息
    44. idleState = new PlayerIdleState(this, stateMachine, "Idle");
    45. moveState = new PlayerMoveState(this, stateMachine, "Move");
    46. jumpState = new PlayerJumpState(this, stateMachine, "Jump");
    47. airState = new PlayerAirState(this, stateMachine, "Jump");
    48. dashState = new PlayerDashState(this, stateMachine, "Dash");
    49. wallSlide = new PlayerWallSlideState(this, stateMachine, "WallSlide");
    50. wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");//wallJump也是Jump动画
    51. primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
    52. counterAttack = new PlayerCounterAttackState(this, stateMachine, "CounterAttack");
    53. aimSword = new PlayerAimSwordState(this,stateMachine, "AimSword");
    54. catchSword = new PlayerCatchSwordState(this, stateMachine, "CatchSword");
    55. blackhole = new PlayerBlackholeState(this, stateMachine, "Jump");
    56. //this 就是 Player这个类本身
    57. }//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)
    58. protected override void Start()
    59. {
    60. base.Start();
    61. stateMachine.Initialize(idleState);
    62. skill = SkillManager.instance;
    63. }
    64. protected override void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update
    65. {
    66. base.Update();
    67. stateMachine.currentState.Update();//反复调用CurrentState的Update函数
    68. CheckForDashInput();
    69. }
    70. public void AssignNewSword(GameObject _newSword)//保持创造的sword实例的函数
    71. {
    72. sword = _newSword;
    73. }
    74. public void CatchTheSword()//通过player的CatchTheSword进入,及当剑消失的瞬间进入
    75. {
    76. stateMachine.ChangeState(catchSword);
    77. Destroy(sword);
    78. }
    79. public IEnumerator BusyFor(float _seconds)//https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
    80. {
    81. isBusy = true;
    82. yield return new WaitForSeconds(_seconds);
    83. isBusy = false;
    84. }//p39 4.防止在攻击间隔中进入move,通过设置busy值,在使用某些状态时,使其为busy为true,抑制其进入其他state
    85. //IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
    86. public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
    87. //从当前状态拿到AnimationTrigger进行调用的函数
    88. public void CheckForDashInput()
    89. {
    90. if (IsWallDetected())
    91. {
    92. return;
    93. }//修复在wallslide可以dash的BUG
    94. if (Input.GetKeyDown(KeyCode.LeftShift) && skill.dash.CanUseSkill())//将DashTimer<0 的判断 改成DashSkill里的判断
    95. {
    96. dashDir = Input.GetAxisRaw("Horizontal");//设置一个值,可以将dash的方向改为你想要的方向而不是你的朝向
    97. if (dashDir == 0)
    98. {
    99. dashDir = facingDir;//只有当玩家没有控制方向时才使用默认朝向
    100. }
    101. stateMachine.ChangeState(dashState);
    102. }
    103. }//将Dash切换设置成一个函数,使其在所以情况下都能使用
    104. }

    PlayerBlackholeState.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.VisualScripting;
    4. using UnityEngine;
    5. public class PlayerBlackholeState : PlayerState
    6. {
    7. private float flyTime = .4f;//飞行时间
    8. private bool skillUsed;//技能是否在被使用
    9. private float defaultGravity;
    10. public PlayerBlackholeState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    11. {
    12. }
    13. public override void AnimationFinishTrigger()
    14. {
    15. base.AnimationFinishTrigger();
    16. }
    17. public override void Enter()
    18. {
    19. base.Enter();
    20. skillUsed = false;
    21. stateTimer = flyTime;
    22. defaultGravity = rb.gravityScale;
    23. rb.gravityScale = 0;
    24. }
    25. public override void Exit()
    26. {
    27. base.Exit();
    28. rb.gravityScale = defaultGravity;
    29. player.MakeTransprent(false);
    30. }
    31. public override void Update()
    32. {
    33. base.Update();
    34. //使角色释放技能后能飞起来
    35. if (stateTimer > 0)
    36. {
    37. rb.velocity = new Vector2(0, 15);
    38. }
    39. if(stateTimer < 0)
    40. {
    41. rb.velocity = new Vector2(0, -.1f);
    42. if(!skillUsed)
    43. {
    44. if(player.skill.blackhole.CanUseSkill())//创建实体
    45. skillUsed = true;
    46. }
    47. }
    48. if(player.skill.blackhole.SkillCompleted())
    49. {
    50. stateMachine.ChangeState(player.airState);
    51. }
    52. }
    53. }

  • 相关阅读:
    Mogdb 5.0新特性:SQL PATCH绑定执行计划
    抢先体验! 在浏览器里写 Flutter 是一种什么体验?
    云流化:XR扩展现实应用发展的一个新方向!
    Badger简单使用
    基于Keras搭建CNN、TextCNN文本分类模型
    Rxjava学习(一)简单分析Rxjava调用流程
    JVM内存模型与类加载机制
    Jtti:windows虚拟机如何设定永久静态路由
    亚马逊要求纽扣电池出口IEC60086测试报告申请流程
    P1040 [NOIP2003 提高组] 加分二叉树
  • 原文地址:https://blog.csdn.net/Homura_/article/details/136558698