Unity教程(十二)视差背景

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

Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现
Unity教程(六)角色滑墙的实现
Unity教程(七)角色蹬墙跳的实现
Unity教程(八)角色攻击的基本实现
Unity教程(九)角色攻击的改进

Unity教程(十)Tile Palette搭建平台关卡
Unity教程(十一)相机
Unity教程(十二)视差背景

Unity教程(十三)敌人状态机
Unity教程(十四)敌人空闲和移动的实现
Unity教程(十五)敌人战斗状态的实现
Unity教程(十六)敌人攻击状态的实现
Unity教程(十七)敌人战斗状态的完善


如果你更习惯用知乎
Unity开发2D类银河恶魔城游戏学习笔记目录



前言

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

本节添加视差背景。
Udemy课程地址

对应视频:
Parallax background
Endless background


一、概述

本节给游戏添加背景,我们做一个视差背景来增强视觉效果。
视差背景是通过多层次的背景来模拟透视视差效果。就是当发生移动时,离照相机越近的背景移动越快;反之越慢。这样,我们的背景就会形成类似于透视视差的效果。
我参照了这篇文章 聊聊2D游戏视差背景的实现
除此之外教程中还讲解了无限滚动的背景怎么实现。

二、视差背景

(1)添加背景

背景图的路径:
Assets->Graphics->Surroundings->Medieval_Castle->Background
将layer_1、layer_2拖入场景中
在这里插入图片描述
注意:(1)如果Tile Palette画笔工具还开着会向Tilemap的背景上绘制。所以记得拖入背景图前关掉。
(2)查看右上角2D选项有没有被关掉,关掉会显示不出背景。
在这里插入图片描述

(2)调整层次

调整Sprite Renderer中的Sorting Layer参数,调整被渲染的顺序
我们先添加四个层Background、Ground、Enemy、Player
在这里插入图片描述
在这里插入图片描述
给天空背景层重命名为BG_Sky_Layer,城堡背景层重命名为BG_City_Layer。
Sorting Layer都设置为Background,并分别修改Order inLayer为-10和-9。
在这里插入图片描述
在这里插入图片描述
重置他们的位置,挂靠在空物体下面,并把空物体重命名为Background
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Animator层次设定为Player
在这里插入图片描述
将Tilemap里Ground层次设置为Ground,Background层次设置为Background
在这里插入图片描述
在这里插入图片描述

(3)视差背景实现

天空层复制两次成为天空层的子层。改变两个子层的位置,x的值一个改为-40,一个改为40。
在这里插入图片描述
城市层进行相同的处理
在这里插入图片描述
创建脚本ParallaxBackground
创建变量xPosition,在进入状态时记录背景的初始位置。
创建变量parallaxEffect来表示视差效应,控制背景跟随相机的速度。
在Update()中每次用背景初始位置xPosition加上计算出的要移动的距离distanceToMove,来更新背景位置

//ParallaxBackground:视差背景
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParallaxBackground : MonoBehaviour
{

    private GameObject cam;
    [SerializeField] private float parallaxEffect;

    private float xPosition;

    // Start is called before the first frame update
    void Start()
    {
        cam = GameObject.Find("Main Camera");

        xPosition = transform.position.x;
    }

    // Update is called once per frame
    void Update()
    {
        float distanceToMove = cam.transform.position.x * parallaxEffect;

        transform.position=new Vector3(xPosition + distanceToMove,transform.position.y);
    }
}

将脚本分别挂载到BG_Sky_Layer和BG_City_Layer,根据想要的效果调节ParallaxEffect的值
在这里插入图片描述
在这里插入图片描述
效果对比如下:
ParallaxEffect都为0
在这里插入图片描述

BG_Sky_Layer:ParallaxEffect为1,BG_City_Layer:ParallaxEffect为0.8
在这里插入图片描述

可以看出增添视差效果后两层背景的移动速度明显不一样了,更具有空间效果。

按照教程做完我发现,假如相机初始位置为负可能造成背景反向移动,以比较极端的情况为例:
我将场景向x负方向拖,Main Camera的x坐标为-109.4
在这里插入图片描述
这时运行,背景会瞬间向后移动很长的距离。
在这里插入图片描述
虽然我们的初始位置一般定在中心,基本不会出现这种情况,但我还是想进行改进。
我们只要在进入状态时记录相机的初始位置,并且在计算要移动的距离时,将使用相机的x坐标改为使用相机x方向的位移即可。

