可以做水果的团购网站有哪些,企业展示型网站程序,桂林北站地址,网页制作工具是Unity开发2D类银河恶魔城游戏学习笔记
Unity教程#xff08;零#xff09;Unity和VS的使用相关内容 Unity教程#xff08;一#xff09;开始学习状态机 Unity教程#xff08;二#xff09;角色移动的实现 Unity教程#xff08;三#xff09;角色跳跃的实现 Unity教程零Unity和VS的使用相关内容 Unity教程一开始学习状态机 Unity教程二角色移动的实现 Unity教程三角色跳跃的实现 Unity教程四碰撞检测 Unity教程五角色冲刺的实现 Unity教程六角色滑墙的实现 Unity教程七角色蹬墙跳的实现 Unity教程八角色攻击的基本实现 Unity教程九角色攻击的改进
Unity教程十Tile Palette搭建平台关卡 Unity教程十一相机 Unity教程十二视差背景
Unity教程十三敌人状态机 Unity教程十四敌人空闲和移动的实现 Unity教程十五敌人战斗状态的实现 如果你更习惯用知乎 Unity开发2D类银河恶魔城游戏学习笔记目录 文章目录 Unity开发2D类银河恶魔城游戏学习笔记前言一、概述二、实现Player的检测三、创建接地状态三、实现战斗状态(1)创建战斗状态(2)状态切换 总结 完整代码Enemy.csSkeletonGroundedState.csSkeletonIdleState.csSkeletonMoveState.csSkeletonBattleState.csEnemy_Skeleton.cs 前言
本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记如有错误欢迎指正。
本节实现敌人的战斗状态。 对应b站视频 【Unity教程】从0编程制作类银河恶魔城游戏P50
一、概述
本节中我们实现骷髅的战斗状态。 骷髅小怪在检测到玩家时会向着玩家移动。在移动到一定距离时停止移动进入攻击状态。 由于我们想让骷髅在空闲和移动时均能转入战斗状态我们创建超级状态接地状态直接写接地状态到战斗状态的切换即可。 状态切换条件如下 二、实现Player的检测
玩家的检测在Enemy基类中实现。 碰撞检测的详细讲解见Unity教程四碰撞检测
这里我们不再仅仅使用bool类型作为函数的返回值而是使用RaycastHit2D返回更详细的信息。 RaycastHit2DUnity官方手册 Raycast包含的变量如下表
变量介绍centroid用于执行投射的图元的质心collider射线命中的碰撞体distance从射线原点到撞击点的距离fraction射线上发生命中的距离的分数normal射线命中的表面的法线矢量point世界空间中射线命中碰撞体表面的点rigidbody附加到命中的对象的 Rigidbody2Dtransform命中的对象的变换
我们要新建一个过滤器WhatIsPlayer进行检测。 这里我们以骷髅的位置为起点向它面向的方向发射射线检测检测的最大距离设置为50.
为了方便调试我们还要绘制出攻击检测的线条在Enemy里对实体中的OnDrawGizmos()函数进行重写。 攻击检测的线条绘制起点为Enemy_Skeleton的位置向右attackDistance找到终点。 在Enemy中添加如下代码 [SerializeField] protected LayerMask WhatIsPlayer;[Header(Attack Info)]public float attackDistance;public virtual RaycastHit2D IsPlayerDetected()Physics2D.Raycast(transform.position, Vector2.right * facingDir, 50 ,WhatIsPlayer);protected override void OnDrawGizmos(){base.OnDrawGizmos();Gizmos.color Color.yellow;Gizmos.DrawLine(transform.position, new Vector3(transform.position.x attackDistance * facingDir, transform.position.y));}将Enemy_Skeleton的大小调大一点 创建一个新的WallCheck并拖到Enemy_Skeleton中 将Wallcheck往下拖一些以免与攻击检测重合。 在Enemy中重写OnDrawGizmos()换一个颜色绘制出攻击检测。 给attackDistancce赋一个恰当的值。
将Enemy_Skeleton中WhatIsPlayer改为Player 新建Player和Enemy层。 Player改为Player层Enemy_Skeleton改为Enemy层修改时选择将它们所有子物体也改为对应层次。
三、创建接地状态
创建接地状态SkeletonGroundedState它继承自EnemyState。 在子菜单中创建构造函数生成重写。 添加Enemy_Skeleton enermy传递骷髅小怪独有的变量和函数并修改构造函数。
//SkeletonGroundedState:骷髅接地状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonGroundedState : EnemyState
{protected Enemy_Skeleton enemy;public SkeletonGroundedState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy,string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy_enemy;}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();}
}将SkeletonIdleState和SkeletonMoveState的父类改为SkeletonGroundedState这时两个子类构造函数参数与父类相同可以删除原有构造函数和Enemy_Skeleton enemy直接在子菜单重新生成一个构造函数了。
三、实现战斗状态
(1)创建战斗状态
创建战斗状态SkeletonBattleState它继承自EnemyState。 在子菜单中创建构造函数生成重写。添加Enemy_Skeleton enermy并修改构造函数。 private Enemy_Skeleton enemy;public SkeletonBattleState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy_enemy;}在EnemySkeleton类中创建battleState。这里条件变量仍然选择“Move”因为战斗状态仍然播放移动动画。 #region 状态public SkeletonIdleState idleState { get; private set; }public SkeletonMoveState moveState { get; private set; }public SkeletonBattleState battleState { get; private set; }#endregionprotected override void Awake(){base.Awake();idleState new SkeletonIdleState(stateMachine,this,this,Idle);moveState new SkeletonMoveState(stateMachine, this,this, Move);battleState new SkeletonBattleState(stateMachine, this, this, Move);}(2)状态切换
当检测到玩家时骷髅由接地状态转换为战斗状态。 在SkeletonGroundedState的Update()函数中添加 public override void Update(){base.Update();if(enemy.IsPlayerDetected())stateMachine.ChangeState(enemy.battleState);}骷髅进入战斗状态时要随玩家位置的变化改变移动方向。因此我们引入player的位置这个变量通过它与骷髅位置的对比确定战斗状态骷髅移动的方向。 player.position.x enemy.transform.position.x玩家在骷髅右边移动方向向右 player.position.x enemy.transform.position.x玩家在骷髅左边移动方向向左 //SkeletonBattleState:骷髅战斗状态
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonBattleState : EnemyState
{private Transform player;private Enemy_Skeleton enemy;private int moveDir;public SkeletonBattleState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy_enemy;}public override void Enter(){base.Enter();player GameObject.Find(Player).transform;}public override void Exit(){base.Exit();}public override void Update(){base.Update();if(player.position.x enemy.transform.position.x)moveDir 1;else if(player.position.x enemy.transform.position.x)moveDir -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, enemy.rb.velocity.y);}
}
效果如下
而当玩家进入骷髅的攻击距离时骷髅停止移动切换为攻击状态。根据上述内容所讲骷髅与玩家的距离可由RaycastHit2D里的distance获得。攻击状态我们先控制输出代替具体攻击状态内容我们下一节再进行实现。 Update中添加如下代码 public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance enemy.attackDistance){Debug.Log(attack);enemy.ZeroVelocity();return;}}if(player.position.x enemy.transform.position.x)moveDir 1;else if(player.position.x enemy.transform.position.x)moveDir -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, enemy.rb.velocity.y);}总结 完整代码
Enemy.cs
添加碰撞检测和攻击距离变量实现攻击检测的函数和攻击检测的绘制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : Entity
{[SerializeField] protected LayerMask WhatIsPlayer;[Header(Move Info)]public float moveSpeed 1.5f;public float idleTime 2.0f;[Header(Attack Info)]public float attackDistance;public EnemyStateMachine stateMachine;protected override void Awake(){base.Awake();stateMachine new EnemyStateMachine();}protected override void Update(){base.Update();stateMachine.currentState.Update();}public virtual RaycastHit2D IsPlayerDetected()Physics2D.Raycast(transform.position, Vector2.right * facingDir, 50 ,WhatIsPlayer);protected override void OnDrawGizmos(){base.OnDrawGizmos();Gizmos.color Color.yellow;Gizmos.DrawLine(transform.position, new Vector3(transform.position.x attackDistance * facingDir, transform.position.y));}
}
SkeletonGroundedState.cs
创建接地状态由移动和空闲状态继承。实现切换到战斗状态。
//SkeletonGroundedState:骷髅接地状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonGroundedState : EnemyState
{protected Enemy_Skeleton enemy;public SkeletonGroundedState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy,string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy_enemy;}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (enemy.IsPlayerDetected())stateMachine.ChangeState(enemy.battleState);}
}
SkeletonIdleState.cs
修改构造函数
//SkeletonIdleState:骷髅空闲状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonIdleState : SkeletonGroundedState
{public SkeletonIdleState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton enemy, string _animBoolName) : base(_stateMachine, _enemyBase, enemy, _animBoolName){}public override void Enter(){base.Enter();stateTimer enemy.idleTime;}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (stateTimer 0)stateMachine.ChangeState(enemy.moveState);}
}SkeletonMoveState.cs
//SkeletonMoveState:骷髅移动状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonMoveState : SkeletonGroundedState
{public SkeletonMoveState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton enemy, string _animBoolName) : base(_stateMachine, _enemyBase, enemy, _animBoolName){}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();enemy.SetVelocity(enemy.moveSpeed*enemy.facingDir,enemy.rb.velocity.y);if(!enemy.isGroundDetected() || enemy.isWallDetected()){enemy.Flip();stateMachine.ChangeState(enemy.idleState);}}
}SkeletonBattleState.cs
创建战斗状态实现切换到攻击状态和随玩家移动改变方向。
//SkeletonBattleState:骷髅战斗状态
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SkeletonBattleState : EnemyState
{private Transform player;private Enemy_Skeleton enemy;private int moveDir;public SkeletonBattleState(EnemyStateMachine _stateMachine, Enemy _enemyBase, Enemy_Skeleton _enemy, string _animBoolName) : base(_stateMachine, _enemyBase, _animBoolName){enemy_enemy;}public override void Enter(){base.Enter();player GameObject.Find(Player).transform;}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (enemy.IsPlayerDetected()){if (enemy.IsPlayerDetected().distance enemy.attackDistance){Debug.Log(attack);enemy.ZeroVelocity();return;}}if(player.position.x enemy.transform.position.x)moveDir 1;else if(player.position.x enemy.transform.position.x)moveDir -1;enemy.SetVelocity(enemy.moveSpeed * moveDir, enemy.rb.velocity.y);}
}
Enemy_Skeleton.cs
创建战斗状态
//Enemy_Skeleton:骷髅敌人
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy_Skeleton : Enemy
{#region 状态public SkeletonIdleState idleState { get; private set; }public SkeletonMoveState moveState { get; private set; }public SkeletonBattleState battleState { get; private set; }#endregionprotected override void Awake(){base.Awake();idleState new SkeletonIdleState(stateMachine,this,this,Idle);moveState new SkeletonMoveState(stateMachine, this,this, Move);battleState new SkeletonBattleState(stateMachine, this, this, Move);}protected override void Start(){base.Start();stateMachine.Initialize(idleState);}protected override void Update(){base.Update();}}