查看原文
其他

使用Sprite Shape构建2D世界

Unity Unity官方平台 2018-11-15

Sprite Shape(精灵形状)可以帮助开发者在Unity中创建出各种形式的丰富2D环境,并通过直观的可视化工作流程根据需要装饰环境。该工具基于设定的角度范围集合,通过沿着样条曲线路径动态地平铺精灵。

 

本文将介绍如何使用Sprite Shape,为形状制作碰撞体并使用一些脚本构建特性功能环境。


 

请注意:Sprite Shape目前仍处于预览版阶段,将在未来发布可用于正式制作的版本。这意味着本文中介绍的工作流程和编程API可能会在之后版本中发生变化。


安装Sprite Shape

如果你使用Unity 2018.1或更高版本,可以通过使用资源包管理器Package Manager为项目安装Sprite Shape。

 

点击Window > Package Manager,然后选择All标签页找到2D Sprite Shape资源包,并将它添加到项目中。


创建形状

1

Sprite Shape配置文件

 

Sprite Shape通过在场景中创建的样条路径作为游戏对象来平铺精灵。要创建路径,首先必须设置Sprite Shape Profile(精灵形状配置),它用于定义和存储关于特定类型形状的信息。

 

在Sprite Shape Profile中,我们将分配需要使用的精灵,并告诉Sprite Shape如何渲染它们。例如:我们可以根据形状一部分所面对的方向,形状是否拥有填充纹理等来配置要显示的精灵。

 

现在创建配置文件。在项目视图的Assets文件夹窗口单击右键,选择Create > Sprite Shape Profile,其中有三种配置文件类型:Empty、Strip和Shape。不同类型的区别仅在于它们预设角度范围的数量。

 

我们先制作Strip配置文件,接下来处理角度范围。我们可以在检视窗口编辑配置文件。观察Angle Ranges下的圆圈会发现,它已被完全填充,这意味着它有一个预定义的角度范围。当曲线面向该特定方向时,角度范围决定渲染该路径的哪些精灵。角度范围覆盖整个圆圈表示同样的精灵会一直显示。

 

在检视窗口的Sprites属性下,可以点击“+”或“-”按钮添加或删除Angle Range中的新精灵,现在让我们给该形状添加精灵吧。


 

请注意:本示例及之后示例中,我们都将使用2D Game Kit中免费提供的精灵。


2

Sprite Shape游戏对象 

我们已设置好配置文件,可以使用该配置文件创建Sprite Shape。为了在新建形状上自动使用该配置文件,请在Assets文件夹窗口中选中该文件,右键单击层级窗口,选择2D Object > Sprite Shape。

 

 

如果你不小心创建空白Sprite Shape或是打算使用不同的配置文件,可以在Sprite Shape Controller组件中指定或修改配置文件。

 

 

该游戏对象的另一组件是Sprite Shape Renderer,其作用类似Sprite Renderer组件,允许让我们修改精灵的材质、颜色和图层顺序。


3

编辑样条曲线(Spline)

现在可以在Sprite Shape Controller选项中点击Edit Spline来编辑形状。启用该功能后,我们可以在场景中重新安排、添加和删除样条曲线上的节点。添加新节点时,只要左键单击样条曲线上的位置即可。删除节点时,先选择节点,然后按下Delete删除。

 

 

现在介绍Sprite Shape Controller组件中的Point Modes。目前我们使用线性点模式(Linear point mode),这意味着节点不会形成曲线。如果切换为其它模式,例如镜像模式(Mirrored mode),选中节点时,将看到节点带有二条切线,移动切线时可以修改贝塞尔曲线的形状。

 

 

第三个模式是非镜像模式(Non-Mirrored mode)。启用该模式会解除二条切线的链接关系,在调整其中一条切线的时候不会影响另一条切线。



4

使用精灵编辑器 

如果我们希望以特定方式平铺精灵,则需要手动调整精灵。在上面的示例中,由于使用了桥式精灵,会得到由桥体各部分组成的形状。如果我们想把它做成一条长的桥梁,要怎么做?

 

我们可以使用精灵编辑器(Sprite Editor),了解精灵编辑器的特定功能将更高效地使用Sprite Shape,并根据需要轻松调整精灵。

 

下面视频将介绍如何使用精灵编辑器。

 


首先编辑桥体精灵。选中该对象,在检视窗口中找到Sprite Editor按钮,点击该按钮会出现Sprite Editor窗口。

 

我们主要使用到的精灵编辑器功能是精灵周围的四个绿色控制点,以及右下角Sprite窗口的Border设置。使用Border设置可以告诉Sprite Shape要平铺形状的哪个部分以及要使用哪部分作为边界精灵,这些精灵只会在路径的开始和终点或角度边角进行渲染。我们可以调整桥体精灵的左右边界,确保只平铺桥体的中间部分。

 


