【Unity2DMobileGame_PirateBomb03】—— 创建游戏玩家

277 阅读5分钟

1.创建Player

添加游戏Player和添加游戏场景的物件是一样的,同样需要修改合适的像素点为32,过滤模式为点采样,还有压缩为None。

其次添加刚体与碰撞体。

为玩家设置Player覆盖层级NPC和碰撞层级同名为NPC,并修改Npc与其他物件的物理关系。使它与游戏环境不进行碰撞交互,只有在发生攻击行为是才会产生物理碰撞。如下图所示:

2.添加Player脚本

2.1 添加PlayerController.cs

创建名为PlayerController的脚本,并为玩家挂载这一脚本组件。

2.2 控制Player的基本移动

实现移动
获取刚体组件private Rigidbody2D rb;,定义移动速度为浮点型public float speed;

void Movement()
{
    // float horizontalInput = Input.GetAxis("Horizontal"); // 获取的值从-1~1,包括小数
    
    float horizontalInput = Input.GetAxisRaw("Horizontal"); // 获取的值从-1~1,不包含小数
    rb.velocity = new Vector2(horizontalInput * speed, rb.velocity.y); // 使用物理向量的速度固定移动速度 y保持不变,x为输入*速度
}

Input.GetAxis("Horizontal")获取的值是-1~1包括小数,所以游戏中当按下方向键的时候,人物的移动速度是由小逐渐变大,有缓冲的效果。使用GetAxisRaw进行快节奏的移动,它是不包含小数字的。

控制翻转
在移动函数内通过修改本地坐标来进行人物翻转,是坐标值等于一个新的三位向量Vector3,因为它拥有x,y,z轴。当输入值horizontalInput为-1,向左移动时为x=-1,horizontalInput=1,向右移动x=1,x与horizontalInput的值是一致的,y和z轴保持不变。

// 修改transform的本地坐标来进行翻转
if (horizontalInput != 0)
    transform.localScale = new Vector3(horizontalInput, 1, 1);

2.3 控制Player的跳跃

定义一个辅助函数用来专门收集玩家的输入操作,对输入的按键进行判断,当输入为空格时可以进行跳跃。这里可以先用一个bool型的变量对是否可以进行跳跃进行标记。public bool isCanJump;
辅助函数只用来对按压的键位进行判断。

void CheckInput()
{
    if (Input.GetButtonDown("Jump"))
        isCanJump = true;
}

跳跃函数

void Jump()
{
    if (isCanJump)
    {
        rb.velocity = new Vector2(rb.velocity.x, jumpForce);
        isCanJump = false;
    }
}

跳跃的向量需要值得注意的是,x的值保持不变,但是不能写成0,这样会导致player不能向左或者向右移动。跳跃以后需要把按键操作清零,不然会跳跃到顶。

2.4 解决跳跃bug

目前存在的bug

  1. 跳跃起来的速度和重力下落不舒适不真实,需要通过修改重力比例和跳跃力
  2. 连续按空格jump时,Player会连续向上跳跃
  3. 当跳跃后按左或者右方向键时,Player会卡在屏幕上无法运动

贴近墙壁问题
添加物理材质修改摩擦力为0,这样就不会卡在墙壁上而是自然滑落。

无限跳跃和落地手感问题
为了避免人物无限跳跃,就需要检测人物只有在地面的时候才可以使用跳跃。
首先需要检测人物是否在地面,需要一个检测的点。如果在这个点的一定范围之内发现有地面,地面的层级Layer在前面设置的是Ground。那么只需要检测它对应的是Ground,就说明它在地面上了。
让人物获得地面监测点的坐标位置,即它的transform组件的position。找到位子后在他的周围一定的范围之内进行物理碰撞检测,看看是否有属于Ground的Layer。

[Header("Ground Check")] 
public Transform groundCheck; // 检测的点
public float checkRadius; // 检测范围
public LayerMask groundLayer; // 选择对应的图层
[Header("States Check")] 
public bool isGround; // 状态监测

添加检测函数

// 地面检测函数使用圆形检测
void PhysicsCheck()
{
    // 坐标,检测范围,图层
    isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, groundLayer);
}

我这里设置检测范围是0.5。此时游戏运行时,已解决无限跳跃的问题。

2.5 可视化检测范围

// 可视化检测范围 系统方法,不需要在任何Update里进行调用
public void OnDrawGizmos()
{
    // 中心点/检测范围
    Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
}

如图所示,会在红色检测点出现一个白色圆圈的检测范围。

2.6 修改重力检测

控制在跳跃时重力修改为4,落地时为1。

if (isGround)
    rb.gravityScale = 1;
else
    rb.gravityScale = 4;

3.PlayerController.cs

本节中添加的玩家代码。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 游戏玩家控制器,主要包含玩家的基本移动即左右移动和跳跃攻击
public class PlayerController : MonoBehaviour
{
    // 获取刚体组件 
    private Rigidbody2D rb;
    public float speed;
    public float jumpForce; // 跳跃的力

    [Header("Ground Check")] public Transform groundCheck; // 检测的点
    public float checkRadius; // 检测范围
    public LayerMask groundLayer; // 选择对应的图层
    [Header("States Check")] public bool isGround; // 状态监测
    public bool isCanJump; // 是否可以跳跃

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        CheckInput();
    }

    void FixedUpdate()
    {
        PhysicsCheck(); // 一开始就检测物理
        Movement();
        Jump();
    }

    // 执行人物移动的方法 需要获取按键
    void Movement()
    {
        // float horizontalInput = Input.GetAxis("Horizontal"); // 获取的值从-1~1,包括小数

        float horizontalInput = Input.GetAxisRaw("Horizontal"); // 获取的值从-1~1,不包含小数
        rb.velocity = new Vector2(horizontalInput * speed, rb.velocity.y); // 使用物理向量的速度固定移动速度 y保持不变,x为输入*速度

        // 修改transform的本地坐标来进行翻转
        if (horizontalInput != 0)
            transform.localScale = new Vector3(horizontalInput, 1, 1);
    }

    // 控制Player跳跃
    void Jump()
    {
        if (isCanJump)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            isCanJump = false;
        }
    }

    // 用来收集Player输入的操作
    void CheckInput()
    {
        // 当按下跳跃按键的时候同时也要检测是否在地面
        if (Input.GetButtonDown("Jump") && isGround)
            isCanJump = true;
    }

    // 地面检测函数使用圆形检测
    void PhysicsCheck()
    {
        // 坐标,检测范围,图层
        isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, groundLayer);
        if (isGround)
            rb.gravityScale = 1;
        else
            rb.gravityScale = 4;
    }

    // 可视化检测范围 系统方法,不需要在任何Update里进行调用
    public void OnDrawGizmos()
    {
        // 中心点/检测范围
        Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
    }
}