当前位置:   article > 正文

Unity类银河恶魔城学习记录9-4 p92 Death of entity源代码

Unity类银河恶魔城学习记录9-4 p92 Death of entity源代码

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

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

PlayerStat
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class PlayerStat : CharacterStats
  5. {
  6. private Player player;
  7. protected override void Start()
  8. {
  9. player = GetComponent<Player>();
  10. base.Start();
  11. }
  12. public override void DoDamage(CharacterStats _targetStats)
  13. {
  14. base.DoDamage(_targetStats);
  15. }
  16. protected override void TakeDamage(int _damage)
  17. {
  18. base.TakeDamage(_damage);
  19. player.DamageEffect();
  20. }
  21. protected override void Die()
  22. {
  23. base.Die();
  24. player.Die();
  25. }
  26. }

EnemyStat
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class EnemyStat : CharacterStats
  5. {
  6. private Enemy enemy;
  7. public override void DoDamage(CharacterStats _targetStats)
  8. {
  9. base.DoDamage(_targetStats);
  10. }
  11. protected override void Die()
  12. {
  13. base.Die();
  14. enemy.Die();
  15. }
  16. protected override void Start()
  17. {
  18. enemy = GetComponent<Enemy>();
  19. base.Start();
  20. }
  21. protected override void TakeDamage(int _damage)
  22. {
  23. base.TakeDamage(_damage);
  24. enemy.DamageEffect();
  25. }
  26. }