//ParallaxBackground:视差背景
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParallaxBackground : MonoBehaviour
{

    private GameObject cam;
    [SerializeField] private float parallaxEffect;

    private float xPosition;
    private float xCamPosition;

    // Start is called before the first frame update
    void Start()
    {
        cam = GameObject.Find("Main Camera");

        xPosition = transform.position.x;

        xCamPosition= cam.transform.position.x;
    }

    // Update is called once per frame
    void Update()
    {
        float distanceToMove = (cam.transform.position.x - xCamPosition) * parallaxEffect;

        transform.position=new Vector3(xPosition + distanceToMove,transform.position.y);
    }
}

这时即使初始位置比较极端程序也可以正常运行
在这里插入图片描述

三、无尽滚动背景

制作无尽滚动的背景我们使用可拼接重复的图片。如下所示,如果一瞬间移动背景使得移动过来的部分与原背景完全一致,在相机中我们是看不出来的。
如果没有视差背景和摄像机应该同步移动,现在背景落后于摄像机,所以每当背景落后于相机一个图片长度的时候我们移动一次背景,背景就可以不断随着角色前移,实现背景的无尽滚动。
在这里插入图片描述
图片的长度length通过SpriteRenderer获得。
判断背景与相机的距离差值与图片长度的关系。差值大于length,则前移length;小于-legth,则后移length
和教程中实现方式对应的示意图如下:
在这里插入图片描述

由图示可知距离插值等于 d i s t a n c e D i f f e r e n c e = c a m P o s i t i o n ∗ ( 1 − E f f e c t ) − x P s i o t i o n distanceDifference=camPosition * (1 - Effect) - xPsiotion distanceDifference=camPosition(1Effect)xPsiotion
对应代码

//ParallaxBackground:视差背景
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParallaxBackground : MonoBehaviour
{

    private GameObject cam;
    [SerializeField] private float parallaxEffect;

    private float xPosition;

    private float length;


    // Start is called before the first frame update
    void Start()
    {
        cam = GameObject.Find("Main Camera");

        length=GetComponent<SpriteRenderer>().bounds.size.x;

        xPosition = transform.position.x;
    }

    // Update is called once per frame
    void Update()
    {
        float distanceToMove = cam.transform.position.x * parallaxEffect;
        float distanceMoved = cam.transform.position.x * (1 - parallaxEffect);

        transform.position=new Vector3(xPosition + distanceToMove,transform.position.y);


        if (distanceMoved > xPosition + length)
            xPosition = xPosition + length;
        else if (distanceMoved < xPosition - length)
            xPosition = xPosition - length;
    }
}

和改进后实现方式对应的示意图如下:
在这里插入图片描述

由图示可知距离插值等于 d i s t a n c e D i f f e r e n c e = ( c a m P o s i t i o n − x P o s i t i o n ) ∗ ( 1 − E f f e c t ) − ( x P o s i t i o n − x C a m P o s i t i o n ) distanceDifference=(camPosition-xPosition) * (1 - Effect) - (xPosition-xCamPosition) distanceDifference=(camPositionxPosition)(1Effect)(xPositionxCamPosition)

//ParallaxBackground:视差背景
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParallaxBackground : MonoBehaviour
{

    private GameObject cam;
    [SerializeField] private float parallaxEffect;

    private float xPosition;
    private float xCamPosition;

    private float length;


    // Start is called before the first frame update
    void Start()
    {
        cam = GameObject.Find("Main Camera");

        length=GetComponent<SpriteRenderer>().bounds.size.x;

        xPosition = transform.position.x;

        xCamPosition= cam.transform.position.x;
    }

    // Update is called once per frame
    void Update()
    {
        float distanceToMove = (cam.transform.position.x - xCamPosition) * parallaxEffect;
        float distanceDifference = (cam.transform.position.x - xCamPosition) *(1- parallaxEffect)-(xPosition-xCamPosition);

        transform.position=new Vector3(xPosition + distanceToMove,transform.position.y);


        if (distanceDifference > length)
            xPosition = xPosition + length;
        else if (distanceDifference < -length)
            xPosition = xPosition + - length;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值