Entity类 包含了基本对象的方法与字段
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Entity : MonoBehaviour
{
[Header("碰撞检测相关")]
[SerializeField] protected Transform groundCheck;
[SerializeField] protected float groundCheckDistance;
[SerializeField] protected Transform wallCheck;
[SerializeField] protected float wallCheckDistance;
[SerializeField] protected LayerMask whatIsGround;
public int facingDirection { get; protected set; } = 1;
public bool facingRight = true;
#region 组件们
public Animator animator{ get; private set;}
public Rigidbody2D rigidbody2D{ get; private set;}
#endregion
// Start is called before the first frame update
#region 射线检测
public virtual bool IsWallDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDirection,wallCheckDistance,whatIsGround);
public virtual bool IsGroundDetected() => Physics2D.Raycast(groundCheck.position,Vector2.down,groundCheckDistance, whatIsGround);
protected virtual void OnDrawGizmosSelected()
{
//Gizmos的DrawLine函数参数 1.画线的起点位置 2.方向向量
//从检测物体位置开始垂直向下检测距离个单位的线段
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 void SetPlyaerVector(float x, float y)
{
rigidbody2D.velocity = new Vector2(x, y);
//只有在playerMove的状态中会去调用该方法使得控制更加安全精准
FlipController(x);
}
//玩家默认朝向
//应该是供外部调用查看是否目前为反转的状态
//翻转函数
public void Flip()
{
//取巧的设计 调用函数自动切换状态
facingDirection = facingDirection * -1;
facingRight = !facingRight;
transform.Rotate(0f, 180f, 0f);
}
//调用翻转函数的方法
/// <summary>
/// 自纠错方法
/// 当玩家速度是x轴的正方向时如果这时候的面朝向左就进行一次转向操作
/// 反之亦然
/// </summary>
///
/// //只有在playerMove的状态中会去调用该方法使得控制更加安全精准
public void FlipController(float _x)
{
if (_x > 0 && !facingRight)
{
Flip();
}
else if(_x < 0 && facingRight)
{
Flip();
}
}
#endregion
protected virtual void Awake()
{
}
protected virtual void Start()
{
rigidbody2D = GetComponent<Rigidbody2D>();
animator = GetComponentInChildren<Animator>();
}
// Update is called once per frame
protected virtual void Update()
{
}
}
Enemy类 包含了敌人基本信息
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : Entity
{
[SerializeField]
protected LayerMask WhatIsPlayer;
[Header("移动相关")]
public float moveSpeed = 1.0f;
public float idleTime = 1.0f;
[Header("攻击信息")] public float attackDistance;
public EnemyStateMachine _StateMachine { get; private set; }
// Start is called before the first frame update
protected virtual void Awake()
{
base.Awake();
_StateMachine = new EnemyStateMachine();
}
protected virtual void Start()
{
base.Start();
}
// Update is called once per frame
protected virtual void Update()
{
base.Update();
_StateMachine.currentState.Update();
Debug.Log(IsPlayerDetected().collider.gameObject.name);
}
protected override void OnDrawGizmosSelected()
{
base.OnDrawGizmosSelected();
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position,new Vector3(transform.position.x + attackDistance * facingDirection,transform.position.y));
}
//玩家检测脚本
public virtual RaycastHit2D IsPlayerDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDirection ,50, WhatIsPlayer);
}
继承了敌人类的骷髅小兵类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Skeleton : Enemy
{
#region State
public SkeletonIdleState IdleState { get; private set; }
public SkeletonMoveState MoveState { get; private set; }
public EnemyBattleState BattleState { 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 EnemyBattleState(this,_StateMachine,"Move",this);
}
protected override void Start()
{
base.Start();
_StateMachine.Initialize(IdleState);
}
protected override void Update()
{
base.Update();
}
}
敌人状态基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyState
{
//不继承mono是在enemy中建立了一个公共的mono模块
//状态类应当包含敌人与敌人身上的状态机
protected Enemy EnemyBase;
protected EnemyStateMachine _stateMachine;
//人物动画
protected bool triggerCalled;
protected string animBoolName;
//构建函数为状态赋值
/// <param name="enemy">当前状态的敌人对象</param>
/// <param name="stateMachine">当前状态的状态机</param>
/// <param name="animBoolName">动画名称</param>
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.animator.SetBool(this.animBoolName, true);
}
public virtual void Update()
{
stateTimer -= Time.deltaTime;
}
public virtual void Exit()
{
EnemyBase.animator.SetBool(this.animBoolName, false);
}
}
状态机类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyStateMachine
{
//当前的怪物状态
public EnemyState currentState { get; private set; }
//初始化状态机在enemy对象类中 就是去执行默认的状态
public void Initialize(EnemyState initialState)
{
currentState = initialState;
currentState.Enter();
}
public void ChangeState(EnemyState newState)
{
currentState.Exit();
currentState = newState;
currentState.Enter();
}
}
地面状态基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SkeletonGroundState : EnemyState
{
protected Enemy_Skeleton enemy;
public SkeletonGroundState(Enemy enemyBase, EnemyStateMachine stateMachine, string animBoolName,Enemy_Skeleton enemy) : base(enemy, stateMachine, animBoolName)
{
this.enemy = enemy;
}
public override void Enter()
{
base.Enter();
}
public override void Update()
{
base.Update();
if (enemy.IsPlayerDetected())
{
_stateMachine.ChangeState(enemy.BattleState);
}
}
public override void Exit()
{
base.Exit();
}
}
战斗类状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyBattleState : EnemyState
{
private Transform player;
private Enemy_Skeleton enemy;
private int moveDir;
public EnemyBattleState(Enemy enemyBase, EnemyStateMachine stateMachine, string animBoolName,Enemy_Skeleton enemy) : base(enemy, stateMachine, animBoolName)
{
this.enemy = enemy;
}
public override void Enter()
{
player = GameObject.Find("player").transform;
base.Enter();
}
public override void Update()
{
base.Update();
if (enemy.IsPlayerDetected())
{
if (enemy.IsPlayerDetected().distance < enemy.attackDistance)
{
Debug.Log("Enemy detected");
enemy.SetPlyaerVector(0,0);
return;
}
}
if (player.position.x > enemy.transform.position.x)
{
moveDir = 1;
}
else
{
moveDir = -1;
}
enemy.SetPlyaerVector(enemy.moveSpeed * moveDir,enemy.rigidbody2D.velocity.y);
}
public override void Exit()
{
base.Exit();
}
}