Entity.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class Entity : MonoBehaviour
  5. {
  6. [Header("Knockback info")]
  7. [SerializeField] protected Vector2 knockbackDirection;//被击打后的速度信息
  8. [SerializeField] protected float knockbackDuration;//被击打的时间
  9. protected bool isKnocked;//此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
  10. [Header("Collision Info")]
  11. public Transform attackCheck;//transform类,代表的时物体的位置,用来控制攻击检测的位置
  12. public float attackCheckRadius;//检测半径
  13. [SerializeField] protected Transform groundCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置
  14. [SerializeField] protected float groundCheckDistance;
  15. [SerializeField] protected Transform wallCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置
  16. [SerializeField] protected float wallCheckDistance;
  17. [SerializeField] protected LayerMask whatIsGround;//LayerMask类,与Raycast配合,https://docs.unity3d.com/cn/current/ScriptReference/Physics.Raycast.html
  18. #region 定义Unity组件
  19. public SpriteRenderer sr { get; private set; }
  20. public Animator anim { get; private set; }//这样才能配合着拿到自己身上的animator的控制权
  21. public Rigidbody2D rb { get; private set; }//配合拿到身上的Rigidbody2D组件控制权
  22. public EntityFX fx { get; private set; }//拿到EntityFX
  23. public CharacterStats stats { get; private set; }
  24. public CapsuleCollider2D cd { get; private set; }
  25. #endregion
  26. public int facingDir { get; private set; } = 1;
  27. protected bool facingRight = true;//判断是否朝右
  28. protected virtual void Awake()
  29. {
  30. }
  31. protected virtual void Start()
  32. {
  33. anim = GetComponentInChildren<Animator>();//拿到自己子组件身上的animator的控制权
  34. sr = GetComponentInChildren<SpriteRenderer>();
  35. fx = GetComponent<EntityFX>();拿到的组件上的EntityFX控制权
  36. rb = GetComponent<Rigidbody2D>();
  37. stats = GetComponent<CharacterStats>();
  38. cd = GetComponent<CapsuleCollider2D>();
  39. }
  40. protected virtual void Update()
  41. {
  42. }
  43. protected virtual void Exit()
  44. {
  45. }
  46. public virtual void DamageEffect()
  47. {
  48. fx.StartCoroutine("FlashFX");//IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
  49. //https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
  50. StartCoroutine("HitKnockback");//调用被击打后产生后退效果的函数
  51. Debug.Log(gameObject.name+"was damaged");
  52. }
  53. protected virtual IEnumerator HitKnockback()
  54. {
  55. isKnocked = true;//此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
  56. rb.velocity = new Vector2(knockbackDirection.x * -facingDir, knockbackDirection.y);
  57. yield return new WaitForSeconds(knockbackDuration);
  58. isKnocked = false;
  59. }
  60. //被击打后产生后退效果的函数
  61. #region 速度函数Velocity
  62. public virtual void SetZeroVelocity()
  63. {
  64. if(isKnocked)
  65. {
  66. return;
  67. }
  68. rb.velocity = new Vector2(0, 0);
  69. }//设置速度为0函数
  70. public virtual void SetVelocity(float _xVelocity, float _yVelocity)
  71. {
  72. if(isKnocked)
  73. return;此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
  74. rb.velocity = new Vector2(_xVelocity, _yVelocity);//将rb的velocity属性设置为对应的想要的二维向量。因为2D游戏的速度就是二维向量
  75. FlipController(_xVelocity);//在其他设置速度的时候调用翻转控制器
  76. }//控制速度的函数,此函数在其他State中可能会使用,但仅能通过player.SeVelocity调用
  77. #endregion
  78. #region 翻转函数Flip
  79. public virtual void Flip()
  80. {
  81. facingDir = facingDir * -1;
  82. facingRight = !facingRight;
  83. transform.Rotate(0, 180, 0);//旋转函数,transform不需要额外定义,因为他是自带的
  84. }//翻转函数
  85. public virtual void FlipController(float _x)//目前设置x,目的时能在空中时也能转身
  86. {
  87. if (_x > 0 && !facingRight)//当速度大于0且没有朝右时,翻转
  88. {
  89. Flip();
  90. }
  91. else if (_x < 0 && facingRight)
  92. {
  93. Flip();
  94. }
  95. }
  96. #endregion
  97. #region 碰撞函数Collision
  98. public virtual bool IsGroundDetected()
  99. {
  100. return Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
  101. }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics2D.Raycast.html
  102. //xxxxxxxx() => xxxxxxxx == xxxxxxxxxx() return xxxxxxxxx;
  103. public virtual bool IsWallDetected()
  104. {
  105. return Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
  106. }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics2D.Raycast.html
  107. //xxxxxxxx() => xxxxxxxx == xxxxxxxxxx() return xxxxxxxxx;
  108. protected virtual void OnDrawGizmos()
  109. {
  110. Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
  111. Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
  112. Gizmos.DrawWireSphere(attackCheck.position, attackCheckRadius);//https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Gizmos.DrawWireSphere.html
  113. //绘制具有中心和半径的线框球体。
  114. }//画图函数
  115. #endregion
  116. public void MakeTransprent(bool isClear)
  117. {
  118. if (isClear)
  119. sr.color = Color.clear;
  120. else
  121. sr.color = Color.white;
  122. }
  123. public virtual void Die()
  124. {
  125. }
  126. }
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 PlayerDeadState deadState { get; private set; }
  32. public PlayerPrimaryAttackState primaryAttack { get; private set; }
  33. public PlayerCounterAttackState counterAttack { get; private set; }
  34. public PlayerAimSwordState aimSword { get; private set; }
  35. public PlayerCatchSwordState catchSword { get; private set; }
  36. public PlayerBlackholeState blackhole { get; private set; }
  37. public SkillManager skill { get; private set; }
  38. public GameObject sword{ get; private set; }//声明sword
  39. #endregion
  40. protected override void Awake()
  41. {
  42. base.Awake();
  43. stateMachine = new PlayerStateMachine();
  44. //通过构造函数,在构造时传递信息
  45. idleState = new PlayerIdleState(this, stateMachine, "Idle");
  46. moveState = new PlayerMoveState(this, stateMachine, "Move");
  47. jumpState = new PlayerJumpState(this, stateMachine, "Jump");
  48. airState = new PlayerAirState(this, stateMachine, "Jump");
  49. dashState = new PlayerDashState(this, stateMachine, "Dash");
  50. wallSlide = new PlayerWallSlideState(this, stateMachine, "WallSlide");
  51. wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");//wallJump也是Jump动画
  52. deadState = new PlayerDeadState(this, stateMachine, "Die");
  53. primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
  54. counterAttack = new PlayerCounterAttackState(this, stateMachine, "CounterAttack");
  55. aimSword = new PlayerAimSwordState(this,stateMachine, "AimSword");
  56. catchSword = new PlayerCatchSwordState(this, stateMachine, "CatchSword");
  57. blackhole = new PlayerBlackholeState(this, stateMachine, "Jump");
  58. //this 就是 Player这个类本身
  59. }//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)
  60. protected override void Start()
  61. {
  62. base.Start();
  63. stateMachine.Initialize(idleState);
  64. skill = SkillManager.instance;
  65. }
  66. protected override void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update
  67. {
  68. base.Update();
  69. stateMachine.currentState.Update();//反复调用CurrentState的Update函数
  70. CheckForDashInput();
  71. if(Input.GetKeyDown(KeyCode.F))
  72. {
  73. skill.crystal.CanUseSkill();
  74. }
  75. }
  76. public void AssignNewSword(GameObject _newSword)//保持创造的sword实例的函数
  77. {
  78. sword = _newSword;
  79. }
  80. public void CatchTheSword()//通过player的CatchTheSword进入,及当剑消失的瞬间进入
  81. {
  82. stateMachine.ChangeState(catchSword);
  83. Destroy(sword);
  84. }
  85. public IEnumerator BusyFor(float _seconds)//https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
  86. {
  87. isBusy = true;
  88. yield return new WaitForSeconds(_seconds);
  89. isBusy = false;
  90. }//p39 4.防止在攻击间隔中进入move,通过设置busy值,在使用某些状态时,使其为busy为true,抑制其进入其他state
  91. //IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
  92. public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
  93. //从当前状态拿到AnimationTrigger进行调用的函数
  94. public void CheckForDashInput()
  95. {
  96. if (IsWallDetected())
  97. {
  98. return;
  99. }//修复在wallslide可以dash的BUG
  100. if (Input.GetKeyDown(KeyCode.LeftShift) && skill.dash.CanUseSkill())//将DashTimer<0 的判断 改成DashSkill里的判断
  101. {
  102. dashDir = Input.GetAxisRaw("Horizontal");//设置一个值,可以将dash的方向改为你想要的方向而不是你的朝向
  103. if (dashDir == 0)
  104. {
  105. dashDir = facingDir;//只有当玩家没有控制方向时才使用默认朝向
  106. }
  107. stateMachine.ChangeState(dashState);
  108. }
  109. }//将Dash切换设置成一个函数,使其在所以情况下都能使用
  110. public override void Die()
  111. {
  112. base.Die();
  113. stateMachine.ChangeState(deadState);
  114. }
  115. }
