Unity:无限背景和视差滚动

视差滚动:
通常相机和人物绑定以一定的速度向前,而背后的景物设置不同的速度这样就实现了视差效果

  1. 获取主相机的transform,记录相机的初始位置
  2. 记录相机的移动的位置,刷新背景的位置(因为保证不同速度所以要乘以一个系数),刷新相机初始位置(通过计算每帧的路程实现速度不一样)

无限背景:

  1. 获取sprite,再获取texture
  2. 计算材质再unity中占几个单位(unity中的默认单位是:1单位100px)
  3. 当摄像机位置减去背景的位置的绝对值(左右)大于材质宽度(unity单位)时刷新背景位置

代码:

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

public class BackGroundController : MonoBehaviour
{
    
    
    private Transform cameraTransform;
    private Vector3 lastCameraPosition;
    [SerializeField] private float parallaxCoefficient;
    private Sprite bgSprite;
    private Texture2D bgTexture;
    private float textureUnitSizeX;

    // Start is called before the first frame update
    void Start()
    {
    
    
        parallaxCoefficient = 0.5f;
        cameraTransform = Camera.main.transform;
        lastCameraPosition = cameraTransform.position;
        bgSprite = GetComponent<SpriteRenderer>().sprite;
        bgTexture = bgSprite.texture;
        textureUnitSizeX = bgTexture.width / bgSprite.pixelsPerUnit;
    }

    // Update is called once per frame
    void Update()
    {
    
    
        Vector3 deltaMovement = cameraTransform.position - lastCameraPosition;
        transform.position += new Vector3(deltaMovement.x * parallaxCoefficient,0,0);
        lastCameraPosition = cameraTransform.position;

        if (Mathf.Abs(cameraTransform.position.x - transform.position.x) >= textureUnitSizeX)
        {
    
    
           
            float offsetPositionX = (cameraTransform.position.x- transform.position.x) % textureUnitSizeX;
            transform.position = new Vector3(cameraTransform.position.x+offsetPositionX, transform.position.y, transform.position.z);
        }
    }
}


/*
视差滚动:
通常相机和人物绑定以一定的速度向前,而背后的景物设置不同的速度这样就实现了视差效果
1.获取主相机的transform,记录相机的初始位置
2.记录相机的移动的位置,刷新背景的位置(因为保证不同速度所以要乘以一个系数),刷新相机初始位置(通过计算每帧的路程实现速度不一样)

无限背景:
1.获取sprite,再获取texture
2.计算材质再unity中占几个单位(unity中的默认单位是:1单位100px)
3.当摄像机位置减去背景的位置的绝对值(左右)大于材质宽度(unity单位)时刷新背景位置
*/

知识点

[SerializeField]private float parallaxCoefficient;

[SerializeField]序列化可以使私有属性在unity中显示

cameraTransform=Camera.main.transform;

获取主相机的transform

GetComponent<SpriteRenderer>().sprite;

获取SpriteRenderer组件里的sprite

bgTexture = bgSprite.texture;

从sprite里获取材质
Texture:Unity 将3D工程目录下的Asset文件夹下的任何图片和 image or movie file 识别为Texture (2D projects工程中,它们被当作 Sprites). 只要图像符合下列尺寸要求, ).

textureUnitSizeX = bgTexture.width / bgSprite.pixelsPerUnit;

将材质大小由像素转换为unity单位(默认为1unity单位为100px)
bgTexture.width:材质的像素宽
bgSprite.pixelsPerUnit:精灵图每单元的像素数

Vector3 deltaMovement = cameraTransform.position - lastCameraPosition;

三维数据可由三维数据互相减而得(加法同理)

transform.position += new Vector3(deltaMovement.x * parallaxCoefficient,0,0);

parallaxCoefficient为视差系数,给不同的图层设置不同的系数,这样每帧每个图层移动不同的距离可以形成良好的视差效果。

transform.position不可以直接指定,需要用new Vector3

Mathf.Abs()

绝对值

使用public在unity中绑定可方便自己处理获取的问题

无限背景的详解:
在这里插入图片描述
首先打开图像平铺,平铺的足够长(要足够长)

背景中心点的起始位置:
在这里插入图片描述
想法:
当角色移动到移动到平铺图中第二个这样的起始位置时,背景图死心移到摄像机的x处(摄像机和角色绑定)

第二个这样的起始位置:
在这里插入图片描述
这样便可以实现无限背景。

问题:
offsetPositionX的作用是什么?

float offsetPositionX = (cameraTransform.position.x- transform.position.x) % textureUnitSizeX;
transform.position = new Vector3(cameraTransform.position.x+offsetPositionX, transform.position.y, transform.position.z)

因为update是每帧执行一次,所以在渲染的时间间隔内可能出现:

Mathf.Abs(cameraTransform.position.x - transform.position.x) != textureUnitSizeX

在这里插入图片描述
假设人物在间隔内走到了箭头所指的地方,然后执行

if (Mathf.Abs(cameraTransform.position.x - transform.position.x) >= textureUnitSizeX)
        {
    
    
           
            float offsetPositionX = (cameraTransform.position.x- transform.position.x) % textureUnitSizeX;
            transform.position = new Vector3(cameraTransform.position.x+offsetPositionX, transform.position.y, transform.position.z);
        }

图像的死心就定位到人物的x处,这样便会出现人物倒退的现象。

为什么最后一个背景会出现抖动的情况?
这个问题我也不太清楚,知道的朋友可以告诉我下。
已知:我把函数放在了fixedupdate中,如果我将时间调小则可以减轻抖动

猜你喜欢

转载自blog.csdn.net/m0_53438035/article/details/123754298
今日推荐