//注意:此文章中的代码将update写成了updata,所以无法正常使用,参考时请自主更改
Entity.cs
将原本属于player.cs的变量与函数提取到Entity中方便复用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Entity : MonoBehaviour
{
[Header("Collision info")]
[SerializeField] protected Transform groundCheck;
[SerializeField] protected float groundCheckDistance;
[SerializeField] protected Transform wallCheck;
[SerializeField] protected float wallCheckDistance;
[SerializeField] protected LayerMask whatIsGround;
//flip Info
public int facingDir { get; private set; } = 1;
protected bool facingRight = true;
#region Components
public Rigidbody2D rb { get; private set; }
public Animator anim { get; private set; }
#endregion
protected virtual void Awake()
{
}
protected virtual void Start()
{
anim = GetComponentInChildren<Animator>();
rb = GetComponent<Rigidbody2D>();
}
protected virtual void Update()
{
}
#region Velocity
public void ZeroVelocity()
{
rb.velocity = new Vector2(0, 0);
}
public void SetVelocity(float _xVelocity, float _yVelocity)
{
rb.velocity = new Vector2(_xVelocity, _yVelocity);
FlipController(_xVelocity);
}
#endregion
#region Collision
public virtual bool IsGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
public virtual bool IsWallDetected() => Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
protected virtual void OnDrawGizmos()
{
Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x - wallCheckDistance, wallCheck.position.y));
}
#endregion
#region Flip
public virtual void Flip()
{
facingDir = facingDir * -1;
facingRight = !facingRight;
transform.Rotate(0, 180, 0);
}
public virtual void FlipController(float _x)
{
if (_x > 0 && !facingRight)
Flip();
else if (_x < 0 && facingRight)
Flip();
}
#endregion
}
修改后的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 bool isBusy { get; private set; }
[Header("Move Info")]
[SerializeField] public float moveSpeed = 12;
[SerializeField] public float jumpForce = 12;
[Header("Dash Info")]
[SerializeField] private float dashColdown;
[SerializeField] private float dashUsageTimer;
[SerializeField] public float dashSpeed;
[SerializeField] public float dashDuration;
[SerializeField] 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; }
#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, "WallJump");
primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
//this 就是 player
}
protected override void Start()
{
base.Start();
stateMachine.Initialize(idleState);
}
public float timer;
public float cooldown = 5;
private void Update()//在mano种update会自动刷新但其他没有mano的不会故需要在这个updata中调用函数以实现
//stateMachine中的update
{
base.Updata();
CheckForDashInput();
stateMachine.currentState.Update();
timer -= Time.deltaTime;
if (timer < 0 && Input.GetKeyDown(KeyCode.R))
{
timer = cooldown;
}
}
public IEnumerator BusyFor(float _seconds)
{
isBusy = true;
yield return new WaitForSeconds(_seconds);
isBusy = false;
}
public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
private void CheckForDashInput()
{
if (IsWallDetected())
return;
dashUsageTimer -= Time.deltaTime;
if (Input.GetKeyDown(KeyCode.LeftShift)&& dashUsageTimer<0)
{
dashUsageTimer = dashColdown;
dashDir = Input.GetAxisRaw("Horizontal");
if(dashDir == 0)
{
dashDir = facingDir;
}
stateMachine.ChangeState(dashState);
}
}
}