PlayerDeadState.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class PlayerDeadState : PlayerState
  5. {
  6. public PlayerDeadState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
  7. {
  8. }
  9. public override void AnimationFinishTrigger()
  10. {
  11. base.AnimationFinishTrigger();
  12. }
  13. public override void Enter()
  14. {
  15. base.Enter();
  16. }
  17. public override void Exit()
  18. {
  19. base.Exit();
  20. }
  21. public override void Update()
  22. {
  23. base.Update();
  24. player.SetZeroVelocity();
  25. }
  26. }

Enemy.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Unity.VisualScripting;
  4. using UnityEngine;
  5. public class Enemy : Entity
  6. {
  7. [SerializeField] protected LayerMask whatIsPlayer;
  8. [Header("Stun Info")]
  9. public float stunnedDuration;//stunned持续时间
  10. public Vector2 stunnedDirection;//stunned改变后的速度
  11. protected bool canBeStunned;//判断是否可以被反击
  12. [SerializeField] protected GameObject counterImage;//一个代表着是否可以被反击的信号
  13. [Header("Move Info")]
  14. public float moveSpeed;
  15. public float idleTime;
  16. public float battleTime;//多久能从battle状态中退出来
  17. private float defaultMoveSpeed;
  18. [Header("Attack Info")]
  19. public float attackDistance;
  20. public float attackCooldown;//攻击冷却
  21. [HideInInspector] public float lastTimeAttacked;//最后一次攻击的时间
  22. #region
  23. public EnemyStateMachine stateMachine { get; private set; }
  24. public string lastingAnimBoolName{ get; private set; }
  25. public virtual void AssignLastAnimName(string _animBoolName)
  26. {
  27. lastingAnimBoolName = _animBoolName;
  28. }
  29. #endregion
  30. protected override void Awake()
  31. {
  32. base.Awake();
  33. stateMachine = new EnemyStateMachine();
  34. defaultMoveSpeed = moveSpeed;
  35. }
  36. protected override void Start()
  37. {
  38. base.Start();
  39. }
  40. protected override void Update()
  41. {
  42. base.Update();
  43. stateMachine.currentState.Update();
  44. //Debug.Log(IsPlayerDetected().collider.gameObject.name + "I see");//这串代码会报错,可能使版本的物体,因为在没有找到Player的时候物体是空的,NULL,你想让他在控制台上显示就报错了
  45. }
  46. public virtual void FreezeTime(bool _timeFrozen)
  47. {
  48. if(_timeFrozen)
  49. {
  50. moveSpeed = 0;
  51. anim.speed = 0;
  52. }
  53. else
  54. {
  55. moveSpeed = defaultMoveSpeed;
  56. anim.speed = 1;
  57. }
  58. }
  59. protected virtual IEnumerator FreezeTimeFor(float _seconds)
  60. {
  61. FreezeTime(true);
  62. yield return new WaitForSeconds(_seconds);
  63. FreezeTime(false);
  64. }
  65. #region Counter Attack Window
  66. public virtual void OpenCounterAttackWindow()//打开可以反击的信号的函数
  67. {
  68. canBeStunned = true;
  69. counterImage.SetActive(true);
  70. }
  71. public virtual void CloseCounterAttackWindow()//关闭可以反击的信号的函数
  72. {
  73. canBeStunned = false;
  74. counterImage.SetActive(false);
  75. }
  76. #endregion
  77. public virtual bool CanBeStunned()//这里的主要目的是完成在被反击过后能立刻关闭提示窗口
  78. {
  79. if (canBeStunned)
  80. {
  81. CloseCounterAttackWindow();
  82. return true;
  83. }
  84. return false;
  85. }
  86. public virtual void AnimationFinishTrigger() => stateMachine.currentState.AnimationFinishTrigger();//动画完成时调用的函数,与Player相同
  87. public virtual RaycastHit2D IsPlayerDetected() => Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, 7, whatIsPlayer);//用于从射线投射获取信息的结构。
  88. //该函数的返回值可以变,可以只返回bool,也可以是碰到的结构
  89. protected override void OnDrawGizmos()
  90. {
  91. base.OnDrawGizmos();
  92. Gizmos.color = Color.yellow;//把线改成黄色
  93. Gizmos.DrawLine(transform.position, new Vector3(transform.position.x + attackDistance * facingDir, transform.position.y));//用来判别是否进入attackState的线
  94. }
  95. }

