Unity教程(三)角色跳跃的实现

Unity开发类银河恶魔城游戏学习笔记

Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现



前言

本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。

本节进行角色跳跃的实现。

对应b站视频:
【Unity教程】从0编程制作类银河恶魔城游戏P31
精灵表素材。
素材链接:https://pan.baidu.com/s/1PnN2t7xOcNpPDLteLm4EJw?pwd=7pec。
提取码: 7pec


一、概述

本节实现角色跳跃需要创建超级状态PlayerGroundedState接地状态和PlayerAirState空中状态。

超级状态是一种用来分层控制的状态,它之下可以有很多简单状态,能对简单状态进行控制。举例说明,比如接地状态下角色可以是移动和闲置的,符合某种条件时可以从接地状态转换成另一个超级状态空中状态,这时角色不能再移动和闲置,但可以在空中状态下转换状态。通过这种方式创建分层状态机,就是状态机中又嵌套了一个状态机,通过分离来减少过渡条件,减少状态机的复杂度。我参照了文章

状态转换条件如下:
在这里插入图片描述

可以看到转换到跳跃状态是在超级状态接地状态中进行的,这保证了无论角色处于闲置还是移动状态时都能进行跳跃。如果没有接地状态的控制可能会出现这种情况,角色可以在空中不断继续跳跃升天。

在实现时我们需要添见PlayerJumpState跳跃状态和两个超级状态PlayerGroundedState接地状态和PlayerAirState空中状态,它们都继承自状态基类PlayerState。同时我们需要修改PlayerIdleState空闲状态和PlayerMoveState移动状态让它们继承自PlayerGroundedState接地状态。具体如图:
在这里插入图片描述

二、创建超级状态

创建两个超级状态PlayerGroundedState接地状态和PlayerAirState空中状态。
在这里插入图片描述
把它们继承的类改为状态基类PlayerState,并生成构造函数、生成重写。基本操作具体讲解见
Unity教程(零)Unity和VS的使用相关内容
在这里插入图片描述

修改PlayerIdleState空闲状态和PlayerMoveState移动状态让它们继承自PlayerGroundedState接地状态
在这里插入图片描述
在这里插入图片描述


三、创建跳跃状态的混合树动画

层次面板中选中Animator,在Animation面板中创建两个动画playerJump跳跃动画和playerFall下落动画
playerJump精灵表标号41-43,采样率改为10
playerFall精灵表标号46-48,采样率改为10
具体讲解见Unity教程(零)Unity和VS的使用相关内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

你会看到动画师中多出两个状态
在这里插入图片描述


删掉palyerJump和playerFall这两个块,创建混合树动画,命名为Jump/Fall
右键->Create State->From New Blend Tree
在这里插入图片描述在这里插入图片描述
把混合树参数重命名为yVelocity,到时候我们需要动画按照角色y方向速度混合。

双击Jump/Fall混合树进入混合树的进一步编辑
在这里插入图片描述
在右侧面板添加两个动画
"+"号->Add Motion Field->拖入动画
在这里插入图片描述
在这里插入图片描述
结果如下:
在这里插入图片描述
在这里插入图片描述
勾掉Automate Threshholds,将PlayerFall的Threshhold改为-1
在这里插入图片描述
关于Threshold阈值的理解
参照博客Unity动画系统详解5:BlendTree混合树是什么?官方手册 混合树1D混合
在此混合树中我们使用的是1D混合,Threshold代表的是混合树参数在等于阈值时完全使用这个动画。
在这里插入图片描述
顺带一提,这个钟表图标Time Scale可以调节动画的播放速度,比如你想让动画播放速度变为原来的2倍,可以把它设置为2。
在这里插入图片描述
在这里可以检查混合树的效果
将右下Blend Tree这一小条向上拖
在这里插入图片描述
在这里插入图片描述
拖动Blend Tree的参数滑动条查看不同参数时的动画
在这里插入图片描述
可以看到动画随参数变化
在这里插入图片描述


连接状态机,并添加过渡条件Jump,并修改过渡设置
如需更详细过程讲解,见Unity教程(零)Unity和VS的使用相关内容
添加条件变量
在这里插入图片描述
连接过渡
在这里插入图片描述

进入Jump/Fall的过渡
在这里插入图片描述
退出Jump/Fall的过渡
在这里插入图片描述


四、跳跃的实现

