unity2d_unity2d 动画 - CSDN
精华内容
参与话题
  • [Unity3D] 2D像素游戏(一) Hello Unity

    万次阅读 多人点赞 2018-08-22 17:47:49
    Unity面板 面板介绍 面板调整 内置预设 自定义预设 操作模式 预热 创建第一个GameObject Sprite(精灵) 寻找素材 导入素材 创建精灵 拓展阅读 引言 事先声明:这儿只是一位自得其乐的游戏开发爱好者的...

    引言

    事先声明:这儿只是一位自得其乐的游戏开发爱好者的学习笔记,不追求绝对正确和优雅高效,但尽量保证简单易懂(怕自己以后也看不懂自己在写些什么),如果不小心误导了大家,那真是无意之举了。单纯期盼最后能做出一款属于自己真正的小游戏而已,只是突然萌生了用博客记录过程的想法。那么赶紧开始吧!

    使用的软件

    • Unity 2018.2(小游戏还不会用到很多高端技术,只要不是太老的Unity应该都可以)
    • Visual Studio 2015(之后会写C#脚本,因此编译器还是需要的)
    • Photoshop CC 2017(处理素材&自创素材&编辑插图)
    • GifCam(制作动图的小软件)

    Unity面板

    面板介绍

    创建一个2D Project之后,就看到了好多面板,这里务必要简单介绍一下主要面板的作用。
    这里写图片描述

    • 场景(Scene):游戏呈现的场景就会显示在这里,相当于一个预览的作用。
    • 层次(Hierarchy):该场景的所有游戏物件都会在一个列表上显示的清清楚楚
    • 项目(Project):也就是项目文件夹啦,整个项目的文件目录。
    • 属性(Inspector):直译的话叫“检视”,但我觉得它更符合“属性”的概念,任何一个对象的具体信息都会在这里呈现。
    • 游戏(Game):模拟游戏运行时的画面,就跟游戏发布后一模一样。

    面板调整

    如果你的第一反应是:这怎么跟我的Unity长得不一样?
    那就对了。我之前进行过面板位置的调整,毕竟要每天一直看着它,总得调的赏心悦目一点。

    内置预设

    在上面的工具栏里: Window -> Layouts
    这里写图片描述
    里面都是自带的窗口设计,总有一款合你口味。

    自定义预设

    当然里面的Save Layout功能也不是摆设,你可以保存当前面板为一个自定义预设,下次再也不怕打乱面板了!

    操作模式

    顶部的一排按钮也非常的实用,但是!我现在只用下面这几个:
    这里写图片描述 :拖拽模式。不想碰到场景里的东西,只想移动视角,就在这个模式下按住鼠标拖拽画面吧。快捷键 Q ,2D模式下还可以直接使用鼠标右键
    这里写图片描述 :移动模式。想移动某一个物件的时候,就在这个模式下移动物体。快捷键 W
    这里写图片描述 :运行。想测试游戏的时候,按播放键自动跳转到游戏面板开始测试。
    这里写图片描述 :暂停。想暂停测试的时候,按暂停键中断测试。

    预热

    在正式开始上手之前,最后再分析一波各个面板间的联系。
    首先一个项目代表了一整个游戏,而一个场景文件代表了一个关卡,所有的场景文件最好都保存在项目面板里的Scenes文件夹下(养成好的分类习惯!)。我们设计一个关卡的时候,场景面板呈现关卡的样貌,而关卡里的游戏物件都会列在层次面板里面,物件的信息都在属性面板。我们测试运行的时候,由摄像机(也属于游戏物件)捕捉场景画面呈现在游戏面板上。开发游戏就是个不断创建文件,不断添加功能,不断调试运行的过程。

    创建第一个GameObject

    一个游戏很多时候是围绕着主角进行的,所以我们首先要创建一个主角出来。

    Sprite(精灵)

    2D模式下最常用的物体就是精灵(Sprite)精灵使一张毫无生机的平面图像变身成为可以操作,运动,碰撞等等的一个活生生的游戏物体。当然这需要我们把图像、脚本等功能性组件依附到我们的游戏物体上。

    寻找素材

    如果大家有自己喜欢的像素小人是最好不过的了,这里既然只是做个学习笔记,我也就自己随便画一个胖嘟嘟的火柴人充数吧。
    这里写图片描述
    好啦!一个可爱的主角诞生了!(大家拿去用是我的荣幸)
    这里写图片描述

    导入素材

    需要先把图像导入到项目里,步骤是:

    • 项目里先通过右键 -> Create -> Folder 新建一个Sprites 文件夹,用来存放所有的Sprites图像。
    • Sprites中空白处右键 -> Import New Asset... ,选择自己的主角导入。

    此时项目中应该有类似这样的视图:
    这里写图片描述
    如果美工(这里指自己)给完图片,你还想修改文件名的话,只需在文件名上极其缓慢地单击两下就可以重命名。这里就顺便给“火柴人”取个名字吧,叫LittleBuddy

    创建精灵

    • 层次里,右键 -> 2D Object -> Sprite ,我们会看到一个New Sprite

    接下来是官方推荐的标准动作,建议在创建每个GameObject之后都做一下。

    • 重命名:属性中最上方是名字更改,改为Player
    • 重置: 属性中的Transform栏的右上角,有一个小齿轮,单击后选择下拉列表里的Reset 重置坐标

    现在的精灵处于No Sprite的状态,我们把刚刚导入的LittleBuddy依附到Player上。

    • LittleBuddy项目里拖到Sprite Render栏的Sprite里。
      我

    至此已经看到左边的Scene已经出现了我们的小巴迪,那就算是已经创建成功了。
    另外值得一提的是,属性中可以看到Player初始带有2个组件:TransformSpriteRender。所有的GameObject最后都是通过加载组件的方式成为一个真正被我们所操纵的实例对象的,通过组件可以非常方便的添加/删除某些功能。这也是为什么Unity的上手度比较强的原因之一。

    赶快运行一下!
    这里写图片描述
    Hello LittleBuddy!

    拓展阅读

    Sprite简介
    https://blog.csdn.net/BeUniqueToYou/article/details/74616061?locationNum=8&fps=1

    Unity官方教程《Space Shooter》中文图文版
    https://www.jianshu.com/p/8cc3a2109d3b

    Unity官方教程《Roll-a-ball》中文图文版
    https://www.jianshu.com/p/6e4b0435e30e

    展开全文
  • Unity 2D游戏制作

    万次阅读 2017-09-05 11:30:32
    调试背景 2D游戏的制作最重要的是层的...创建2D object改名BackGround设置背景图片修改为BackGround 0层 创建2D object添加大雁图片Ctrl+6,保存,把大雁动态模型全选,插入。调整时间可以看起来舒服,调整所在层为Ba

    调试背景

    2D游戏的制作最重要的是层的设置

    先设置两个层①Layers②Edit Layers③Sorting Layers添加两个层BackGround和Front

    调试大雁

    创建2D object改名BackGround设置背景图片修改为BackGround 0层

    创建2D object添加大雁图片Ctrl+6,保存,把大雁动态模型全选,插入。调整时间可以看起来舒服,调整所在层为BackGround 1层

    添加脚本使大雁从屏幕右边开始飞入左边飞出

    publicclassSwanFly : MonoBehaviour {

        //天鹅起飞的位置

        privateVector3 startPosition;

        publicfloat speed;

             // Use this for initialization

             void Start () {

            Debug.Log("屏幕的宽度" + Screen.width);

            Debug.Log("屏幕的高度" + Screen.height);

            Vector3 screenSize = Camera.main.ScreenToWorldPoint(newVector3(Screen.width, Screen.height, 0));

            float swanExtentsX = transform.GetComponent<Renderer>().bounds.extents.x;

            startPosition = newVector3(screenSize.x + transform.position.y, transform.position.z);

            transform.position = startPosition;

             }      

             // Update is called once per frame

             void Update () {

            if (transform.position.x <-startPosition.x)

            {

                transform.position = startPosition;

            }

            transform.Translate(Vector3.right * -1 * speed * Time.deltaTime);

             }

    }

    调整草地

    设置空物体,在其中创建草地,两边超过相机边框。

    在空物体上挂载BoxCollider2D组件,点击EditCollider 会有一个绿色方框调整位置

    如图所示即可

     

     

    游戏对象设置

    设置球添加Front0层,挂载Circle Collider2DRigibody2D组件

    创建一个2D空物体挂载脚本,随机产生球

    publicclassCreatBall : MonoBehaviour {

        //保龄球预制体

        publicGameObject ballPrefab;

        //产生的范围

        privatefloat createRange;

        //产生的时间

        publicfloat rate;

             // Use this for initialization

             void Start () {

            Vector3 screenSize = Camera.main.ScreenToWorldPoint(newVector3(Screen.width, Screen.height, 0));

            float ballExtentsX = ballPrefab.transform.GetComponent<Renderer>().bounds.extents.x;

            createRange = screenSize.x -ballExtentsX;

        }

             // Update is called once per frame

             void Update () {

            rate -= Time.deltaTime;

            if (rate<0)

            {

                Vector3 position = newVector3(Random.Range(-createRange, createRange),transform.position.y, transform.position.z);

                GameObject ball = Instantiate(ballPrefab, position, Quaternion.identity) asGameObject;

                //下一个保龄球产生的时间

                rate = Random.Range(1.5f, 2.5f);

                Destroy(ball, 3f);

            }

             }

    }

    调试接物体的物体

    创建两个2D object分别添加帽子的内沿和外沿,外沿为内沿的子物体

    内沿层Front 0层  外延层Front 1层

    分别挂载Edge Collider 2D组件,内沿勾选Is Trigger,发生碰撞

    设置Edit Collider

    外沿 内沿

    挂载脚本接球然后销毁产生粒子效果

    publicclassHatController : MonoBehaviour {

        //帽子移动的范围

        privatefloat HatMoveRange;

        //粒子产生的位置

        publicGameObject particleSystemPoint;

        publicGameObject particle;

             // Use this for initialization

             void Start () {

            Vector3 screenSize = Camera.main.ScreenToWorldPoint(newVector3(Screen.width, Screen.height, 0));

            float hatExtentsX = transform.GetComponent<Renderer>().bounds.extents.x;

            HatMoveRange = screenSize.x -hatExtentsX;

        }

             // Update is called once per frame

             void Update () {

            Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            float x = Mathf.Clamp(mousePosition.x,-HatMoveRange, HatMoveRange);

            transform.position = newVector3(x, transform.position.y, transform.position.z);

             }

        voidOnTriggerEnter2D(Collider2D col)

        {

            //粒子产生

            GameObject tempParticle = Instantiate(particle,particleSystemPoint.transform.position, Quaternion.identity)asGameObject;

            Destroy(col.gameObject);

            Destroy(tempParticle, 2f);

        }

    }

    设置粒子效果

    设置预制体的Renderer Sorting LayerFront 2

    离子产生的位置设置一个2D空物体成为帽子内沿的子物体,调整位置



    展开全文
  • Unity 2D 入门

    万次阅读 多人点赞 2017-07-14 13:34:43
    原文:Introduction to Unity 2D 作者:Sean Duffy 译者:kmyhy 3/15/17 更新说明: 升级至 Unity 5.5。Unity 是一个非常流行和强大的游戏引擎,它支持众多的平台和设备。尽管 3D 游戏最近火热,大部分手机游戏、...

    原文:Introduction to Unity 2D
    作者:Sean Duffy
    译者:kmyhy

    3/15/17 更新说明: 升级至 Unity 5.5。

    Unity 是一个非常流行和强大的游戏引擎,它支持众多的平台和设备。尽管 3D 游戏最近火热,大部分手机游戏、控制台和桌面游戏仍然是以 2D 方式呈现的,因此学习用 Unity 编写 2D 游戏仍然非常重要。

    在本教程中,你将编写一个 2D 太空登陆游戏, 并学到如下技能:

    1. 如何使用精灵和相机。
    2. 如何使用物理 2D 组件处理碰撞和玩法。
    3. 如何创建 2D 动画和状态。
    4. 如何使用图层和精灵的 order。

    如果你还没安装 unity 5,请从 Unity 官网下载它。

    注意:如果你是第一次接触 Unity,你可以看看我们的《Intro to Unity 教程》 ,以便加快你的学习进度。

    开始

    从这里下载本教程的开始项目,解压缩,用 Unity 打开 LowGravityLander-Start 项目。

    在项目窗口中,打开 Scenes 文件夹下的Lander-Start 场景。你会在 Game 视图中看到:

    开始项目已经能够运行,但你还需要解决几个问题才能真正完成它。

    准备发射(当在着陆点着陆时更是危机四伏)!让我们开始吧!

    注意:对于 Unity 2D 游戏,Unity 编辑器会自动处于 2D 模式。当你创建新项目时,可以选择 2D 或 3D 模式:


    在开始项目中已经设置好这个选项了。

    精灵

    通过 Unity 强大的 2D 引擎和内置编辑器,我们很容易使用精灵。

    要向游戏中添加精灵,从项目文件夹中将它拖到你的场景视图即可。这真的很简单,打开场景视图,然后从 Sprites 文件夹中,将 playership 精灵图片拖到你的场景视图。

    在结构视图中,点击 Unity 为你创建的 playership 游戏对象,在检视器中查看它的属性。注意 Unity 会自动添加一个 Sprite Renderer 组件到游戏对象中,这个组件包含了你的 playership 图片:

    OK!Sprite Renderer 允许你将图片用做 2D/3D 场景中的精灵。

    从结构视图中删除 playership 游戏对象。

    Sprite Modes

    在 Assets/Sprites 文件夹中选中一个精灵图片。在检视器中,你可以有三种不同的模式来使用这个精灵:

    • Single: 只有一张图片的精灵。
    • Multiple: 使用多张图片的精灵,比如动画或精灵表单(spritesheet,同一个角色图片由多个图片组成)。
    • Polygon: 自定义精灵的多边形形状,你可以用各种原始形状来创建,比如:三角形、方块、五边形、六边形等等。

    一个精灵表单是一张包含多个更小图片的单张图片,比如:

    使用精灵表单的原因是游戏中用到的每一张图片都会占用一次绘制动作。当精灵图片非常多时,这会产生非常大的负担,而且你的游戏会变得复杂臃肿,导致潜在的问题。

    通过精灵表单,你可以在一次绘制中绘制多个精灵图,提升游戏性能。当然,在精灵表单中如何组织这些精灵图是一个学问,那就是另一篇教程的事情了。

    精灵编辑

    将多张图片放到一张图片是很有用的,这样就可以用于动画或者允许对象拥有多个动作。通过 Unity 的 2D 精灵表单编辑器,能够轻易管理这些精灵表单。

    在这个游戏中你将用到两个精灵表单:一个用于登陆舱的推进器动画,一个用于爆炸效果。这两个动画都由多个播放帧组成,你可以用精灵编辑器编辑和分割它们。

    explosion-spritesheet.png 是用于爆炸效果的,它已经切分好了, 但 thruster-spritesheet.png 图片仍然需要处理,这是你接下来的工作。

    在项目窗口的 Sprites 文件夹中点击 thruster-spritesheet.png。在检视器中,它的 Sprite Mode 已经是 Multiple 了(如果不是,请修改为 Multiple 并点击 Apply)。

    然后,点击 Sprite Editor:

    弹出一个窗口,显示了自动切分成多个帧的精灵表单(下图中的数字是方便演示而添加的,不是截图中的内容):

    点击窗口左上角的 Slice,你会看到默认的切分动作是 Automatic:

    Automatic 表示 Unity 会自动搜索并切分你的精灵表单,以它自己的方式。但你也可以以 cell size 和 cell count 方式来切分你的精灵表单。

    选择 cell size 将允许你以像素单位的方式来指定每一帧的大小。

    在精灵编辑器中,点击 Slice 菜单下面的 Grid by Cell Size:

    在 Pixel Size,将 X 设为 9,Y 设为 32。将 Pivot 设为 Center,其它值保持为 0,然后点击 Slice:

    点击精灵编辑器窗口的 Apply,将修改应用到精灵表单:

    这就完成了——你可以关闭精灵编辑器了。推进器的精灵表单已经就绪。

    将精灵赋给登陆舱

    现在,还不能在游戏中看到登陆舱。因为它还没有被添加上任何 Sprite Renderer组件。不会有任何壮观的着陆场景——或者坠毁效果!——如果登陆舱甚至不能在屏幕上看到的话。

    要解决这个问题,点击结构视图中的 Lander 游戏对象。在检视器中,点击 Add Component,在搜索栏中输入 Sprite Renderer。然后,选中 Sprite Renderer 组件,在组件属性中点击 Sprite 右边的圆圈,选择 playership 精灵图片:

    将 Order in Layer 设置为 1。

    接下来的工作是设置起落架的精灵图。
    在 Lander 游戏对象下方,选择 LanderFeet 游戏对象,然后点击 Sprite Renderer 组件中 Sprite 选择器右边的小圆圈。然后从 Select Sprite 窗口中选择 lander-feet 图片:

    点击 Play;你可以在游戏视图中查看你的登陆舱了。通过 WASD 或者箭头键在屏幕上移动:

    2D 镜头和单位像素

    Unity 2D 项目默认带有一个正交视图相机。

    在 2D 游戏中,通常你会用这种相机而不是透视视图相机。接下来你会了解正交视图和透视视图的区别。

    下图显示了 Lander 项目中的默认的相机设置:

    注意,Projection (投影)属性现在是 Orthographic(正交)。

    在项目窗口中,选择 playership 精灵图,然后在检视器中查看它的 Import Settings。在 Pixels Per Unit(单位像素)属性中,当前默认为 100:

    这里的 100 是什么意思呢?

    术语:单位像素

    在 Unity 中“单位”一词不一定和屏幕像素对应。相反,你的对象的大小只是相对于其它对象的,它可以是任意大小,比如:1 个单位 = 1 米。对于精灵图片,Unity 用“单位像素”来定义它们以“单位”计算的大小。

    假设有一张精灵图,是一张 500 像素宽度的图片。下表显示了当绘制这个精灵时,在不同的缩放系数以及不同单位像素时,它的 x 轴上的宽度的变化:

    还是没看懂?下面会对这个计算过程进行说明:

    假设有一个游戏,使用了静态相机来全屏显示背景,就好像电脑桌面上的墙纸。

    backdrop.png 的高是 2048,默认单位像素是 100。如果你稍微心算一下,就会知道在结构视图中的游戏对象 backdrop 的高度是 20.48 个单位。

    当然,正交相机的 Size 属性会将屏幕高度折半,因backdrop 游戏对象的真实高度应当也经过直角转换,即 10.24:

    当然,你不需要修改项目中的相机,因为当前的 Size 为 5 ,对于这个游戏中的移动相机来说刚刚好。

    星系

    在精灵的 Import 设置中有一个 Max Size 属性,允许你指定精灵的最大尺寸,单位为像素。你可以根据目标平台来修改这个设置。

    放大一下背景是淡蓝色星系的场景视图。注意它有一点模糊;当你导入一张精灵图片时,Max Size 属性默认是2048。Unity 会将图片缩小以适应默认的纹理尺寸,这会导致图片质量下降。

    要解决这个问题,在项目窗口中选中这张 backdrop 图片,勾选 Override for PC、Mac & Linux Standalone,然后将 Max Size 修改为 4096。点击 Apply,然后 Unity 会花几秒钟重新导入这张图片到场景视图中。你会发现背景突然变得清晰明锐了:

    将 Max Size 设为 4096 将告诉 Unity 用 4096x4096 大小的纹理贴图,这样你就可以看出原图的细节显示。

    但是,这确实会付出一些代价。查看下图中的检视器的的预览区域;背景贴图的大小现在是 4 M,而原来是 1 M。

    纹理贴图的大小增加后,会使它的内存暴增 4 倍。

    值得注意的是,根据 Unity 所支持的平台的不同,可能会有针对其它平台的 Override 设置。如果你准备将游戏编译到这些平台时,你可以使用这些 Override 设置,从而在不同的平台上使用不同的大小和格式。

    注意:4096x4096 是十分大的图片文件了,尽可能避免使用这么大的文件,尤其是对于手机游戏来说。这个项目中只是为了演示才使用这么大的图片。

    贴图

    你还可以修改贴图的格式:

    你可能想修改某些贴图的格式,以提升图像质量,或者压缩它们的大小,但这要么会增加图片在内存中的占用,要么会降低图片的保真度。最好是理解每个参数的作用,尝试修改它们并比较贴图最终的尺寸和质量。

    将 Use Crunch Compression 设置为 50% 的压缩时间会长一点,但文件尺寸会变得最小,当然你后面仍然可以调整它。

    将 backdrop 的 Import 设置改回之前的内容,然后再修改 Format 和 Crunch Compression 设置,然后点击 Apply。

    在开发你自己的游戏时,你可以尝试不同的压缩率以在最小大小和质量之间找到一个结合点。

    2D 碰撞和物理

    Unity 中你可以像在 3D 游戏中一样修改 2D 物理引擎的重力。对于新项目 Unity 默认将重力设置为地球重力,也就是 9.80665 m/s2。但如果你将飞船降落在月球上,而不是地球上,则重力就应当是地球重力的 16.6%,也就是 1.62519 m/s2

    注意:在开始项目中,重力被设置为 -1,以便你更容易起飞和测试游戏。

    要修改游戏的重力,点击 Edit / Project Settings / Physics 2D 然后用 Physics2DSettings 检视器面板将重力的 Y 值从 -1 修改为 -1.62519:

    点击 Play,运行游戏,四处飞一下,看看重力对你的飞船的移动有什么影响:

    碰撞

    如果你曾经试过引导登陆舱,那么你也可能碰到过一两块岩石了。这是因为 Unity 的 2D 碰撞系统生效了。

    每个会受重力和其它物体影响到的对象,都需要拥有一个 2D 碰撞体组件和一个 2D 刚体组件。

    在结构视图中选中 Lander 这个游戏对象;你会看到它带有有一个 2D 刚体和一个 2D 多边形碰撞体组件。在一个精灵上添加一个 2D 刚体组件将让它接受 Unity 2D 物理系统的管理。

    物理组件的简单介绍

    一个 2D 刚体组件表示重力将对这个精灵产生作用,你可以在脚本中通过力来控制这张图片。如果你想让这个精灵受其它对象影响并和其它对象发生碰撞,你还需要添加一个 2D 碰撞体。添加碰撞体组件将使精灵能够响应和其它精灵发生的碰撞。

    多边形 2D 碰撞体相对于其它简单的碰撞体,比如盒子碰撞体或圆形碰撞体来说,要耗费更多的性能,但它能和其它物体发生更精确的碰撞。尽可能地使用最简单的碰撞体能够确保你达到最佳性能。

    碰撞多边形

    在你的飞船上尝试一下碰撞体,从结构视图中选择 Lander 游戏对象,在 Polygon 2D Collider 中点击 Edit Collider:

    在场景视图中,将鼠标至于碰撞体的边沿;当手柄出现,你可以移动碰撞体的端点;也可以添加或删除端点,从而改变碰撞体的形状:

    现在,将 Lander 的碰撞体恢复原样。

    注意:在 Lander 游戏对象附属的 Lander.cs 脚本中,我们用 OnCollisionEnter2D 去处理和其它对象的碰撞。如果碰撞力超过某个设定值,登陆舱就会坠毁。

    你的降落坐垫也需要一个碰撞体;不然的话在着陆的时候你的飞船会直接落下。

    在结构视图中,双击 LanderObjective 游戏对象,让降落坐垫居中显示。在检视器中,点击 Add Component,选择 Box Collider 2D 组件:

    Unity 会为 LanderObjective 游戏对象添加一个盒子 2D 碰撞体组件,并自动将碰撞体的大小设为和精灵图的大小一样。很好!

    对于刚体和 2D 碰撞体组件,有几点需要注意:

    • 如果你想在移动物体时应用变形组件,而不是只有重力能够作用它,可以将刚体的 body type 设为 Kinematic。要保持让它们受 Unity 重力控制,使用 Dynamic。如果要让它们根本不可移动,设为 Static。
    • 还可以修改刚体组件的质量,线性阻力、角阻力和其它物理属性。
    • 碰撞体可以用于 Trigger 模式;在这种模式下,它们不会和其它物体发生物理碰撞,而是允许你用代码在所有 MonoBehaviour 脚本中都有效的 OnTriggerEnter2D() 方法来响应事件。
    • 要在你的脚本代码中处理碰撞事件,可以用 OnCollisionEnter2D() 方法。这个方法在所有 MonoBehaviour 脚本中都是可用的。
    • 可以为碰撞体分配一个可选的 Physics2D 材质,以控制反弹属性或摩擦属性。

    注意:当游戏中只有几个对象的时候,你可能没有注意到,如果屏幕上有数以百计的对象时都参与物理作用时,用更简单的碰撞体形状将大大提升游戏性能。

    如果有大量对象发生碰撞时,你可能不得不重新审视一下使用多边形碰撞体组件的策略。

    登陆舱动画

    你的登录器还不算完,因为还缺少一个看得见的推进器向上助推的效果。现在推进器已经有了,但看不出它喷火的效果。

    Unity 动画 101

    要为游戏对象增加动画效果,需要为这个对象添加一个包含所需动画的 Animator 组件。这个组件需要引用一个 Animation Controller,这个 Controller 定义了将要使用的动画剪辑,以及这些剪辑的控制方式,以及其它“发烧级”特效,比如混合和动画的过渡。

    推进器的动画控制器

    在结构视图中,展开 Lander 游戏对象,显示出 4 个下级对象。选择 ThrusterMain 游戏对象,你会看到已经有一个 Animator 组件在上面了,但它还没有对应的动画控制器:

    仍然在 ThrusterMain 游戏对象,点击 Animation 编辑器标签。如果在编辑器主窗口中看不见这个标签,请点击 Window 菜单,然后选择 Animation:

    点击 Create 按钮,创建一个动画剪辑:

    名字输入 ThrusterAnim,位置选择 Assets/Animations 文件夹。

    你会在项目窗口的 Animations 文件夹看到 2 个新的动画资源。ThrusterAnim 这个动画剪辑中保存了推进器的动画,ThrusterMain 则是控制这个动画的动画控制器:

    在动画窗口,你会看到一个时间轴;在时间轴上,你可以对每个推进器的图片帧进行排序或添加。

    点击 Add Property ,属性类型选择 Sprite Renderer/Sprite:

    你的编辑器现在看起来是这个样子:

    在项目窗口,点击 Sprites 文件夹,展开 truster-spritesheet.png 图片。选中 4 个切片图,然后拖到动画编辑器的 ThrusterMain : Sprite 时间线。

    动画帧在时间线中重叠在一起,你可以根据需要重新安排。首先从最右边的图片开始;点击这张图片,将它向右拖,置于 0:05 秒处:

    选中最后一帧,用 Delete 键删除它。

    点击动画窗口的 Record 按钮一次,关闭这个剪辑的记录模式,防止意外修改到这个动画:

    接下来配置动画控制器。

    Lander.cs 脚本当前的 Animation参数设置为 true 或 false,表明玩家是否点火了推进器。动画控制器应该负责计算这些参数并允许某些状态被修改。

    在项目窗口,点击 Animations 子文件夹,双击 ThrusterMain.controller。这会打开动画编辑器,当你在 ThrusterMain 游戏对象上创建动画剪辑时,Unity 会自动添加这个控制器。

    现在推进器动画正在持续运行。

    正确地说,推进器动画只应当在玩家当前已经点火了推进器才播放。

    右击动画编辑器中的网格区域,然后选择 Create State/Empty:

    在检视器中,将新状态命名为 NoThrust。这是动画在玩家没有任何输入时的默认状态:

    从 Entry 处,Animator 会走到 NoThrust 并停下来,直到布尔值变成 true。为了改变动画状态,你必须添加一个 transition 连接。

    在 Entry 状态上右击,选择 Make Transition。再点击 NoThrust 状态,这会从 Entry 添加一个箭头指向 NoThrust。右键点击 NoThrust,选择 Set As Layer Default State。NoThrust 会变成如下图所示的橙色:

    橙色表明这个状态将会是播放时的第一个状态。

    在 Animator 编辑器中,点击 Parameters 标签中的 + 按钮,创建一个新的 Bool 型参数,命名为 ApplyingThrust:

    右击 NoThrust,点击 Make Transition,然后点击 ThrusterAnim。这会创建一个转换,允许在两个状态之间改变。执行同样步骤,创建一个从 TrhusterAnim 到 NoThrust 的转换:

    点击从 NoThrust 到 ThrusterAnim 之间的转换线条,在检视器中点击 +,添加一个条件。这个选项只对条件 ApplyingThrust 有效。

    从下拉框中选择 true。也就是说只有 ApplyingThrust 为 true 时,动画才会变成 TrusterAnim 状态。

    现在编辑从 ThrusterAnim 到 NoThrust 之间的转换,同样适用 ApplyingThrust 条件,但这次将条件设为 false:

    完成后的动画控制器变成这个样子:

    在 Animator 编辑器中,你可以调整动画回放速度为一个合适的值。点击 ThrusterAnim 状态,在检视器中,修改 Speed 属性为 1.5:

    推进器动画应该对用户按下扳机进行即时响应。点击两条转换箭头(NoThrust 和 ThrusterAnim 之间的两条),在检视器中,将转换有关的设置修改为 0。反选 Has Exit Time 和 Fixed Duration:

    最后,你需要将相同的动画和控制器应用到左右推进器。在结构视图中,选择 ThrusterLeft 和 ThrusterRight,将 ThrusterMain.controller 从项目窗口的 Animations 文件夹拖到 Animator 组件的 Controller 属性上:

    点击 Play,运行游戏;用 WASD 或箭头键试一下你的推进器吧!

    休斯顿,起飞吧!

    精灵的排序和图层

    如果精灵不进行排序的话,2D 引擎的事情不能算完。Unity 允许你使用图层系统和图层顺序来进行精灵的排序。

    点击 Play,再次运行游戏;拿出你吃奶的力气去碰撞旁边的大石头吧!观察编辑器中的场景视图,当 Restart 按钮显示时,有一些石头会消失在幕布图片之后:

    这是因为渲染引擎无法得知精灵的摆放顺序。所有精灵,除了飞船之外,都用的是默认的图层顺序 0。

    要解决这个问题,需要使用图层和图层排序系统来分隔精灵。Unity 会按照指定的图层顺序来将精灵们绘制在图层上。对于每个图层,Unity 会按照精灵在图层中的序号依序绘制。

    点击 Edit 菜单,然后点击 Project Settings,选择 Tags & Layers。展开 Sorting Layers 一节。

    点击 +,添加 3 个新的图层:

    • Background
    • Rocks
    • Player

    点击并拖动每个图层旁边的句柄,将他们的顺序设置为如下所示。你的图层顺序决定了 Unity 的绘制这些图层中的精灵的顺序:

    从结构视图中点击 Backdrop;在 Sprite Render 组件中点击 Sorting Layer 下拉框,然后选择列表中的 Background:

    展开 Rocks 游戏对象,选中所有下级的 rock 游戏对象。在检视器中,将这些对象的Sorting Layer 统统设置为 Rocks:

    由于场景中的岩石是前后交叠的,很方便用它们来演示同一图层中的精灵的 Order in Layer 属性的用法。

    如果你不为 Rocks 图层中的每个岩石分配一个排序值,你会发现在游戏中,岩石会随机地从其它岩石上“弹出”。这是因为 Unity 无法以同一的顺序绘制岩石,因为它们在图层中的顺序都是0。

    找到交叠在一起的岩石,将位于较前面的岩石指定一个更大的 Order in Layer 值。

    修改 Lander 及其子对象,以及 Pickups 下面的所有 Fuel 游戏对象的 Sprite Renderer Sorting Layer 属性为 Player。这将确保它们绘制在所有东西之前。

    但有一个问题。对于推进器动画该怎么办(而且,登陆舱的脚架正常情况下应当隐藏在登陆舱下面)?如果我们不指定它们的 Order in Layer 数值,我们会看到一些奇怪的现象。

    将 Lander 的 Order in Layer 属性修改为 2。选中 Thruster 的所有子对象和 LanderFeet 对象,设置它们的 Order in Layer 为 1。

    当登陆舱碰到登录平台时,平台会微微下沉,表示你已经着陆。登录平台和岩石精灵是彼此交叠的,为了使结果看起来正确,你必须将登录平台排在岩石的后面。

    将 LanderObjective 精灵设置为 Rocks 图层,然后指定它的 Order in Layer 为 0。

    设置 LanderObjective 下方的岩石的 Order in Layer 值设置为 1:

    最后,选中 Prefabs 文件夹中的 Explosion 预制件,将它的 Sorting Layer 设置为 Player:

    点击 Player,试一下你的飞行技巧,点火推进器,落到着陆平台上——注意不要在一个反向上推得过猛,以便撞到岩石上!

    结束

    你可以从这里下载本教程完整的示例项目。

    你已经学习了 Unity 的大部分重要的 2D 设计功能,你已经有一个好玩的重力着陆游戏去“秀”一下了!

    如果想进一步学习 Unity 的 2D 工具和功能,你可以看一下官方的 Unity 2D 游戏制作文档。

    希望你喜欢这个教程——请在下面的评论中留言或提问。我期望与你交流!:]

    展开全文
  • Unity 2D游戏基本知识笔记

    千次阅读 多人点赞 2019-09-15 01:08:06
    目录 操作知识 角色移动(方法一) 角色移动(方法二) 角色移动(方法三) 角色移动(方法四) 方向键操控角色 更改角色Sprite 获取对象速度 获取对象位置 复制对象 ...响应键盘按键函...

    目录

    操作知识

    角色移动(方法一)

    角色移动(方法二)

    角色移动(方法三)

    角色移动(方法四)

    方向键操控角色

    更改角色Sprite

    获取对象速度

    获取对象位置

    复制对象

    销毁对象

    鼠标(手指)对对象的操作

    获取鼠标光标位置

    隐藏鼠标光标

    播放音频

    Sleep(休眠)

    读写存档变量

    删除变量存档

    按Esc退出游戏

    加载其它场景(Sence)

    响应键盘按键函数

    角色发生碰撞(接触)事件函数

    鼠标相关函数

    触发器常用函数

    显示图片

    显示文字

    代码知识

    求绝对值

    求开方

    定义数组

    定义二维向量坐标

    队列使用

    调试打印输出

    读写其他脚本的变量

    使用其他脚本的函数

    技术探讨

    方括号的4种用法

    Update()、FixedUpdate()和LateUpdate()的区别

    Awake()和Start()的区别





    操作知识


    角色移动(方法一)

    gameObject.transform.Translate(Time.deltaTime * Speed, 0, 0);
    //右移,其中Speed为float类型变量,后两个参数分别是竖直方向和图层前后方向
    
    GameObject.Find("player").transform.Translate(Time.deltaTime * Speed, 0, 0);
    //寻找名字为"Player"的对象,并让它移动
    //但是当对象过多时,会耗时很多
    
    //此方法是让物体每次都向目的方向瞬间平移一定距离,无视碰撞
    //所以在撞到边缘之后会出现不停抖动的情况,不推荐使用

    角色移动(方法二)

    transform.GetComponent<Rigidbody2D>().AddForce(Vector2.right*100);
    //瞬间给当前物体施加一个水平向右的力使其速度为100
    
    //此方法适用于普通的物理物体,但是由于速度会叠加,没有最大速度
    //且方向控制很麻烦,也不推荐使用

    角色移动(方法三)

    Rigidbody2D Player;
    float Speed = 600f;
    void Start() {
        Player = transform.GetComponent<Rigidbody2D>();
    }
    void Update () {
        Player.velocity = new Vector2(Speed, Speed);    //分别为水平方向和竖直方向的速度
    }
    
    //这个方法最好,不但速度稳定检测碰撞而且改变速度方便迅速,推荐移动角色时使用

    角色移动(方法四)

    Vector2 Speed = new Vector2(1, 0);    //设置速度方向和大小
    public Rigidbody2D rigidbody;
    
    void FixedUpdate() {
        rigidbody.MovePosition(rigidbody.position + speed * Time.deltaTime);
    }
    //每次都是瞬间移动过去再判断是否有碰撞器的,当速度过大时可能会穿过其它碰撞器

    方向键操控角色

    //写在Update函数里
    float BallX = Input.GetAxis("Horizontal");    //改为“Vertical”即竖直方向
    if (BallX ==1) {
        //向右移动的代码
    }
    if (BallX ==-1) {
        //向左移动的代码
    }
    //但是我发现它最后有一点延迟,原因不明,就不喜欢用

    更改角色Sprite

    //初始化(可以写在Start函数里)
    SpriteRenderer Player;
    public Sprite Picture;    //Inspector界面拖拽Sprite赋值
    Player = this.GetComponent<SpriteRenderer>();
    
    //更改Sprite
    Player.sprite = Picture;

    获取对象速度

    Rigidbody2D Player;
    Player = GetComponent<Rigidbody2D>();     //获取当前的物理物体对象
    float Speed = Player.velocity.magnitude;

    获取对象位置

    Vector3 Pos = transform.position;
    
    //把对象位置赋值给Pos(包含图层一共三个数据)
    //可用Pos.x Pos.y Pos.z调用
    
    //或者这样写:
    Vector3 Pos = gameObject.transform.position;

    复制对象

    Instantiate(Transform, new Vector2(0,0), Quaternion.identity);
    
    //Transform处写该类型的变量名一般可以public定义,然后拖拽赋值
    //第二个参数是新对象的位置

    销毁对象

    Player.gameObject.SetActive(false);
    //Player为对象名字

    鼠标(手指)对对象的操作

    void OnGUI() {
        if (Event.current.type == EventType.MouseDown) {
            //这里写鼠标按下(屏幕触摸按下)对象的代码
        }
        if (Event.current.type == EventType.MouseDrag) {
            //这里写鼠标拖动(屏幕触摸滑动)对象的代码
        }
        if (Event.current.type == EventType.MouseUp) {
            //这里写鼠标抬起(屏幕触摸抬起)对象的代码
        }
    }

    获取鼠标光标位置

    Pos = Event.current.mousePosition;
    //获取当前光标位置,其中横坐标和纵坐标分别是Pos.x和Pos.y,原点在左上角,单位为1像素

    隐藏鼠标光标

    Cursor.visible = false;    //隐藏
    
    Cursor.visible = true;    //显示

    播放音频

    AudioSource.PlayClipAtPoint(AudioClip, transform.localPosition);
    //AudioClip就是音频变量,赋值后就可以用了

    Sleep(休眠)

    Thread.Sleep(100);
    
    //在文件开头要加上导入语句:
    using System.Threading;

    读写存档变量

    PlayerPrefs.SetInt("读取对象的名字", a);    //把a的值写入存档里
    
    int a = PlayerPrefs.GetInt("读取对象的名字");    //读取存档值,赋值给a

    删除变量存档

    PlayerPrefs.DeleteAll();        //删除所有存档
    
    PlayerPrefs.DeleteKey("这里是删除对象的名字");    //删除指定key对应的信息

    按Esc退出游戏

    void Update() {
        if (Input.GetKeyDown(KeyCode.Escape)) {
            Application.Quit();
        }
    }

    加载其它场景(Sence)

    SceneManager.LoadScene("场景名");

    响应键盘按键函数

    if (Input.GetKey(KeyCode.LeftArrow)) {    //按左向键
        //这里写事件代码
    }
    //KeyCode里包含了基本所有按键

    角色发生碰撞(接触)事件函数

    void OnCollisionEnter2D(Collision2D c) {    //重载,可以没有参数
        if (c.gameObject.name == "碰撞对象的名字") {
            //这里写操作代码
        }
    }

    鼠标相关函数

    //针对脚本对应的对象
    
    void OnMouseUp() {    }        //鼠标左键抬起(屏幕触摸抬起)
    
    void OnMouseDown() {    }       //鼠标左键按下(屏幕触摸按下)
    
    void OnMouseEnter() {    }        //鼠标光标指向
    
    void OnMouseExit() {    }       //鼠标光标移开

    触发器常用函数

    void OnTriggerStay() {    }        //player持续Trigger触发事件
    
    void OnTriggerEnter() {    }        //player触碰Trigger触发事件
    
    void OnTriggerExit() {    }        //player离开Trigger触发事件

    显示图片

    void OnGUI() {
        GUI.DrawTexture(new Rect(Posx,Posy,Weight,Height), Texture);
        //Texture为图片类型,位置为(Posx,Posy),尺寸为Weight * Height (像素)
    }

    显示文字

    void OnGUI() {
        GUIStyle fontStyle = new GUIStyle();    //设置字体变量
        fontStyle.normal.textColor = new Color(R,G,B);   //R,G,B都在(0,1)之间
        fontStyle.fontSize = 100;       //字体大小
        GUI.Label(new Rect(Posx,Posy,Weight,Height), "hello" , fontStyle);    //显示文本
    }

     


     

    代码知识

    求绝对值

    int ans = Math.Abs(num);    //求整数num的绝对值,赋值给ans
    
    float ans = Mathf.Abs(num);    //求浮点数num的绝对值,赋值给ans

    求开方

    float ans = Mathf.Sqrt(a);
    //求a的开方,并赋值给ans

    定义数组

    int[] a = new int[4];    //定义长度为4的一维数组a
    
    int[,] a = new int[4, 4];    //定义4*4的二维数组a
    
    int[] a=new int[5]{1,2,3,4,5};    //定义并初始化一维数组a
    
    int[] a={1,2,3,4,5};    //定义并初始化一维数组a
    

    定义二维向量坐标

    Vector2 a = new Vector2(10, 10);
    //定义a,并赋值

    队列使用

    //需要在开头加:
    using System.Collections.Generic;
    
    //队列名为q,类型可改
    Queue<int> q = new Queue<int>();
    
    //进入队列
    q.Enqueue(a);    //变量a的值进入队列
    
    //统计队列长度
    int size = q.Count;    //把长度赋值给size;
    
    //取出元素
    int a = q.Peek();    //取出队尾元素,赋值给a
    int a = q.Dequeue();    //取出队尾元素,赋值给a,并删除队尾元素
    
    TrimExcess();    //重新设置队列容量,删除Dequeue后的元素
    
    Clear();    //清空队列

    调试打印输出

    Debug.log(a);    //输出a的值(只能有一个参数)
    
    print("哈哈哈"+a);    //可以输出变量字符串叠加,中间用“+”连接

    读写其他脚本的变量

    //假设脚本一的文件名为Script1,先在第一个脚本将需要扩展的变量定义为public,如
    public static int a = 10;
    
    //在第二个脚本中可以用Script1.a来使用并更改这个变量的值,如
    int ans = Script.a;
    
    //修改同理,如
    Script.a=20;

    使用其他脚本的函数

    //假设被调用函数的脚本名为Script1,且被调用的函数为:
    
    public static void Sum() {
        //函数内容
    }
    
    //那么在其他脚本使用该函数时写作:
    
    Script1.Sum();

     


     

    技术探讨

    方括号的几种用法

    /*变量序列化*/
    
        [SerializeField]
        int a;    //这里,a只需在Inspector窗口中赋值一次,以后打开项目i都会有初始值了,这就叫序列化
    
        //对于加了public的变量就不需要了,会自动序列化的,而对于private变量则需要加上才能序列化
    
        [NonSerialized]
        public int a;    //这里,a不会被序列化,Inspector窗口不会显示该变量
    
        [HideInInspector]
        public int a;    //这里,a会被序列化,但是Inspector窗口不会显示,顾名思义只是被隐藏起来了
    
    
    
    /*使Component菜单下出现自定义的类*/
    
        [AddComponentMenu("XXX/XXX/XXX")]    //其中的“/”用来分割父类和子类
    
    
    
    /*运行前执行脚本*/
    
        [ExecuteInEditMode]
        //这里写类
    
    执行情况:
    1.当场景中的某个物体发生变化时调用Update函数
    2.当GameView接收到一个Event时调用ONGUI函数
    3.当SceneVidw或者GameView重绘时调用OnRenderObject和其他的渲染回调函数
    4.当加载时调用Awake函数
    5.当第一次激活时调用Start函数
    6.当该MonoBehavior在编辑器中被赋于给GameObject的时候调用Awake、Start函数
    7.当Play按钮被按下游戏开始后调用Awake、Start函数
    8.当Play按钮停止后调用Awake、Start函数
    9.当在编辑器中打开包含有该MonoBehavior的场景的时候调用Awake、Start函数
    
    
    
    /*在添加脚本的时候会自动添加写上去的属性*/
    
        [RequireComponent(typeof(ClassName))]    //ClassName即为属性名,比如Rigidbody
    
    
    
    

    Update()、FixedUpdate()和LateUpdate()的区别

    Update() 每一帧的时间不固定,受当前渲染的物体影响
    
    FixedUpdate() 固定的时间间隔调用,故物理属性的更新操作应它,这样表现效果会更平滑逼真。
    其时间间隔可以在项目设置中更改:Edit->Project Settings...->Time->Fixed Timestep
    
    LateUpdate() 在所有Update函数调用后被调用,跟随物体的摄相机用它效果最好,可防止瞬移和抖动

    Awake()和Start()的区别

    Awake()先于Start()执行。
    
    使用方法:
    在Awake()中获取游戏对象或者脚本实例的信息
    在Start()中进行一些获取之后的初始化设置

    最近依次更新时间:2019.09.15

    展开全文
  • UNITY 2D入门基础教程 (一)

    万次阅读 2016-11-11 14:28:26
    如果用以前版本的Unity做2D游戏,虽然能做,但是要费很多周折. 比如你可以将一张纹理赋予一个”面片”网格,然后用脚本控制它的动画调整它的位移.如果你要使用物理引擎,那么还要将这个Obeject处理3D的,所以你还要确保你...
  • Unity-2D游戏开发套件指南-免费资源

    千次阅读 2019-10-09 12:05:01
    今年年初,Unity Brighton的内容团队推出了他们的最新作品-2D游戏开发套件,该套件适用于任何希望学习在Unity中创作2D游戏的人,在不编写任何代码的情况下使用2D游戏开发套件,通过设置与拖放便能快捷的实现你的...
  • 在我们找资源的时候,有时候会遇到那种把一堆图片放进一张png图片里面的...那么我们现在把图片导入到Unity中,选中图片你会看到左边的Inspector界面 然后,选择Texture Type类型为Advanced,如下面左图: 将Read/Wri
  • unity2d之2d帧动画创建

    万次阅读 2016-03-24 15:21:15
    在2d游戏中帧动画的应用是非常广泛的,那么如何在unity中创建一个帧动画,主要是下面几个步骤。 一,导入图片 把美术给的动画图片导入unity,并把图片属性设置成下图中的属性 二,创建动画 选择要生成动画的图片...
  • Unity3d-加载Texture2D

    万次阅读 2012-04-25 11:46:59
    加载图片有几种方法 1.Resource.Load:在编辑器的Resource文件夹中放置资源,不仅仅是图片。可以是不同层次的Resource文件夹,注意没有后缀名,所以…… ...3.自己写通过类通过Texture2D.LoadImage等
  • private Rigidbody2D rig; //刚体 private float jumpForce ; //跳跃的力 private float horizontal; //水平偏移量 private float moveSpeed; //水平移动速度绝对值 private float move; //水平移动速度(左 或 ...
  • unity开发状态下2d与3d模式的转换

    千次阅读 2017-01-28 16:06:01
    Unity中,2D和3D只是一种视角上的转换,所有的物体都是有3D坐标信息的,在Vector3转为Vector2,并且视图方式由透视变为正交的时候,Z轴信息就没有意义了,也就从3D变为了2D2D模式:层级视图中只有一个正交摄像机...
  • Unity2018新功能之2D Animation2D动画

    万次阅读 2018-07-21 15:21:49
    新版本中引入不少2D的新功能,我们打开资源包管理器,可以看到2D Animation,2D IK,2D Pixel Perfect,2D SpriteShape等等。 我们先来讲讲2D Animation的功能。 2D Animation的安装 点击菜单Window &gt; ...
  • 今天项目中需要用到黑夜灯光照射,由于普通的2DSprite使用的材质是不接收光反射的。所以我们必须修改Sprite Renderer的材质。第一步,建立工程下面是我建立的工程,你会发现Point l
  • unity3d 代码动态添加,修改BoxCollider2D

    万次阅读 2014-06-12 11:41:56
    tempQie2.AddComponent();  tempQie2.GetComponent().center =new Vector2(0f,0f);  tempQie2.GetComponent().size = new Vector2(0.32f, 0.32f);
  • Unity Texture2D缩放

    千次阅读 2015-05-14 09:14:45
    Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight) { Texture2D result = new Texture2D(targetWidth, targetHeight, source.format, false); float incX = (1.0f /
  • Unity Tilemap模块全攻略

    万人学习 2019-02-01 15:31:02
    这是Tilemap相关的系列教程,在Unity2017.2以及以上版本中提供了这样的新功能,他可以快速的设计2D关卡,减少关卡设计的重复操作,提高效率,很有魅力的一个模块,跟五斗米老师一起学习吧,你一定会为这个新功能欢呼...
  • 本小主在这里给大家分享一下unity 2D游戏开发中制作帧动画的两种方法。 比较简单,一学即会。 方法一: 是用代码控制: 先创建一个2D工程。导入图片资源,并设置texture的texture type为sprite,看下图...
  • using UnityEngine;using System.Collections; public class CameraController : MonoBehaviour { public Ray myRay; // Update is called once per frame void Update () ... if(Input.GetMouseButtonDow
  • 建议大家能够熟练使用这些软件后,再决定买正版。 接触的这些个软件,都是只能对单个精灵进行变化。...这些个特效插件,比较试用与2D像素特效。毕竟特效不像纸娃娃 Day and Night Cycle With Scatteri
  • 在网络小游戏中有时候会有这样的需求的就是Texture和Texture2D类型的转换,例如:本地选择头像更换,背包图片的更新等.当然这方法只适用于小量级的小需求,大的需求会使用专门的处理类完成处理. 小游戏一般会使用更省...
1 2 3 4 5 ... 20
收藏数 34,812
精华内容 13,924
关键字:

unity2d