另一个可以使用的设置是精灵轴心点(Pivot point)。轴心决定如何通过样条曲线渲染精灵。目前桥体精灵的轴心点在中心位置,这会使样条曲线在中心位置经过轴心点。如果将轴心点设在桥体顶部,该精灵会在样条曲线下渲染。

 

该方法非常实用,能够调整为形状自动生成碰撞体的相对位置,以及能够使用Sprite Shape更精确地装饰环境。


5

精灵变体 

在勾勒环境时,Sprite Shape允许为每个角度范围指定多个精灵,并在形状上切换这些精灵。该功能可以为形状添加多样化视觉效果,或创建道具和装饰“画笔”。

 

首先准备了一个简单的悬挂苔藓配置文件,带有二个指定给单个角度范围的精灵。我们可以使用该配置文件给场景中的形状添加装饰苔藓。

 

 

得到满意的形状后,我们可以修改样条曲线上各部分需要渲染的精灵变体。选择要修改部分的起始点,设置Sprite Shape Controller组件上的Sprite Index为其它精灵。


添加碰撞

Sprite Shape能为形状自动生成碰撞体,我们可以手动调整自动生成的碰撞体。

 

对于目前的开放式Sprite Shape,可以使用Edge Collider 2D组件来处理。在检视窗口将该组件添加到Sprite Shape游戏对象。此时Sprite Shape Controller组件中会出现Update Collider设置,勾选该设置后,碰撞体会根据形状实时进行调整。

 

 

处理好形状后,如果我们打算手动修改碰撞体,请首先取消勾选Update Collider,否则该设置会重写修改内容。然后在Edge Collider 2D组件下,点击Edit Collider,然后根据需要调整碰撞体。

 

 

我们可以将游戏角色放入场景中测试新碰撞体。


封闭式形状

现在我们已经熟悉了Sprite Shape和Strip配置文件的基础知识,下面让我们了解如何使用多个角度范围创建封闭式形状。

 

首先我们简要回顾之前的二个Sprite Shape Profile。Empty配置文件没有任何预设角度范围,Shape配置文件有八个预设角度范围。我们的形状只需要四个角度范围,所以让我们使用Empty配置文件,学习如何添加定义角度范围。


1

定义角度范围 

选中新配置文件,创建角度范围时,我们可以点击预览圆圈的空白位置或点击下方的Create Range按钮进行创建。

 

一旦创建好角度范围后,我们可以点击选中该角度范围,通过数值定义起始点或终点,或是拖拽范围上的图示到理想位置。

 

 

我们需要四个角度范围,所以设置每个角度范围为90度角。这一步完成后,可以分别为每个角度范围分配一个精灵,让形状看起来是个完整地形。

 

接下来,使用该配置文件来在场景中创建新形状。

  

 

由于定义了角度范围,形状会自动成为封闭式形状。我们可以随时在场景中选择形状,启用或禁用Sprite Shape Controller组件中的Open Ended复选框,从而修改形状类型。

 

另外我们的新形状有些问题:首先它没有填充纹理,其次形状的边角不会渲染任何精灵。我们可以在该Sprite Shape Profile中轻松修改这些内容。

 

2

添加填充纹理 

为了填充形状的内部,我们必须在配置文件中加入填充纹理。这一步可以在检视窗口中的Fill选项下完成。我们还可以将它改为理想分辨率。

 

下面将使用2D Game Kit中的一个平铺作为纹理。

 

 

关于填充纹理需要了解几点内容。首先填充纹理必须作为独立文件导入,不能作为精灵图集的一部分导入。此外在导入设置中,必须将Wrap Mode设为Repeat。如果没有正确设置Wrap Mode,该纹理会产生瑕疵。


3

使用边角精灵 

使用填充纹理后,形状的效果更好了,但我们还是缺少形状边角部分的精灵。Sprite Shape中的选项最多可以添加八个独立边角精灵,每个精灵对应形状的特定位置。

 

边角精灵可以在Sprite Shape Profile中的Corners部分指定。本示例中,我们将指定八个边角精灵中的六个精灵。形状使用的边角精灵数量可能会有所不同,具体取决于创建路径类型。

 

指定好边角精灵后,需要告诉形状这些边角精灵要用在什么位置。进入Edit Spline模式,在此选择形状上的独立边角节点,将节点的Corner Mode设为Automatic。


对样条曲线上的节点附加对象

我们介绍了Sprite Shape界面和工作流程的大部分内容,现在还可以通过脚本扩展该功能。

 

下面是一个示例脚本,该脚本能在场景中将对象附加到样条曲线的节点上。

using System.Collections;

using System.Collections.Generic;

using UnityEditor;

using UnityEngine;

using UnityEngine.U2D;

[ExecuteInEditMode]

public class NodeAttach : MonoBehaviour

{

   public SpriteShapeController spriteShapeController;

   public int index;

   public bool useNormals = false;

   public bool runtimeUpdate = false;