跳跃的实现要经过这样一个过程:
在角色处于接地状态PlayerGroundedState时接收到跳跃键按下的输入,转换到跳跃状态PlayerJumpState,在跳跃状态中设置跳跃速度。然后当跳跃至顶点时角色开始下落,在y方向的速度开始为负,这时切换到空中状态PlayerAirState。在落到地面时,y方向速度为0,角色切换为闲置状态。

在这里插入图片描述
创建脚本PlayerJumpState,继承于PlayerState,生成构造函数和重写。

在Player添加PlayerJumpState和PlayerAirState两个状态,在Awake函数中创建这两个状态,它们都通过条件变量Jump去控制动画。

    #region 状态
    public PlayerStateMachine StateMachine { get; private set; }
    public PlayerState idleState { get; private set; }
    public PlayerState moveState { get; private set; }
    public PlayerState jumpState { get; private set; }
    public PlayerState airState { get; private set; }
    #endregion

    //创建对象
    private void Awake()
    {
        StateMachine = new PlayerStateMachine();

        idleState = new PlayerIdleState(StateMachine, this, "Idle");
        moveState = new PlayerMoveState(StateMachine, this, "Move");
        jumpState = new PlayerJumpState(StateMachine, this, "Jump");
        airState = new PlayerAirState(StateMachine, this, "Jump");

        anim = GetComponentInChildren<Animator>();
        rb = GetComponent<Rigidbody2D>();

    }

完善PlayerJumpState实现设置跳跃和切换状态,实现大致如下:
在这里插入图片描述

在player中添加变量jumpForce用以设置跳跃

    public float jumpForce = 12f;

顺带Gravity Scale改为3.5
在这里插入图片描述

接下来在PlayerJumpState中进行完善。
在进入Jump状态时设置y方向速度实现跳跃。

    public override void Enter()
    {
        base.Enter();

        rb.velocity = new Vector2(rb.velocity.x, player.jumpForce);
    }

在y方向速度开始小于0时,角色下落切换到空中状态

    public override void Update()
    {
        base.Update();

        if(rb.velocity.y < 0)
            stateMachine.ChangeState(player.airState);
    }

完善PlayerGroundedState,按下空格时切换到跳跃状态
    //更新
    public override void Update()
    {
        base.Update();

        if (Input.GetKeyDown(KeyCode.Space))
            stateMachine.ChangeState(player.jumpState);
    }

完善PlayerAirState,实现落地后切换为闲置状态
    public override void Update()
    {
        base.Update();

        if(rb.velocity.y == 0)
            stateMachine.ChangeState(player.idleState);
    }

完成后运行,效果如下:
在这里插入图片描述


你会发现还有一个小问题,下落的时候并没有切换到下落的动画,依旧是向上跳跃时的,因为我们还没有设置混合树的参数。
我们在PlayerState中设置,确保它在跳跃和空中状态都可用。

    //更新状态
    public virtual void Update()
    {
        xInput = Input.GetAxisRaw("Horizontal");
        player.anim.SetFloat("yVelocity", rb.velocity .y);
    }

这样我们就实现了跳跃和下落动画的混合
在这里插入图片描述


总结 完整代码

Player.cs

添加创建跳跃状态和空中状态,定义跳跃力度

//Player:玩家
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{

    [Header("Move Info")]
    public float moveSpeed = 8f;
    public int facingDir { get; private set; } = 1;
    private bool facingRight = true;

    public float jumpForce = 12f;


    #region 组件
    public Animator anim { get; private set; }
    public Rigidbody2D rb { get; private set; }
    #endregion


    #region 状态
    public PlayerStateMachine StateMachine { get; private set; }
    public PlayerState idleState { get; private set; }
    public PlayerState moveState { get; private set; }
    public PlayerState jumpState { get; private set; }
    public PlayerState airState { get; private set; }
    #endregion

    //创建对象
    private void Awake()
    {
        StateMachine = new PlayerStateMachine();

        idleState = new PlayerIdleState(StateMachine, this, "Idle");
        moveState = new PlayerMoveState(StateMachine, this, "Move");
        jumpState = new PlayerJumpState(StateMachine, this, "Jump");
        airState = new PlayerAirState(StateMachine, this, "Jump");

        anim = GetComponentInChildren<Animator>();
        rb = GetComponent<Rigidbody2D>();

    }

    // 设置初始状态
    private void Start()
    {
        StateMachine.Initialize(idleState);
    }

    // 更新
    private void Update()
    {
        StateMachine.currentState.Update();
    }

    //设置速度
    public void SetVelocity(float _xVelocity, float _yVelocity)
    {
        rb.velocity = new Vector2(_xVelocity, _yVelocity);
        FlipController(_xVelocity);
    }

    //翻转实现
    public void Flip()
    {
        facingDir = -1 * facingDir;
        facingRight = !facingRight;
        transform.Rotate(0, 180, 0);
    }
    //翻转控制
    public void FlipController(float _x)
    {
        if (_x > 0 && !facingRight)
            Flip();
        else if(_x < 0 && facingRight)
            Flip();
    }
}

