使用Unity制作“饥荒”风格的俯视角2.5D游戏

1,839 阅读2分钟

一、前言:

通常游戏按照镜头的角度可以分为2D游戏和3D游戏,但是还有一种独树一帜的游戏风格,将二维与三维的特点结合起来,在2D图像上展现出3D的效果,我们称之为2.5D,也就是伪3D。有很多非常受欢迎的游戏都采用了这种风格,而这种风格也将他们从同类的其他游戏中凸显出来。比如有《饥荒》和《八方旅人》。

二、实现2.5D风格游戏

1.效果展示:

2.5D.gif

2.如何实现

2.1搭建地图

首先搭建2D的地图,如果你是2019版本的unity,可能是需要导入2D Tilemap Editor绘制2D地图

image.png

绘制好后,我们设置好对应的所有树,加上2D盒状碰撞器,人物加上刚体(锁定z轴旋转,取消重力值)、盒状碰撞器,动画控制器。这里的人物采用的是unity商店的Tiny RPG-Forest人物

image.png

2.2配置人物动画

在这里我们使用的是两个混合树来实现,移动是单独的一个混合树,不移动idle状态下也是一个混合树,添加一个布尔值,当为true的时候触发移动混合树,为FALSE触发idle混合树。

image.png

image.png

2.3让人物动起来

PlayerMovement.CS

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

public class PlayerMovement : MonoBehaviour
{
    public float speed;
    new private Rigidbody2D rigidbody;
    private Animator animator;
    private float inputX, inputY;
    private float stopX, stopY;

    void Start()
    {
        rigidbody = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        //水平轴是AD键
        inputX = Input.GetAxisRaw("Horizontal");
        //垂直轴是WS键
        inputY = Input.GetAxisRaw("Vertical");
        //相对于自身坐标进行移动,如果是Vector3就是相对于世界坐标进行移动
        Vector2 input = (transform.right * inputX + transform.up * inputY).normalized;
        print(input);
        //刚体控制人物移动
        rigidbody.velocity = input * speed;
        //只要按下了上下左右input就是会有值,有值就会isMoving为true,进入stopX,stopY进行赋值,
        //没有input没有值说明人物停下来了,说明是idle状态,isMoving为FALSE,进入idle混合树
        if (input != Vector2.zero)
        {
            animator.SetBool("isMoving", true);
            //这样记录的作用是当人物停下来的时候会记录idle上一帧的动画状态,而不是只是单独的一个动画
            stopX = inputX;
            stopY = inputY;
        }
        else
        {
            animator.SetBool("isMoving", false);
        }
        //在isMoving切换的状态下进入InputX,inputY赋值
        animator.SetFloat("InputX", stopX);
        animator.SetFloat("InputY", stopY);

    }
}

image.png

2.4所有物体朝向摄像机

FacingCamera.CS

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

public class FacingCamera : MonoBehaviour
{
    Transform[] childs;
    void Start()
    {
        //加载子物体
        childs = new Transform[transform.childCount];
        for (int i = 0; i < transform.childCount; i++)
        {
            //将所有子物体存入数组中
            childs[i] = transform.GetChild(i);
        }
    }

    void Update()
    {
        //所有场景中的子物体朝向摄像机
        for (int i = 0; i < childs.Length; i++)
        {
            childs[i].rotation = Camera.main.transform.rotation;
        }
    }
}

2.5:摄像机设置

新建空对象CameraPosition,子物体存放的是场景的摄像机,注意:要把摄像机改为透视:

image.png 项目设置中也是这样

image.png

RotatingCamera.CS

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

public class RotatingCamera : MonoBehaviour
{
    public float rotateTime = 0.2f;//摄像机旋转的时间
    private Transform player;
    private bool isRotating = false;//是否在旋转的状态
    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    void Update()
    {
        transform.position = player.position;

        Rotate();
    }

    void Rotate()
    {
        if (Input.GetKeyDown(KeyCode.Q) && !isRotating)
        {
            StartCoroutine(RotateAround(-45, rotateTime));
        }
        if (Input.GetKeyDown(KeyCode.E) && !isRotating)
        {
            StartCoroutine(RotateAround(45, rotateTime));
        }
    }
    /// <summary>
    /// 使用携程可以让旋转动作更加平滑的去执行,而不是像普通的循环结构一样,一帧就会执行完,但是携程不会这样,它可以等待
    /// </summary>
    /// <param name="angel"></param>
    /// <param name="time"></param>
    /// <returns></returns>
    IEnumerator RotateAround(float angel, float time)
    {
        float number = 60 * time;
        float nextAngel = angel / number;
        isRotating = true;

        for (int i = 0; i < number; i++)
        {
            transform.Rotate(new Vector3(0, 0, nextAngel));
            yield return new WaitForFixedUpdate();
        }

        isRotating = false;
    }
}

image.png

到此我们就实现了俯视角2.5D游戏