   [Header("Offset")]

   public float yOffset = 0.0f;

   public bool localOffset = false;

   private Spline spline;

   private int lastSpritePointCount;

   private bool lastUseNormals;

   private Vector3 lastPosition;


   void Awake()

   {

       spline = spriteShapeController.spline;

   }


   void Update()

   {

       if (!EditorApplication.isPlaying || runtimeUpdate)

       {

           spline = spriteShapeController.spline;

           if ((spline.GetPointCount() != 0) && (lastSpritePointCount != 0))

           {

               index = Mathf.Clamp(index, 0, spline.GetPointCount() - 1);

               if (spline.GetPointCount() != lastSpritePointCount)

               {

                   if (spline.GetPosition(index) != lastPosition)

                   {

                       index += spline.GetPointCount() - lastSpritePointCount;

                   }

               }

               if ((index <= spline.GetPointCount() - 1) && (index >= 0))

               {

                   if (useNormals)

                   {

                       if (spline.GetTangentMode(index) != ShapeTangentMode.Linear)

                       {

                           Vector3 lt = Vector3.Normalize(spline.GetLeftTangent(index) - spline.GetRightTangent(index));

                           Vector3 rt = Vector3.Normalize(spline.GetLeftTangent(index) - spline.GetRightTangent(index));

                           float a = Angle(Vector3.left, lt);

                           float b = Angle(lt, rt);

                           float c = a + (b * 0.5f);

                           if (b > 0)

                               c = (180 + c);

                           transform.rotation = Quaternion.Euler(0, 0, c);

                       }

                   }

                   else

                   {

                       transform.rotation = Quaternion.Euler(0, 0, 0);

                   }

                   Vector3 offsetVector;

                   if (localOffset)

                   {

                       offsetVector = (Vector3)Rotate(Vector2.up, transform.localEulerAngles.z) * yOffset;

                   }

                   else

                   {

                       offsetVector = Vector2.up * yOffset;

                   }

                   transform.position = spriteShapeController.transform.position + spline.GetPosition(index) + offsetVector;

                   lastPosition = spline.GetPosition(index);

               }

           }

       }

       lastSpritePointCount = spline.GetPointCount();

   }

   private float Angle(Vector3 a, Vector3 b)

   {

       float dot = Vector3.Dot(a, b);

       float det = (a.x * b.y) - (b.x * a.y);

       return Mathf.Atan2(det, dot) * Mathf.Rad2Deg;

   }

   private Vector2 Rotate(Vector2 v, float degrees)

   {

       float radians = degrees * Mathf.Deg2Rad;

       float sin = Mathf.Sin(radians);

       float cos = Mathf.Cos(radians);

       float tx = v.x;

       float ty = v.y;

       return new Vector2(cos * tx - sin * ty, sin * tx + cos * ty);


当移动锚点节点或旋转其切线时,对象的Transform也会变化。

 

 

像这样的脚本可以用于创建动态环境,或让环境对玩家输入做出反应。它也能够让我们更轻松构建关卡原型,而且不必重新定位独立元素。

 

Sprite Shape脚本API仍处于开发阶段,如果你想要尝试使用Sprite Shape,可以通过Visual Studio Solution Explorer的Assembly Reference访问仍在编写的API文档,多数API与Unity.2D.SpriteShape.Runtime相关。


小结

后续我们还会介绍Sprite Shape的功能和UI,如果项目带有Sprite Shape资源包,你可以在项目中访问脚本API。


我们期待开发者能够使用Sprite Shape创作出精彩的作品,有关于此功能的反馈欢迎访问Unity官方中文论坛(UnityChina.cn)!



推荐阅读


官方活动

直播预告 | Unity面部捕捉解决方案课程(第一期)

9月26日晚8点,Unity技术直播课程将带来Facial AR Remote面部捕捉解决方案系列课程的第一期,感兴趣的朋友赶紧预约吧![了解详情...

直播课程:Facial AR Remote面部捕捉解决方案课程(第一期)

直播地址:https://connect.unity.com/events/unitychina-facialar


Unity官方教师培训报名火热进行中

Unity将在10月22-26日,举办为期5天的专业的Unity官方教师培训课程,诚邀广大教师与Unity一同学习分享最新技术![了解详情...

报名地址:

https://connect.unity.com/events/2018jiaoshipeixun


Unity开学季|重磅教育活动来袭

九月开学季,Unity将在南京、南昌、上海开展重磅教育活动,欢迎教育领域的领导、专家、教师团队莅临交流![了解详情...


优惠活动|Unity订阅新起航,开启您的创作之旅

现在访问Unity在线商店(store.unity.com),成功订阅Unity Pro专业版、Unity Plus加强版即可享受全新增值服务组合。11月18日之前订阅,更有指定插件资源限时赠送。[了解详情...]

活动地址:https://store.unity.com/cn


点击“阅读原文”访问Unity官方中文论坛

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存