26.2D相关-Tilemap瓦片地图-瓦片地图关键脚本和碰撞器
26.1 知识点
回顾瓦片地图编辑
- 回想创建新建瓦片文件,拖入瓦片图片,场景新建不同层级瓦片地图,拖入瓦片到场景的步骤。
瓦片地图相关组件参数
Grid网格组件
Cell Size 单元格大小
- 网格单元格的大小,可以调整图集中的每单位像素,改变每个瓦片图片在场景中的显示大小。
Cell Gap 单元格间隙
- 网格之间的间隔大小。
Cell Layout 单元格布局
- 网格单元的形状和排列。
- Rectangle:矩形
- Hexagon:六边形
- Isometric:等距布局,单元格为菱形
- Isometric Z as Y:等距布局,但Unity将单元格Z轴转换为局部Y坐标。
Cell Swizzle 单元格重排
- Unity将XYZ单元格坐标重新排序为你选择的类型,可以设置2D的两个轴。
Tilemap瓦片地图组件
Animation Frame Rate 动画帧速率
- Unity播放瓦片动画的速率,相当于倍速。
Color 瓦片色调颜色
Tile Anchor 平铺锚
- 瓦片的锚点偏移。
Orientation 方向
- 瓦片地图上瓦片的方向,相当于2D平面使用的是Unity中的哪两个轴。
TilemapRenderer瓦片地图渲染器组件
Sort Order 排序次序
- 设置所选瓦片地图上的瓦片排序方向,其实就是选择原点在哪。
Mode 模式
- 渲染器的渲染模式。
- Chunk:按位置对瓦片进行分组,并将瓦片精灵一起批处理进行渲染,性能较好。
- Individual:单独渲染每个瓦片,会考虑它们的位置和排序顺序。会让瓦片精灵和场景中其他渲染器或自定义排序轴进行交互。
Detect Chunk Culling 检测块剔除边界
- 渲染器如何剔除瓦片地图的边界,就是超出瓦片的范围不渲染的方式。
- Auto:自动检测
- Manual:手动设置拓展边界。
Chunk Culling Bounds 区块剔除边界
- 当选择手动设置剔除拓展边界时,可以在这里自己填写拓展的值。
TilemapCollider2D瓦片地图碰撞器2D组件
为挂载TilemapRenerer脚本的对象添加Tilemap Collider2D脚本,会自动添加碰撞器。注意:想要生成碰撞器的瓦片Collider Type类型要进行设置。
一般直接添加瓦片地图碰撞器即可,注意图片选择的模式。假如是无的话不会有碰撞器,假如是格子的话是整个格子都作为碰撞器。正常选精灵模式就行。
瓦片碰撞器也可以添加复合碰撞器优性能,确定添加会加刚体。可以把自带的刚体设置成静态。
26.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson26_2D相关_Tilemap瓦片地图_瓦片地图关键脚本和碰撞器 : MonoBehaviour
{
void Start()
{
#region 知识点一 回顾瓦片地图编辑
#endregion
#region 知识点二 瓦片地图关键脚本参数
//参数相关
#endregion
#region 知识点三 瓦片地图碰撞器
//为挂载TilemapRenerer脚本的对象添加Tilemap Collider2D脚本
//会自动添加碰撞器
//注意:想要生成碰撞器的瓦片Collider Type类型要进行设置
#endregion
}
}
26.3 练习题
请用TileMap制作,一个横版通关的地图,让一个角色可以在其中移动
创建瓦片资源文件,拖入瓦片图片。场景中创建两个瓦片地图,作为天空背景瓦片地图和普通地图。分别把图片拖入场景。给普通瓦片动态添加瓦片地图碰撞器。
创建一个2D精灵作为玩家,给他添加碰撞器和刚体。注意调整两个瓦片地图和玩家对象的层级。
创建玩家移动和跳跃脚本控制,写移动和跳跃的逻辑
public class PlayerObject1 : MonoBehaviour
{
public float moveSpeed = 3;
private SpriteRenderer sr;
private Rigidbody2D rigidBody2D;
private float h;
void Start()
{
rigidBody2D = this.GetComponent<Rigidbody2D>();
sr = this.GetComponent<SpriteRenderer>();
}
void Update()
{
h = Input.GetAxis("Horizontal");
rigidBody2D.velocity = new Vector2(h * moveSpeed, rigidBody2D.velocity.y);
if (h < 0)
sr.flipX = true;
else if (h > 0)
sr.flipX = false;
if (Input.GetKeyDown(KeyCode.Space))
{
rigidBody2D.AddForce(Vector2.up * 300);
}
}
}
做平台效用器的话,可以重新拖入图片资源到瓦片地图上。资源是可以重复利用生成瓦片图片资源的。可以把新生成的瓦片图片资源设置碰撞器类型为None。拖入刚刚创建的图片资源,因为设置为None不会在对应图片资源生成瓦片碰撞器。我们可以创建空物体添加平台碰撞器,调整位置和大小放到瓦片碰撞器的位置。这样就做成瓦片碰撞器了。
不要局限于瓦片碰撞器。假如做一个可以被跳跃销毁的顶箱子或者踩怪,可以直接拖入图片作为2D对象,然后写逻辑,不使用瓦片相关也没问题。
请用TileMap制作,一个有伪Z轴的地图,让一个角色可以在其中移动
2D游戏中模仿3D游戏纵深的感觉是通过Y轴充当伪Z轴进行的。瓦片地图用等距瓦片Y和Z。
使用等距瓦片Y和Z要在项目设置中设置透明度排序模式为自定义轴,并且调整下面透明度排序组为0,1,-0.26
只要是等距瓦片,就应该把Tilemap的渲染模式切换成Individual。只要会把格子单个渲染,排序不会出问题。
等距瓦片和等距瓦片z和y的区别是,开启了下面改变Z轴的选项。等距瓦片把瓦片丢到场景里按-和+不会调整伪Z轴的距离,等距瓦片z和y会改变。
做伪z轴的时候要注意调整轴心点。这里把轴心点调整到对象中下位置。拖到场景中
发现瓦片图片资源没和菱形对齐的时候,要去瓦片图片资源中设置轴心点。有可以用下面和菱形匹配。
注意玩家对象要把精灵排序点设置为锚点,这样才会以我们刚刚设置好的脚底轴心进行排序计算。对比发现当玩家轴心点小于瓦片轴心代理时,瓦片会盖在上面。大于时玩家会在上面。
假如把瓦片图片资源的轴心点改到最上面是可以解决显示问题。但是瓦片的菱形会和图片产生偏移导致对不准。让编辑看起来混乱。不建议大家使用。
推荐做法是把玩家层级调的比地面瓦片的层级高。四周墙的瓦片一个是要遮挡玩家的,可以新创建一个瓦片地图做为四周墙瓦片地图,调整四周墙瓦片地图层级比玩家高,就能遮挡玩家。
假如现在场景中加植物的话。可以在创一个瓦片地图,和玩家的层级一样。注意要调整TileRender模式为Individual,注意才能按单个图片轴心点排序。不然只能按整体排序。注意只要玩家的轴心点的y小于瓦片地图的轴心点玩家就会在前面,否则就会在后面。
第二种方式是直接拖入2d精灵图片到场景中充当一个对象。调整层级和玩家的一样。注意设置对象轴心点为脚底下并设置2d精灵渲染器是已精灵排序点已轴心排序。注意也会和玩家对象进行轴心点排序。注意只要玩家的轴心点的y小于2d精灵图片对象的轴心点玩家就会在前面,否则就会在后面。
使用瓦片图片资源的好处是方便拖,但是相比于2d精灵图片对象的缺点是一个瓦片只能放一个对象,2d精灵图片对象可以密集的放很多个对象。
给玩家对象添加刚体和碰撞体。刚体不使用重力并且锁定旋转。
中间的地板成瓦片地图是不应该有碰撞器的。围墙层瓦片地图添加瓦片地图碰撞器。注意围墙的碰撞器类型要选为格子。
添加控制玩家移动的脚本
public class PlayerObject2 : MonoBehaviour
{
public float moveSpeed = 3;
private float h;
private float v;
public SpriteRenderer sr;
void Update()
{
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
this.transform.Translate(Vector3.right * moveSpeed * Time.deltaTime * h);
this.transform.Translate(Vector3.up * moveSpeed * Time.deltaTime * v);
if (h < 0)
sr.flipX = true;
else if (h > 0)
sr.flipX = false;
}
}
发现因为视觉问题,上方的图片一个是偏移一格能移动到的。这个时候可以重复拖图片资源构成相同精灵图片的瓦片资源。但是可以调整当做瓦片资源的碰撞器模式和轴心点,分别做上方视角的墙和下放视角的墙。或者在上方视角的上面在多围一层。靠近的墙调整为没有碰撞器的瓦片资源图片。实现更好的效果。
理清在伪Y轴做跳跃思路,可以添加一个空对象父物体。把刚体碰撞器移动脚本都放在父物体上。子物体选择就只是一张2d图片。跳跃的时候就改变子对象2d图片的y轴就好。真正控制玩家对象的父物体的坐标是没变的。
26.4 练习题代码
Lesson26_练习题
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson26_练习题 : MonoBehaviour
{
void Start()
{
#region 练习题一
//1.请用TileMap制作
//一个横版通关的地图
//让一个角色可以在其中移动
#endregion
#region 练习题二
//2.请用TileMap制作
//一个有伪Z轴的地图
//让一个角色可以在其中移动
//重点知识运用
//1.等距瓦片地图的两项重要设置
//2.两种等距瓦片地图的区别
//3.等距瓦片地图的排序问题
// 3-1:轴心点排序
// 3-2:排序层排序(推荐)
//4.等距瓦片地图角色不使用重力
//5.等距瓦片碰撞器建议使用格子形状
//6.等距瓦片地图上跳跃问题
#endregion
}
}
Lesson26_练习题_PlayerObject1
//引入必要的命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//创建一个脚本继承自MonoBehaviour类,管理角色对象的运动及状态
public class Lesson26_练习题_PlayerObject1 : MonoBehaviour
{
//定义一个公共变量moveSpeed,用于设置角色移动速度
public float moveSpeed = 3;
//定义私有变量sr和rigidBody2D,分别用于存储角色的SpriteRenderer和Rigidbody2D组件,以实现对角色的渲染和物理运动控制
private SpriteRenderer sr;
private Rigidbody2D rigidBody2D;
private float h; //定义一个局部变量h,用于记录玩家水平方向输入的值
//初始化,在脚本首次启动的时候执行,获取角色刚体和SpriteRenderer组件
void Start()
{
rigidBody2D = this.GetComponent<Rigidbody2D>();
sr = this.GetComponent<SpriteRenderer>();
}
//每帧更新一次,根据玩家输入和角色状态更新角色的位置和状态
void Update()
{
//获取玩家水平方向的输入值,并根据输入值来控制角色水平移动
h = Input.GetAxis("Horizontal");
rigidBody2D.velocity = new Vector2(h * moveSpeed, rigidBody2D.velocity.y);
//根据玩家输入的水平方向值来改变角色面朝的方向
if (h < 0)
sr.flipX = true;
else if (h > 0)
sr.flipX = false;
//当检测到玩家按下空格键的时候,给角色一个向上的力,实现跳跃效果
if (Input.GetKeyDown(KeyCode.Space))
{
rigidBody2D.AddForce(Vector2.up * 300);
}
}
}
Lesson26_练习题_PlayerObject2
//引入必要的命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//创建一个脚本继承自MonoBehaviour类,管理角色对象的运动及状态
public class Lesson26_练习题_PlayerObject2 : MonoBehaviour
{
//定义一个公共变量moveSpeed,用于设置角色移动速度
public float moveSpeed = 3;
//定义私有变量h和v,分别用于记录玩家水平方向和竖直方向输入的值
private float h;
private float v;
//定义公共变量sr,用于存储角色的SpriteRenderer组件,以实现对角色的渲染和翻转
public SpriteRenderer sr;
//每帧更新一次,根据玩家输入和角色状态更新角色的位置和状态
void Update()
{
//获取玩家水平方向和竖直方向的输入值,并根据输入值来控制角色移动
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
//水平方向移动(向右为正方向)
this.transform.Translate(Vector3.right * moveSpeed * Time.deltaTime * h);
//竖直方向的移动(向上为正方向)
this.transform.Translate(Vector3.up * moveSpeed * Time.deltaTime * v);
//当玩家输入的水平方向值小于0时,将角色翻转
if (h < 0)
sr.flipX = true;
//当玩家输入的水平方向值大于0时,将角色翻转回来
else if (h > 0)
sr.flipX = false;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com