赞
踩
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class PlayerStat : CharacterStats
- {
- private Player player;
-
-
-
-
- protected override void Start()
- {
- player = GetComponent<Player>();
- base.Start();
- }
- public override void DoDamage(CharacterStats _targetStats)
- {
- base.DoDamage(_targetStats);
-
- }
- protected override void TakeDamage(int _damage)
- {
- base.TakeDamage(_damage);
- player.DamageEffect();
- }
- protected override void Die()
- {
- base.Die();
-
- player.Die();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class EnemyStat : CharacterStats
- {
- private Enemy enemy;
- public override void DoDamage(CharacterStats _targetStats)
- {
- base.DoDamage(_targetStats);
- }
-
- protected override void Die()
- {
- base.Die();
- enemy.Die();
- }
-
- protected override void Start()
- {
- enemy = GetComponent<Enemy>();
- base.Start();
- }
-
- protected override void TakeDamage(int _damage)
- {
- base.TakeDamage(_damage);
-
- enemy.DamageEffect();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class Entity : MonoBehaviour
- {
- [Header("Knockback info")]
- [SerializeField] protected Vector2 knockbackDirection;//被击打后的速度信息
- [SerializeField] protected float knockbackDuration;//被击打的时间
- protected bool isKnocked;//此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
-
- [Header("Collision Info")]
- public Transform attackCheck;//transform类,代表的时物体的位置,用来控制攻击检测的位置
- public float attackCheckRadius;//检测半径
- [SerializeField] protected Transform groundCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置
- [SerializeField] protected float groundCheckDistance;
- [SerializeField] protected Transform wallCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置
- [SerializeField] protected float wallCheckDistance;
- [SerializeField] protected LayerMask whatIsGround;//LayerMask类,与Raycast配合,https://docs.unity3d.com/cn/current/ScriptReference/Physics.Raycast.html
-
- #region 定义Unity组件
- public SpriteRenderer sr { get; private set; }
- public Animator anim { get; private set; }//这样才能配合着拿到自己身上的animator的控制权
- public Rigidbody2D rb { get; private set; }//配合拿到身上的Rigidbody2D组件控制权
- public EntityFX fx { get; private set; }//拿到EntityFX
- public CharacterStats stats { get; private set; }
- public CapsuleCollider2D cd { get; private set; }
- #endregion
- public int facingDir { get; private set; } = 1;
- protected bool facingRight = true;//判断是否朝右
-
- protected virtual void Awake()
- {
-
- }
- protected virtual void Start()
- {
- anim = GetComponentInChildren<Animator>();//拿到自己子组件身上的animator的控制权
- sr = GetComponentInChildren<SpriteRenderer>();
- fx = GetComponent<EntityFX>();拿到的组件上的EntityFX控制权
- rb = GetComponent<Rigidbody2D>();
- stats = GetComponent<CharacterStats>();
- cd = GetComponent<CapsuleCollider2D>();
- }
- protected virtual void Update()
- {
-
- }
-
- protected virtual void Exit()
- {
-
- }
- public virtual void DamageEffect()
- {
-
- fx.StartCoroutine("FlashFX");//IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
- //https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
- StartCoroutine("HitKnockback");//调用被击打后产生后退效果的函数
- Debug.Log(gameObject.name+"was damaged");
- }
-
- protected virtual IEnumerator HitKnockback()
- {
- isKnocked = true;//此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
- rb.velocity = new Vector2(knockbackDirection.x * -facingDir, knockbackDirection.y);
- yield return new WaitForSeconds(knockbackDuration);
- isKnocked = false;
- }
- //被击打后产生后退效果的函数
- #region 速度函数Velocity
- public virtual void SetZeroVelocity()
- {
- if(isKnocked)
- {
- return;
- }
- rb.velocity = new Vector2(0, 0);
- }//设置速度为0函数
-
- public virtual void SetVelocity(float _xVelocity, float _yVelocity)
- {
- if(isKnocked)
- return;此值通过卡住SetVelocity函数的方式用来阻止当一个角色被攻击时,会乱动的情况
-
- rb.velocity = new Vector2(_xVelocity, _yVelocity);//将rb的velocity属性设置为对应的想要的二维向量。因为2D游戏的速度就是二维向量
- FlipController(_xVelocity);//在其他设置速度的时候调用翻转控制器
- }//控制速度的函数,此函数在其他State中可能会使用,但仅能通过player.SeVelocity调用
- #endregion
- #region 翻转函数Flip
- public virtual void Flip()
- {
- facingDir = facingDir * -1;
- facingRight = !facingRight;
- transform.Rotate(0, 180, 0);//旋转函数,transform不需要额外定义,因为他是自带的
- }//翻转函数
-
- public virtual void FlipController(float _x)//目前设置x,目的时能在空中时也能转身
- {
- if (_x > 0 && !facingRight)//当速度大于0且没有朝右时,翻转
- {
- Flip();
- }
- else if (_x < 0 && facingRight)
- {
- Flip();
- }
- }
- #endregion
- #region 碰撞函数Collision
- public virtual bool IsGroundDetected()
- {
- return Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
- }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics2D.Raycast.html
- //xxxxxxxx() => xxxxxxxx == xxxxxxxxxx() return xxxxxxxxx;
- public virtual bool IsWallDetected()
- {
- return Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
- }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics2D.Raycast.html
- //xxxxxxxx() => xxxxxxxx == xxxxxxxxxx() return xxxxxxxxx;
- protected virtual void OnDrawGizmos()
- {
- Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
- Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
- Gizmos.DrawWireSphere(attackCheck.position, attackCheckRadius);//https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Gizmos.DrawWireSphere.html
- //绘制具有中心和半径的线框球体。
- }//画图函数
- #endregion
- public void MakeTransprent(bool isClear)
- {
- if (isClear)
- sr.color = Color.clear;
- else
- sr.color = Color.white;
- }
-
- public virtual void Die()
- {
-
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- 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 PlayerDeadState deadState { 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动画
- deadState = new PlayerDeadState(this, stateMachine, "Die");
-
-
- 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();
-
- if(Input.GetKeyDown(KeyCode.F))
- {
- skill.crystal.CanUseSkill();
- }
-
- }
- 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切换设置成一个函数,使其在所以情况下都能使用
-
-
- public override void Die()
- {
- base.Die();
-
- stateMachine.ChangeState(deadState);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class PlayerDeadState : PlayerState
- {
- public PlayerDeadState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
- {
- }
-
- public override void AnimationFinishTrigger()
- {
- base.AnimationFinishTrigger();
- }
-
- public override void Enter()
- {
- base.Enter();
- }
-
- public override void Exit()
- {
- base.Exit();
- }
-
- public override void Update()
- {
- base.Update();
-
- player.SetZeroVelocity();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEngine;
-
- public class Enemy : Entity
- {
- [SerializeField] protected LayerMask whatIsPlayer;
- [Header("Stun Info")]
- public float stunnedDuration;//stunned持续时间
- public Vector2 stunnedDirection;//stunned改变后的速度
- protected bool canBeStunned;//判断是否可以被反击
- [SerializeField] protected GameObject counterImage;//一个代表着是否可以被反击的信号
-
- [Header("Move Info")]
- public float moveSpeed;
- public float idleTime;
- public float battleTime;//多久能从battle状态中退出来
- private float defaultMoveSpeed;
-
- [Header("Attack Info")]
- public float attackDistance;
- public float attackCooldown;//攻击冷却
- [HideInInspector] public float lastTimeAttacked;//最后一次攻击的时间
-
-
- #region 类
- public EnemyStateMachine stateMachine { get; private set; }
-
- public string lastingAnimBoolName{ get; private set; }
-
- public virtual void AssignLastAnimName(string _animBoolName)
- {
- lastingAnimBoolName = _animBoolName;
- }
- #endregion
-
- protected override void Awake()
- {
- base.Awake();
- stateMachine = new EnemyStateMachine();
- defaultMoveSpeed = moveSpeed;
-
- }
- protected override void Start()
- {
- base.Start();
-
- }
-
-
- protected override void Update()
- {
- base.Update();
-
- stateMachine.currentState.Update();
-
- //Debug.Log(IsPlayerDetected().collider.gameObject.name + "I see");//这串代码会报错,可能使版本的物体,因为在没有找到Player的时候物体是空的,NULL,你想让他在控制台上显示就报错了
- }
-
- public virtual void FreezeTime(bool _timeFrozen)
- {
- if(_timeFrozen)
- {
- moveSpeed = 0;
- anim.speed = 0;
- }
- else
- {
- moveSpeed = defaultMoveSpeed;
- anim.speed = 1;
- }
- }
-
- protected virtual IEnumerator FreezeTimeFor(float _seconds)
- {
- FreezeTime(true);
-
- yield return new WaitForSeconds(_seconds);
-
- FreezeTime(false);
- }
- #region Counter Attack Window
- public virtual void OpenCounterAttackWindow()//打开可以反击的信号的函数
- {
- canBeStunned = true;
- counterImage.SetActive(true);
- }
- public virtual void CloseCounterAttackWindow()//关闭可以反击的信号的函数
- {
- canBeStunned = false;
- counterImage.SetActive(false);
- }
- #endregion
-
-
-
- public virtual bool CanBeStunned()//这里的主要目的是完成在被反击过后能立刻关闭提示窗口
- {
- if (canBeStunned)
- {
- CloseCounterAttackWindow();
- return true;
- }
- return false;
-
- }
- public virtual void AnimationFinishTrigger() => stateMachine.currentState.AnimationFinishTrigger();//动画完成时调用的函数,与Player相同
- public virtual RaycastHit2D IsPlayerDetected() => Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, 7, whatIsPlayer);//用于从射线投射获取信息的结构。
- //该函数的返回值可以变,可以只返回bool,也可以是碰到的结构
-
- protected override void OnDrawGizmos()
- {
- base.OnDrawGizmos();
-
- Gizmos.color = Color.yellow;//把线改成黄色
- Gizmos.DrawLine(transform.position, new Vector3(transform.position.x + attackDistance * facingDir, transform.position.y));//用来判别是否进入attackState的线
- }
-
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class EnemyState
- {
-
- protected Enemy enemyBase;
-
- protected EnemyStateMachine stateMachine;
-
- protected Rigidbody2D rb;//小简化
-
- protected bool triggerCalled;
-
- private string animBoolName;
-
- protected float stateTimer;
-
-
- public EnemyState(Enemy _enemyBase, EnemyStateMachine _stateMachine, string _animBoolName)
- {
- this.enemyBase = _enemyBase;
- this.stateMachine = _stateMachine;
- this.animBoolName = _animBoolName;
- }
- public virtual void Enter()
- {
- triggerCalled = false;
- enemyBase.anim.SetBool(animBoolName, true);
- rb = enemyBase.rb;//小简化
- }
- public virtual void Update()
- {
- stateTimer -= Time.deltaTime;
- }
- public virtual void Exit()
- {
- enemyBase.anim.SetBool(animBoolName, false);
-
- enemyBase.AssignLastAnimName(animBoolName);
- }
-
- //动画完成时调用的函数,与Player相同
- public virtual void AnimationFinishTrigger()
- {
- triggerCalled = true;
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEditorInternal;
- using UnityEngine;
-
- public class Enemy_Skeleton : Enemy
- {
- #region 类State
- public SkeletonIdleState idleState { get; private set; }
- public SkeletonMoveState moveState { get; private set; }
- public SkeletonBattleState battleState { get; private set; }
- public SkeletonAttackState attackState { get; private set; }
- public SkeletonStunnedState stunnedState { get; private set; }
- public SkeletonDeadState deadState { get; private set; }
- #endregion
- protected override void Awake()
- {
- base.Awake();
-
- idleState = new SkeletonIdleState(this, stateMachine, "Idle", this);
- moveState = new SkeletonMoveState(this,stateMachine, "Move", this);
- battleState = new SkeletonBattleState(this, stateMachine, "Move", this);
- attackState = new SkeletonAttackState(this, stateMachine, "Attack", this);
- stunnedState = new SkeletonStunnedState(this, stateMachine, "Stunned", this);
- deadState = new SkeletonDeadState(this, stateMachine, "Idle", this);
-
- }
-
- protected override void Start()
- {
- base.Start();
- stateMachine.Initialize(idleState);
- }
-
- protected override void Update()
- {
- base.Update();
-
-
- }
-
- public override bool CanBeStunned()
- {
- if (base.CanBeStunned())//在这里重写主要是因为只有在Skeleton里面才能调用stunnedState
- {
- stateMachine.ChangeState(stunnedState);
- return true;
- }
- return false;
- }
- //重写后不仅能达成在完成被反击后关闭提示窗口,还能转换为stunnedState
- public override void Die()
- {
- base.Die();
- stateMachine.ChangeState(deadState);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class SkeletonDeadState : EnemyState
- {
- private Enemy_Skeleton enemy;
- public SkeletonDeadState(Enemy _enemyBase, EnemyStateMachine _stateMachine, string _animBoolName,Enemy_Skeleton _enemy) : base(_enemyBase, _stateMachine, _animBoolName)
- {
- this.enemy = _enemy;
- }
-
- public override void Enter()
- {
- base.Enter();
-
- enemy.anim.SetBool(enemy.lastingAnimBoolName, true);
- enemy.anim.speed = 0;
- enemy.cd.enabled = false;
-
- stateTimer = .1f;
- }
-
- public override void Update()
- {
- base.Update();
-
- if (stateTimer > 0)
- rb.velocity = new Vector2(0, 10);
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。