PlayerGroundedState.cs

实现接地状态切换到跳跃,并且被PlayerIdleState,PlayerMoveState继承

//超级状态PlayerGroundedState:接地状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerGroundedState : PlayerState
{
    //构造函数
    public PlayerGroundedState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName)
    {
    }

    //进入
    public override void Enter()
    {
        base.Enter();
    }

    //退出
    public override void Exit()
    {
        base.Exit();
    }

    //更新
    public override void Update()
    {
        base.Update();

        if (Input.GetKeyDown(KeyCode.Space))
            stateMachine.ChangeState(player.jumpState);
    }
}

PlayerJumpState.cs

实现设置跳跃速度,实现切换到PlayerAirState空中状态

//PlayJumpState:跳跃状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerJumpState : PlayerState
{
    public PlayerJumpState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();

        rb.velocity = new Vector2(rb.velocity.x, player.jumpForce);
    }

    public override void Exit()
    {
        base.Exit();
    }

    public override void Update()
    {
        base.Update();

        if(rb.velocity.y < 0)
            stateMachine.ChangeState(player.airState);
    }
}

PlayerAirState.cs

实现切换到闲置状态

//超级状态PlayerAirState:空中状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAirState : PlayerState
{
    //构造函数
    public PlayerAirState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName)
    {
    }

    //进入
    public override void Enter()
    {
        base.Enter();
    }

    //退出
    public override void Exit()
    {
        base.Exit();
    }

    //更新
    public override void Update()
    {
        base.Update();

        if(rb.velocity.y == 0)
            stateMachine.ChangeState(player.idleState);
    }
}

PlayerState.cs

实现混合树参数的设置

//PlayerState:状态基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerState
{

    protected PlayerStateMachine stateMachine;
    protected Player player;

    protected Rigidbody2D rb;

    protected float xInput;
    private string animBoolName;

    //构造函数
    public PlayerState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName)
    {
        this.stateMachine = _stateMachine;
        this.player = _player;
        this.animBoolName = _animBoolName;
    }

    //进入状态
    public virtual void Enter()
    {
        //进入动画播放条件变量设置
        player.anim.SetBool(animBoolName, true);

        //获取刚体
        rb = player.rb;
    }

    //更新状态
    public virtual void Update()
    {
        xInput = Input.GetAxisRaw("Horizontal");
        player.anim.SetFloat("yVelocity", rb.velocity .y);
    }

    //退出状态
    public virtual void Exit()
    {
        //退出动画播放条件变量设置
        player.anim.SetBool(animBoolName, false);
    }
}
  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity实现角色跳跃,你可以按照以下步骤进行操作: 1. 添加一个刚体组件到角色对象上。可以通过在Unity编辑器中选中角色对象,然后点击“Add Component”按钮,在搜索栏中输入“Rigidbody”,选择添加刚体组件。 2. 在角色对象上添加一个碰撞体组件。同样,在Unity编辑器中选中角色对象,点击“Add Component”按钮,在搜索栏中输入“Capsule Collider”(或者其他适合的碰撞体类型),选择添加碰撞体组件。 3. 创建一个脚本来控制角色跳跃行为。右键点击Hierarchy面板中的角色对象,选择“Create Empty”来创建一个空对象,将其命名为“JumpController”。然后,将该脚本附加到JumpController对象上。 4. 在JumpController脚本中,添加以下代码来实现跳跃行为: ```csharp using UnityEngine; public class JumpController : MonoBehaviour { public float jumpForce = 5f; private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) // 监听空格键按下事件 { rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); // 施加向上的力来实现跳跃 } } } ``` 5. 将JumpController对象拖拽到角色对象上,作为其子对象,并在Inspector面板中将其Position属性调整为合适的位置。 现在,当你按下空格键时,角色对象将受到向上的力,并实现跳跃效果。你可以根据需要调整跳跃力的大小(jumpForce变量)来控制角色跳跃高度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值