Enemy_Skeleton.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class EnemyState
  5. {
  6. protected Enemy enemyBase;
  7. protected EnemyStateMachine stateMachine;
  8. protected Rigidbody2D rb;//小简化
  9. protected bool triggerCalled;
  10. private string animBoolName;
  11. protected float stateTimer;
  12. public EnemyState(Enemy _enemyBase, EnemyStateMachine _stateMachine, string _animBoolName)
  13. {
  14. this.enemyBase = _enemyBase;
  15. this.stateMachine = _stateMachine;
  16. this.animBoolName = _animBoolName;
  17. }
  18. public virtual void Enter()
  19. {
  20. triggerCalled = false;
  21. enemyBase.anim.SetBool(animBoolName, true);
  22. rb = enemyBase.rb;//小简化
  23. }
  24. public virtual void Update()
  25. {
  26. stateTimer -= Time.deltaTime;
  27. }
  28. public virtual void Exit()
  29. {
  30. enemyBase.anim.SetBool(animBoolName, false);
  31. enemyBase.AssignLastAnimName(animBoolName);
  32. }
  33. //动画完成时调用的函数,与Player相同
  34. public virtual void AnimationFinishTrigger()
  35. {
  36. triggerCalled = true;
  37. }
  38. }

EnemyState.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Unity.VisualScripting;
  4. using UnityEditorInternal;
  5. using UnityEngine;
  6. public class Enemy_Skeleton : Enemy
  7. {
  8. #region 类State
  9. public SkeletonIdleState idleState { get; private set; }
  10. public SkeletonMoveState moveState { get; private set; }
  11. public SkeletonBattleState battleState { get; private set; }
  12. public SkeletonAttackState attackState { get; private set; }
  13. public SkeletonStunnedState stunnedState { get; private set; }
  14. public SkeletonDeadState deadState { get; private set; }
  15. #endregion
  16. protected override void Awake()
  17. {
  18. base.Awake();
  19. idleState = new SkeletonIdleState(this, stateMachine, "Idle", this);
  20. moveState = new SkeletonMoveState(this,stateMachine, "Move", this);
  21. battleState = new SkeletonBattleState(this, stateMachine, "Move", this);
  22. attackState = new SkeletonAttackState(this, stateMachine, "Attack", this);
  23. stunnedState = new SkeletonStunnedState(this, stateMachine, "Stunned", this);
  24. deadState = new SkeletonDeadState(this, stateMachine, "Idle", this);
  25. }
  26. protected override void Start()
  27. {
  28. base.Start();
  29. stateMachine.Initialize(idleState);
  30. }
  31. protected override void Update()
  32. {
  33. base.Update();
  34. }
  35. public override bool CanBeStunned()
  36. {
  37. if (base.CanBeStunned())//在这里重写主要是因为只有在Skeleton里面才能调用stunnedState
  38. {
  39. stateMachine.ChangeState(stunnedState);
  40. return true;
  41. }
  42. return false;
  43. }
  44. //重写后不仅能达成在完成被反击后关闭提示窗口,还能转换为stunnedState
  45. public override void Die()
  46. {
  47. base.Die();
  48. stateMachine.ChangeState(deadState);
  49. }
  50. }
SkeletonDeadState.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class SkeletonDeadState : EnemyState
  5. {
  6. private Enemy_Skeleton enemy;
  7. public SkeletonDeadState(Enemy _enemyBase, EnemyStateMachine _stateMachine, string _animBoolName,Enemy_Skeleton _enemy) : base(_enemyBase, _stateMachine, _animBoolName)
  8. {
  9. this.enemy = _enemy;
  10. }
  11. public override void Enter()
  12. {
  13. base.Enter();
  14. enemy.anim.SetBool(enemy.lastingAnimBoolName, true);
  15. enemy.anim.speed = 0;
  16. enemy.cd.enabled = false;
  17. stateTimer = .1f;
  18. }
  19. public override void Update()
  20. {
  21. base.Update();
  22. if (stateTimer > 0)
  23. rb.velocity = new Vector2(0, 10);
  24. }
  25. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/228914
推荐阅读
相关标签
  

闽ICP备14008679号