Unity Pixels Per Unit 与 Sprite Renderer Scale的逻辑关系,为什么平铺的Sprite Renderer会变形?

        SpriteRenderer之前用的比较基础,没遇到过什么问题,这几天使用SpriteRenderer的平铺时发现平铺变形了,研究了一下,原来有这么多在逻辑在里面。

        当我们导入图片选择Texture Type为Sprite时表示我们的图片用途是UI或者SpriteRenderer,可以看到有个导入属性为Pixels Per Unit(下文简称为PPU),该属性默认值为 100,按照字面意思理解,PPU意为一个  “单位” 内含的像素数,这里的 “单位” 指的是Unity空间内的单位,可以理解为场景的一个格子长宽各为一个单位,下面开始对同一张图片设置不同的PPU进行显示测试。

        首先强调下 “单位” 这个概念,我们在场景中创建一个cube,Scale值默认为1,那么这个Cube就可以理解为长宽高各为1个单位,场景中显示的所有包括2D,3D的内容都可以以此Cube为基准进行衡量。导入一个空白的白色图片,图片大小为100*100,PPU修改为100,如图:

        然后分别创建缩放为1的Cube,缩放为2的Cube,缩放为1的SpriteRenderer,贴图内容为上面导入的图片,方便对比大小,切换到2D视角对比,结果如图 ,各个对象用不同颜色标注,左上角SR *1表示SpriteRenderer,Scale值为1,其他同理:

         可以明显看到SpriteRenderer的大小与Cubex1的大小相同,表示此时,该SpriteRenderer的长宽各位1个 “单位”,Cubex2的长宽各为2个 “单位”,结合各个对象的Scale值,那是不是可以理解为对象的Scale值就表示为的单位数量呢?比如Scale = (3,5,0.5f),是否就表示该对象长宽高分别为3个 “单位”, 5 个 “单位”, 0.5个 “单位”?

        答案当然是否定的,但是上面的结果又如何解释呢?当我们随意修改SpriteRenderer的Scale值,会发现无论如何都会与相应缩放的Cube所对齐,不就说明Scale 与 “单位”是完全对应的吗?而为什么会出现这样的结果,答案其实很简单 ——“巧合”,没错,就是巧合,只是凑巧而已,而导致这个 “巧合” 结果的,正是PPU的值。

        下面我们将上面导入的图片复制两份,分别修改PPU为20,200,再进行对比,设置如下:

        创建同样Scale为1的两个SpriteRenderer,贴图分别设置为上面两个,对象设置如图: 

        结果如图:

         可以看到,相同的图片尺寸,相同的缩放值,不同PPU值,在表现上的尺寸差距是巨大的,而为什么会造成这样的结果呢?就是因为每个SpriteRenderer所占的 “单位”不同,各自占的“单位”值又是多少呢?

        我们记“单位”为Unit,先计算PPU = 100的图片,图片分辨率为100*100,即水平和垂直方向像素数量均为Pixel = 100, PPU = 100表示显示该图片是每个单位占据100个像素,那么完全显示该图片需要 一共 需要 Unit =   Pixel / PPU = 100/ 100 = 1 ,即1个 “单位”;同理计算PPU = 20的图片,Unit = Pixel / PPU = 100 / 20 = 5 ,即5个 “单位‘ ;PPU = 200 的图片, Unit = Pixel / PPU = 100/ 200 = 0.5,即0.5个 ”单位“。

       总结:PPU = 100,Unit = Pixel / PPU = 100 / 100 = 1

        PPU = 20, Unit = Pixel / PPU = 100 / 20 = 5

        PPU = 200,Unit = Pixel / PPU = 100 / 200 = 0.5

        即不同的PPU值,在Scale值相同时所占的 “单位”是不同的,所以表现上面尺寸差距巨大,而如果我们像让这些图片尺寸看上去都一样的话,就需要根据所占的 “单位”数量反向缩放,缩放值即为目标“单位”值/当前所占“单位”值,  对上面的对象进行相应的缩放,可以得到如下结果:

        

         可以看到,进行相应的缩放之后,三个对象在表现上大小一致了,所以在我们想修改图片在spriterenderer上表现的大小时,不但可以通过修改Scale值,也可以修改PPU达到相同的效果,为了验证上面的结果不是因为图片分辨率是 100* 100 导致的 “巧合”,可以导入其他任意分辨率的图片进行测试验证,这里只做少量的验证,导入一张新的分辨率为65*65的图片,PPU为默认值100,设置如图:

         创建一个SpriteRenderer,将上面图片赋值,与分辨率为100*100,PPU = 100的图片做对比,结果如图:

         根据上面的结果计算,左边 Unit = Pixel / PPU = 100 / 100 = 1,而右边 Unit = Pixel / PPU = 65 / 100 = 0.65,所以右边显示会比左边小,而想要让右边显示与左边一致,即占据1个 “单位”,两种方式,1:修改Scale,放大 100/65倍;2:修改PPU , PPU = Pixel / Unit = 65 / 1 = 65。其他验证这里省略。

        “单位”  与 PPU 的概念至关重要,错误的值会导致SpriteRenderer平铺变形。

        方便看出来变形效果,导入一张包含纹理的图片,分辨率为92*92,PPU设置为100,设置如图:

        先创建一个SpriteRenderer赋值,Scale  = 1,填充方式Draw Mode为完全填充 Simple,根据上面逻辑可以得出该SpriteRenderer的Unit = 92 / 100 = 0.92,然后复制该SpriteRenderer,修改Draw Mode为Tiled,设置Size 值width = heigth = 1,设置完成之后,会发现该SpriteRenderer的显示大小并没有发生变化,但是Scale值却变成了(0.92,0.92,1),图片填充显示也有问题(下文再解释),如图,其中左边方块为Simple方式,右边方块为Tiled方式,为什么有这样的结果?

        

