1.层级显示

使用素材为免费或自制

本文章只用于学习和记录

在Unity2D游戏中可能出现以下情况



贴图的前后关系不正确
可以通过控制图片的层级来解决
本示例中杰西卡和树木都是搭载了图片的空物体,背景为Tilemap
新建脚本PositionSortRenderer

public class PositionSortRenderer : MonoBehaviour
{
[SerializeField] //序列化,私有变量也能显示在Inspector面板中
private int sortingOrderBase = 5000; //大参数方便后续计算
private Renderer myRenderer; //声明一个Renderer
private void Awake()
{
myRenderer = gameObject.GetComponent<Renderer>();
} private void LateUpdate() //在角色和场景内所有物体(包括摄像机)完成移动后进行
{
myRenderer.sortingOrder = (int)(sortingOrderBase - transform.position.y);//根据y左边方向计算
//这里个人感觉sortingOrderBase用0也行,但正数方便计算且节省性能
//个人感觉可以将减法优化为加法
}
}

注意这里是在LateUpdate() 中进行层级运算
Unity应当在层级内的所有物体运动完成和所有物理计算如碰撞这些完成之后再进行与图片等渲染有关的处理,否则图片在运动和碰撞检测时会不断抽搐,这里不深入细讲,LateUpdate()会在FixedUpdate()Update()之后运行。
注意这里需要将代码搭载到需要排序且有Sprite Renderer的图片上,而非空物体
运行后发现有效果

但仍有问题

这是参与计算的是图片的中心点(锚点)位置的原因


那么解决方法存在两种

2.通过代码解决

因为图片默认为中心点,那么只需要在计算时减去中心点到图片底部这一段距离即可
优化PositionSortRenderer

//public class PositionSortRenderer : MonoBehaviour
//{
//[SerializeField]
//private int sortingOrderBase = 5000;
[SerializeField]
private int offset = 0;
//private Renderer myRenderer;
//private void Awake()
//{
//myRenderer = gameObject.GetComponent<Renderer>();
//} //private void LateUpdate() //在角色和场景内所有物体(包括摄像机)完成移动后进行
//{
myRenderer.sortingOrder = (int)(sortingOrderBase - transform.position.y - offset);
//}
//}

这里Offset可以每个图片微调,直接获取图片高度一半的方法还在尝试

3.通过修改图片的锚点来修改

也可以直接修改图片的中心点

单体图片点击即可修改

分割的图片需要打开Sprite Editor选中修改,但单体图片也可进行相同操作

中间的蓝色圆圈即为图片的中心,可以直接拖拽进行修改

修改后如下

4.继续优化

其实那些位置不变的物体只需要计算一次层级,只有类似玩家这类不断移动的物体才需要持续计算层级,静止物体只计算一侧层级能节省许多性能开销
继续优化PositionSortRenderer

//public class PositionSortRenderer : MonoBehaviour
//{
......
[SerializeField]
private bool runOnlyOnce = false;
//private Renderer myRenderer;
......
//private void LateUpdate() //在角色和场景内所有物体(包括摄像机)完成移动后进行
//{
//myRenderer.sortingOrder = (int)(sortingOrderBase - transform.position.y - offset);
if (runOnlyOnce)
{
Destroy(this); //这里摧毁了脚本
}
//}
//}

这样勾选了Run Only Once的图片进行一次层级运算后便会销毁
这里层级信息被直接赋值给了Unity

因为大部分静态对象没有必要每帧都进行层级运算,避免后续计算导致性能开销

角色这类需要运动的对象不要勾选,需要一直对其进行层级运算

5.再次优化

角色的层级运算也不必每帧进行,因为大部分玩家其实是观察不出来的,如果我们通过计时器来定时计算玩家这类会移动的图片还能省下不少性能。
继续优化PositionSortRenderer

//public class PositionSortRenderer : MonoBehaviour
//{
......
private float timer;
private float timerMax = 0.1f;
//private Renderer myRenderer;
......
//private void LateUpdate() //在角色和场景内所有物体(包括摄像机)完成移动后进行
//{
timer -= Time.deltaTime;
if (timer <= 0f)
{
timer = timerMax;
//myRenderer.sortingOrder = (int)(sortingOrderBase - transform.position.y - offset);
//if (runOnlyOnce)
//{
//Destroy(this);
//}
}
//}
//}

这里我设置为0.1秒计算一次,也可自行修改
这样就能得到正确的显示结果

