【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Clone_Skill : Skill
{
[Header("Clone")]
[SerializeField] private GameObject clonePrefah;//克隆原型
[SerializeField] private float cloneDuration;//克隆持续时间
public void CreateClone(Transform _clonePosition)//传入克隆位置
{
GameObject newClone = Instantiate(clonePrefah);//创建新的克隆//克隆 original 对象并返回克隆对象。
//https://docs.unity3d.com/cn/current/ScriptReference/Object.Instantiate.html
newClone.GetComponent().SetupClone(_clonePosition,cloneDuration);//调试clone的位置,同时调试克隆持续时间
//Controller绑在克隆原型上的,所以用GetComponents,
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//Clone_Skill_Controller是绑在Clone体上的也就是Prefah上的
public class Clone_Skill_Controller : MonoBehaviour
{
private SpriteRenderer sr;//定义Sr
[SerializeField] private float colorLoosingSpeed;//加速消失时间
private float cloneTimer;//定时器
private void Awake()
{
sr = GetComponent();//拿到Sr
}
private void Update()
{
cloneTimer -= Time.deltaTime;
if(cloneTimer < 0)
{
sr.color = new Color(1, 1, 1,sr.color.a-(Time.deltaTime * colorLoosingSpeed));//设置sr消失
}
}
public void SetupClone(Transform _newTransform,float _cloneDuration)
{
transform.position = _newTransform.position;//这个函数实现了将克隆出来的对象的位置与Dash之前的位置重合的效果
cloneTimer = _cloneDuration;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SkillManager : MonoBehaviour
{
public static SkillManager instance;
public Dash_Skill dash { get; private set; }
public Clone_Skill clone { get; private set; }
private void Awake()
{
if (instance != null)
{
Destroy(instance.gameObject);
}
else
instance = this;
}
private void Start()
{
dash = GetComponent();
clone = GetComponent();
}
}
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;
[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 PlayerPrimaryAttackState primaryAttack { get; private set; }
public PlayerCounterAttackState counterAttack { get; private set; }
public SkillManager skill { 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, "Jump");//wallJump也是Jump动画
primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
counterAttack = new PlayerCounterAttackState(this, stateMachine, "CounterAttack");
//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();
}
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切换设置成一个函数,使其在所以情况下都能使用
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerDashState : PlayerState
{ //由Ground进入
public PlayerDashState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
player.skill.clone.CreateClone(player.transform);//调用克隆函数,并传入当前位置已调试clone的位置
stateTimer = player.dashDuration;设置Dash可以保持的值
}
public override void Exit()
{
base.Exit();
player.SetVelocity(0, rb.velocity.y);//当退出时使速度为0防止动作结束后速度不变导致的持续移动
}
public override void Update()
{
base.Update();
if(!player.IsGroundDetected()&&player.IsWallDetected())//修复无法在空中dash直接进入wallSlide,修复在wallslide可以dash
//因为一旦在wallSlide里dash,就会直接进wallSlide,当然还有更简单的方法
{
stateMachine.ChangeState(player.wallSlide);
}
player.SetVelocity(player.dashSpeed * player.dashDir, 0);//这个写在Update里,防止在x轴方向减速了,同时Y轴写成0,以防止dash还没有完成就从空中掉下去了
if (stateTimer < 0)当timer小于0,切换
{
stateMachine.ChangeState(player.idleState);
}
}
}