图1

         Simple填充的表现是复合预期的,想要解释Tiled为什么会有这样的表现,首先要理解Tiled模式下的Size属性, 千万不要理解为Size值表示水平和垂直方向平铺的图片数量,这是完全错误的!其中的width的解释为 The width dimension value for the sprite(精灵的宽度尺寸值),实在是被这个解释坑了好久,不知道官方的 dimension 具体指的是什么尺寸,经过一系列测试,发现这个值,与上面我们定义的 “单位” 是完全对应的,即width的含义,可以理解为 平铺之后水平方向的 “单位”值。width = 1,表示平铺后,水平方向 “单位” 大小为1,而因为填充模式为Simple时,“单位”大小为 0.92,所以这里会自动缩放Scale = 0.92,保持与修改前的表现大小一致。然后我们将 Scale再修改为1,那么该SpriteRenderer 显示大小会重新与 “单位”为1的SpriteRenderer保持一致,如图:

        

         验证下Tiled模式下width 与 “单位”的关系,新建Tiled,填充上面的图片,width值设置为10,然后再新建一个Cube,Scale值设置为(10,1,1),即此时该Cube长度 “单位” 为10,对比长度,结果如图:

        长度是吻合的,表示width 与 “单位”是相等关系,是标准的,通关修改导入贴图的PPU信息,不影响尺寸表现效果。

        理解了上面的width之后,就可以理解为什么平铺的图片会有问题了。

        先看第一个问题,上面 图1 右边的图片,填充的时候,会比左边的图片多显示了一部分,这是因为我们平铺模式选择的是 Continuous,均匀的平铺,不进行缩放,因为我们这里设置的width = 1,即占的 “单位” Unit = 1,而贴图分辨率Pixel = 92x92,PPU = 100,所以在 1个“单位”里面会显示 100(PPU)个像素,而我们的图片分辨率只有 92,所以还剩下 100 - 92 = 8个像素用于平铺,就造成了 图1 的情况。要修改这种结果,只需要修改 平铺模式 为 Adaptive即可,该模式会对图片进行拉伸,效果如图,其中右下角平铺方式为Adaptive:

        但是这样就解决问题了吗? 

        新建一个SpriteRenderer,依然导入上面的图片,填充模式设置为Tiled,width设置为20,height设置为0.92以保证垂直方向不进行缩放(因为上面我们计算的结果是该图片水平垂直方向 的“单位”值均为0.92),平铺模式修改为Adaptive,如图,其中最左边的方块和最上面的方块都为Simple模式填充,Scale为1,为了方便观察,只截取了一部分原大小:

        可以明显看到平铺的 的长宽已经不是比例,发生了变形,垂直方向保证了原大小,但是水平方向有些微的差异,如果width值更大,那么变形会更明显,通过调节Adaptive 方式下的Stretch Value会有一定的效果,但是我发现不同的size值需要对应不同的Stretch Value,通过修改这个Stretch Value,不同的值也没有修复掉变形的问题,而且我确实没有搞明白Stretch Value的逻辑具体是什么,就放弃了这个方式。而出现这样的情况,是因为导入图片的分辨率Pixel与PPU设置值不匹配而导致的,根据上面的逻辑,我们可以知道,width设置为20,表示水平占据 20个 “单位”,根据上面我们算的结果,这个图片水平方向的 “单位”值是0.92,不能整除 “20”单位,所以显示的结果一定是经过缩放的,但是垂直方向没有进行缩放,所以看起来才会变形,如果我们把height也修改为20,那么水平垂直同比缩放,就不会有变形的问题了,但是那样的结果只能是正方形,不符合我们的预期。此时我们就可以通过修改PPU来解决现在的问题,因为平铺基本都是整数的,上面我们height设置0.92是为了观察变形效果,所以我们只需要保证我们的一张图片的“单位”能被整数整除就行,比如上面的图片分辨率为92*92,那么我们修改PPU = 92,保证每张图片都是一个单位,那么在平铺时只要水平垂直方向都是整数,这样就不会变形。

        那么我们必须保证平铺和图片所占 “单位”都是整数,甚至图片只能是正方形才能保证平铺不会变形吗?当然不是的,变形只是因为长宽缩放不一致导致的,而如果我们能保证缩放一致,无论怎样都不会变形,或者说我们只要保证水平和垂直方向都是均匀拉伸就不会变形,而要达到这个要求,只需要保证平铺是的width 和 height能分别整除 图片水平和垂直方向所占的 “单位”大小,即 width % (pixel.x / PPU) = 0,height % (pixel.y / PPU) = 0。可以自行测试验证。

        告一段落,基本上就是这个样子了,之后会看时间配上视频具体讲下,有错误的地方还望指出。

        关于“单位”的应用与正交相机的Size计算也有关系,正在研究,后面研究完再记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626936.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