Unity中的2D层级显示问题的更多相关文章

  1. 关于Unity中的删除、显示和隐藏节点

    一.删除节点和组件 1.删除一个节点,以及节点上面所有的组件全部删除了//删除一个节点的时候,节点上面所有的组件也会被删除:MonoBehaviour.Destroy(this.gameObject) ...

  2. Unity中2D和UGUI图集的理解与使用

    图集 什么是图集? 在使用3D技术开发2D游戏或制作UI时(即使用GPU绘制),都会使用到图集,而使用CPU渲染的2D游戏和UI则不存在图集这个概念(比如Flash的原生显示列表),那么什么是图集呢? ...

  3. Unity中调用Windows窗口句柄以及根据需求设置并且解决扩展屏窗体显示错乱/位置错误的Bug

    问题背景: 现在在搞PC端应用开发,我们开发中需要调用系统的窗口以及需要最大化最小化,缩放窗口拖拽窗口,以及设置窗口位置,去边框等功能 解决根据: 使用user32.dll解决 具体功能: Unity ...

  4. 介绍用C#和VS2015开发基于Unity架构的2D、3D游戏的技术

    [Unity]13.3 Realtime GI示例 摘要: 分类:Unity.C#.VS2015 创建日期:2016-04-19 一.简介 使用简单示例而不是使用实际示例的好处是能让你快速理解光照贴图 ...

  5. 【unity shaders】:Unity中的Shader及其基本框架

    shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...

  6. Unity中Mesh分解与边缘高亮加上深度检测

    一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...

  7. Unity中简单使用Opengl

    简介 由于项目特殊需求,需要在unity中使用一些OpenGL的东西来绘制图形(PS:其实就是有一个拖尾算法只有OpenGL版本~~~懒得改了,直接在unity中使用OpenGL算了).所以琢磨咯下如 ...

  8. 在Unity中高效工作(上)

    原地址:http://www.unity蛮牛.com/thread-19974-1-1.html 编的话:感谢做编程的IT朋友,帮我翻译文章,我又稍稍做了些修改.给点儿掌声哩.欢迎大家多多评论呦. 我 ...

  9. Unity 4.3 2D 教程:新手上路

    这篇文章译自 Christopher LaPollo 先生的 Unity 4.3 2D 教程的第一部分 Unity 4.3 2D Tutorial: Getting Started 感谢这套优秀教程的 ...

随机推荐

  1. 消息中间件-RabbitMq相关概念及原理介绍【图文并茂】

    消息中间件 消息中间件的作用 解耦:消息中间件在服务之间插入了一个隐含的.基于数据的接口层.两边的服务处理过程都要实现这一接口,这允许我们独立的扩展或修改两边的处理过程,只要确保他们遵守相同的规范约束 ...

  2. 如何在MySQL中增加一列

    如果想在一个已经建好的表中添加一列,可以使用诸如: alter table TABLE_NAME add column NEW_COLUMN_NAME varchar(255) not null; 这 ...

  3. 平衡树:为什么Redis内部实现用跳跃表

    摘要:Redis使用跳跃表(skiplist)作为有序集合(zset)的底层实现之一. 本文分享自华为云社区<5分钟了解Redis的内部实现跳跃表(skiplist)>,作者:万猫学社. ...

  4. CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!) A ~ D

    A. 给定一个序列,对于任意1<=k<=n 都满足|ai−ak|+|ak−aj|=|ai−aj|, 找满足条件的i和j并输出 思路: 观察样例,发现输出的是最大值和最小值,那么猜答案是最大 ...

  5. zookeeper 是如何保证事务的顺序一致性的?

    zookeeper 采用了全局递增的事务 Id 来标识,所有的 proposal(提议)都在被 提出的时候加上了 zxid,zxid 实际上是一个 64 位的数字,高 32 位是 epoch(时 期; ...

  6. 深入理解Java虚拟机-HotSpot虚拟机对象探秘

    一.对象的创建过程 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载.解析和初始化过.如果没有,那就先执行相应的类 ...

  7. 请说说你对Hibernat的理解?JDBC和Hibernate各有什么优势和劣势?

    Hibernate是一个轻量级的持久层开源框架,它是连接Java应用程序和关系数据库的中间件,负责Java对象和关系数据之间的映射.Hibernate内部对JDBC API进行了封装,负责Java对象 ...

  8. 如果leader crash时,ISR为空怎么办?

    kafka在Broker端提供了一个配置参数:unclean.leader.election,这个参数有两个值:true(默认):允许不同步副本成为leader,由于不同步副本的消息较为滞后,此时成为 ...

  9. FiddlerEverywhere注册账号进行激活失效问题

    有关FiddlerEverywhere通过邮件激活账号时,激活链接提示已失效问题:这个链接有进行一个讨论(https://www.telerik.com/forums/unable-to-activa ...

  10. XML 文档定义有几种形式?它们之间有何本质区别?解析 XML 文档有哪几种方式?

    XML 文档定义分为 DTD 和 Schema 两种形式,二者都是对 XML 语法的约束,其 本质区别在于 Schema 本身也是一个 XML 文件,可以被 XML 解析器解析,而且 可以为 XML ...