风电功率预测 | 基于RF随机森林的风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测完整代码风电功率预测 基于随机森林(Random Forest, RF)的风电功率预测是一种常用且有效的方法。以下是基于RF的风电功率预测的一般步骤: 数据准备:收集与风电场发电功率相关的数据,包括风速、风向、温度、湿度等气象数据以及风电场的历史功率数…

手机触控面板中应用的电容式触摸芯片

手机触控屏(Touch panel)又称为触控面板,是个可接收触头等输入讯号的感应式液晶显示装置,当接触了屏幕上的图形按钮时,屏幕上的触觉反馈系统可根据预先编程的程式驱动各种连结装置,可用以取代机械式的按钮面…

生产消费者模型-环形队列与信号量

文章目录 前言一、怎样的环形队列?二、什么是信号量三、使用步骤信号量的接口函数1. sem_init2.sem_destroy3.sem_wait4.sem_post 环形队列的设计测试用例 前言 之前我们使用互斥锁和条件变量实现过一个生产者消费者模型,那么那个生产消费者模型具有一个…

YOLOv9改进策略 | 低照度图像篇 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

一、本文介绍 本文给大家带来的2024.3月份最新改进机制,由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络,CPA-Enhancer通过引入链式思考提示机制&am…

Centos 6.10 安装oracle10.2.0.1

由于阿里云机房要下架旧服务器,单位未购买整机迁移服务,且业务较老不兼容Oracle11g,所以新购买一台新服务器进行安装Oracle10.2.0.1 ,后续再将数据迁移到新服务器上。 对外ip 内部ip 数据库版本 操作系统版本 实例名 源库 1…

Pyqt中QThread传递自己定义的参数、类、函数

Pyqt中QThread传递自己定义的参数、类、函数 1 pyqt中Qthread传递自己定义的参数2 pyqt中Qthread传递自己定义的类3 pyqt中Qthread传递自己定义的函数4 pyqt中Qthread内部定义自己的函数5 pyqt中Qthread传递参数到内部定义自己的函数 1 pyqt中Qthread传递自己定义的参数 在PyQ…

Linux: Make工具以及Makefile文件

make工具 人们通常利用 make 工具来自动完成编译工作。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作&…

Pytorch代码基础—张量

Pytorch代码—张量 Pytorch张量 张量的属性: data:被包装的Tensorgrad:data的梯度grad_fn:创建Tensor的Function,是自动求导的关键requires_grad:指示是否需要梯度isleaf:指示是否是叶子结点&#xff0…

第四课,python基础语法(算术运算符及其复合运算符、字符串三种定义方式)

一,算术运算符 经过前几节课的学习之后同学们对加减乘除已经不再陌生,本节课进一步掌握两个新的运算符,整除(//)和模(%),整除用来计算两数相除的商,而模用来计算两数相除…

ES6之正则扩展

正则表达式扩展 u修饰符(Unicode模式)y修饰符(Sticky或粘连模式)s修饰符(dotAll模式)Unicode属性转义正则实例的flags属性字符串方法与正则表达式的整合 javascript的常用的正则表达式 验证数字邮箱验证手机…

windows 安装 Conda

1 Conda简介 Conda 是一个开源的软件包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。Conda 是为 Python 程序创建的,适用于 Linux,OS X 和Windows,也可以打包和分发其他软…

【LAMMPS学习】九、LAMMPS脚本 示例

9. 示例脚本 LAMMPS 发行版包含一个包含许多示例问题的示例子目录。许多是二维模型,运行速度快且易于可视化,在台式机上运行最多需要几分钟。每个问题都有一个输入脚本 (in.*),并在运行时生成一个日志文件 (log.*)。有些使用初始坐标的数据文…

刷代码随想录有感(65):回溯算法——组合问题

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<vector<int>> res;vector<int> tmp;void backtracking(int n, int k, int start){if(tmp.size() k){res.push_back(tmp);return;}for(int i start; i < n; i){tmp.push_back(i);bac…

支持不同业务模式与安全要求的跨网传输解决方案,了解一下

对于科技研发型企业来说&#xff0c;最值钱的是研发代码这类数据资产。因此很多企业会想将这些数据“困”在内部&#xff0c;防止数据泄露。最常见的做法是通过防火墙、DMZ区、双网卡主机、虚拟机、网闸/光闸等隔离方式&#xff0c;将网络划分为企业内外网&#xff0c;较为常见…

云商城系统源码,无后门,一站式系统Java源码

云商城系统&#xff0c;无后门&#xff0c;一站式系统Java源码&#xff0c;心权益商品数量不限数量 系统对接 手动发货 自动发货 兑 换 码 订单监控 商品监控 对象存储 邮箱提醒 加价模板 密价功能 三方支付 会员体系 财务明细 交易分析 售后服务 技术支持 【Java源码】云商…

Java面试八股之为什么要使用克隆

Java中为什么要使用克隆&#xff1f;怎么实现对象的克隆&#xff1f;深拷贝和浅拷贝的区别是什么 在Java中使用克隆主要有以下几个原因&#xff1a; 创建对象副本&#xff1a;克隆可以快速创建一个与原对象状态完全相同的副本&#xff0c;无需手动逐一复制每个属性。这种情况…

04-单片机商业项目编程,从零搭建低功耗系统设计

一、本文内容 上一节《03-单片机商业项目编程&#xff0c;从零搭建低功耗系统设计-CSDN博客》我们确定了设计思路&#xff0c;并如何更有效的保持低功耗&#xff0c;这节我们就准备来做软件框架设计。在AI飞速发展的时代&#xff0c;我们也会利AI来辅助我们完成&#xff0c;让自…

k8s v1.20二进制部署 部署 CNI 网络组件 部署 Calico

一、部署 flannel 1.1.K8S 中 Pod 网络通信 ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一个网络命名空间&#xff0c;相当于它们在同一台机器上一样&#xff0c;可以用 localhost 地址访问彼此的端口。…

【MATLAB源码-第59期】基于matlab的QPSK,16QAM164QAM等调制方式误码率对比,调制解调函数均是手动实现未调用内置函数。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 正交幅度调制&#xff08;QAM&#xff0c;Quadrature Amplitude Modulation&#xff09;是一种在两个正交载波上进行幅度调制的调制方式。这两个载波通常是相位差为90度&#xff08;π/2&#xff09;的正弦波&#xff0c;因此…

【R语言与统计】SEM结构方程、生物群落、多元统计分析、回归及混合效应模型、贝叶斯、极值统计学、meta分析、copula、分位数回归、文献计量学

统计模型的七大类&#xff1a;一&#xff1a;多元回归 在研究变量之间的相互影响关系模型时候&#xff0c;用到这类方法&#xff0c;具体地说&#xff1a;其可以定量地描述某一现象和某些因素之间的函数关系&#xff0c;将各变量的已知值带入回归方程可以求出因变量的估计值&…