Unity强化篇(十) —— 基于Unity 2D的Pinball游戏的简单实现(一)

版本记录

版本号 时间
V1.0 2020.07.19 星期日

前言

Unity是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。Unity类似于Director,Blender game engine, Virtools 或 Torque Game Builder等利用交互的图型化开发环境为首要方式的软件。其编辑器运行在Windows 和Mac OS X下,可发布游戏至WindowsMacWiiiPhoneWebGL(需要HTML5)、Windows phone 8和Android平台。也可以利用Unity web player插件发布网页游戏,支持Mac和Windows的网页浏览。它的网页播放器也被Mac 所支持。网页游戏 坦克英雄和手机游戏王者荣耀都是基于它的开发。感兴趣的看下面几篇文章。
1. Unity强化篇(一) —— 如何使用Vuforia制作AR游戏(一)
2. Unity强化篇(二) —— 适用于Unity的HTC Vive教程(一)
3. Unity强化篇(三) —— 适用于Unity的HTC Vive教程(二)
4. Unity强化篇(四) —— Unity 和 Ethereum(一)
5. Unity强化篇(五) —— Unity 和 Ethereum(二)
6. Unity强化篇(六) —— 使用Unity和Photon进行多人游戏简介(一)
7. Unity强化篇(七) —— Unity Sprite Shapes简介(一)
8. Unity强化篇(八) —— 使用Unity运行时网格操作(一)
9. Unity强化篇(九) —— Shader Graph简介(一)

开始

首先,我们看下写作内容:

在本教程中,您将学习如何使用Unity2D技术通过排序组(sorting group),网格编辑器(mesh editor)等来构建老式的弹球游戏(pinball game)。内容来自翻译

下面看下写作环境:

C# 7.3, Unity 2019.3, Unity

下面就是正文了。

在本Unity 2D技术教程中,您将学习在Unity中构建2D游戏的高级技巧。学习如何在构建史诗般的老式弹球游戏“ Snap and Strike”时应用这些技术!

如果您觉得本教程太高级,请先在Unity 2D游戏中研究此入门指南,然后再在Unity 2D教程中How to Make a Game Like Jetpack Joyride in Unity 2D开始。完成后,请返回并进一步提高2D Unity技能。

本教程中的脚本编写很少,但是如果您具有C#编程的基本知识,则将更容易理解。要提高技能,请查看我们的Introduction to Unity Scripting教程。

注意:本教程假定您熟悉使用Unity,并且了解使用Unity UI的方式。如果您不是,请花些时间先阅读我们的Introduction to Unity UI指南。

在完成本教程时,您将了解更多有关以下内容的信息:

  • Sorting groups
  • Sprite masks
  • 9-slice sprites
  • 2D colliders and joints
  • The mesh editor
  • Types of effectors and 2D physics materials

是时候让球滚动了!

确保您使用的是Unity版本2019.3,可以通过Unity Hub下载。

解压缩材料并在Unity中打开starter项目。 项目启动后,请切换到Scene视图,并确保您使用的是2D模式。

1. Exploring the Starter Project

首先浏览该项目。

Assets / RW / Scenes中双击PinballWizard场景。 在层次结构中,您可以看到GameObjects分为以下类别:

  • SoundObjects
  • Main camera
  • Hotspots
  • Static colliders
  • Static panel
  • Animations

单击Play,然后查看弹球表的当前状态。

好吧,事情肯定很有趣! 但是图像目前正在互相争斗以在屏幕上渲染。

您的第一个任务是调整最后三个组的Sorting Layer,以便它们以正确的顺序渲染。

2. Adjusting Your Sorting Layers

排序组(Sorting Group)是用于创建合并的Sorting Layers的一组组件。 即,预制件(prefab)的多个实例在不同的分类层上具有多个对象。

此项目中的Sorting Layers应按以下顺序排列:

  • Panel (lowest layer)
  • Efx
  • Logo
  • Obstacles
  • Top
  • Cover (highest layer)

现在,如下调整您的排序层Sorting Layers

  • 1) Static colliders - 静态碰撞器:这些具有碰撞器的对象构成弹球台的基本碰撞结构。 此处不需要排序组。
  • 2) Static panel - 静态面板:该组中的内容被隐藏。

要显示该组,请在层次结构中选择Static Panel。 然后,单击Add Component,然后选择Rendering ▸ Sorting Group。 在新添加的Sorting Group组件中,找到Sorting Layer下拉菜单,然后选择Panel

  • 3) Animations - 动画:在“层次结构”中选择Animations,然后单击Add Component。 然后,选择Rendering ▸ Sorting Group

Sorting Layer下拉列表中,选择Efx,然后单击Play

您会发现弹球游戏的大多数细节已经在入门项目中。 现在该玩些有趣的东西了:添加动作!


Getting the Ball Rolling

首先,您需要创建一个空的GameObject来保存您的作品。

通过在层次结构中右键单击空白空间,然后选择Create Empty来执行此操作。 现在,将新对象命名为Interactive Parts

在检查器中,通过单击“设置”图标并选择Reset来重置其Transform值。

接下来,再创建七个空的GameObject作为Interactive Parts的子代,并将其命名为:

  • ScrollingTrees
  • BillBoard
  • Plunger
  • Flippers
  • Float Piece Area
  • Road Tunnel Zone
  • Bumpy Parts

确保还重置所有Transform值。

注意:通过选择Interactive Parts游戏对象并按Alt-Shift-N来创建子游戏对象,可以快速创建这些游戏对象。 然后使用Control / Command-D将其复制六次! 然后剩下的就是重命名每个GameObject


Scrolling Trees

接下来,您将使用Sprite Mask仅显示动画的一部分。 看起来像这样:

方法如下:

  • 1) 转到Assets / RW / Sprites,将trees_circle拖动到Hierarchy中的ScrollingTrees上,并将该sprite实例命名为TreeCircle
  • 2) 在检查器中,将Transform Position设置为(X:-0.7,Y:2.2,Z:0),并将其Rotation设置为(X:0 Y:0 Z:17)
  • 3) 在层次结构中右键单击ScrollingTrees,选择2D Object ▸ Sprite Mask,并将其命名为TreeMask
  • 4) 将Transform Position设置为(X:-1.91,Y:2.58,Z:0)并将缩放比例设置为(X:1.48,Y:1.58,Z:1)
  • 5) 在检查器中,转到“ Sprite Mask”组件的“ Sprite”字段,单击circle图标以启动Sprite资产列表,然后选择“trees_mask”
  • 6) 在层次结构中选择TreeCircle。 使用检查器找到Sprite Renderer,然后从Sorting Layer下拉列表中选择Efx。 从Mask Interaction下拉菜单中,选择Visible Inside Mask

1. Scripting the Animation

放置好图形后,就该添加控制动画的脚本了。

双击Assets / RW / Scripts / AnimateController在代码编辑器中将其打开。

在现有变量下面添加以下变量:

public GameObject treeObject;
private float turnSpeed = 30f;

FixedUpdate下添加:

private void FixedUpdate()
{
    if (treeObject != null)
    {
        treeObject.transform.Rotate(new Vector3(0f, 0f, turnSpeed * Time.fixedDeltaTime));
    }
}

这样,无论播放器的帧频是30 FPS60 FPS还是在两者之间波动,都以一致的速度旋转分配给treeObject变量的精灵。 turnSpeed使您可以调整树木旋转的速度。

注意:您可以在官方的Unity文档中了解有关FixedUpdate的更多信息。

单击保存,然后返回到Unity。

在层次结构中选择ScrollingTrees,单击Add Component,然后选择Scripts ▸ Animate Controller。 然后将TreeCircle从检查器拖到Tree Object字段中。

单击Play预览新的工作动画。


Adding the Billboard

如果您无法超越自己的最后成绩,那就没有理由打弹球了! 为了帮助您做到这一点,您接下来将添加一个动画广告牌,其中包括闪烁的灯光。

打开Assets / RW / Sprites / ani_billboard并将aniBillbord0001拖动到层次结构中的BillBoard中。 将子实例命名为AniBillboard

Sorting Layer下拉列表中,选择Top。 单击Add Component,然后选择Miscellaneous ▸ Animator

在检查器中,打开AnimatorController字段,然后单击旁边的circle图标以启动动画师控制器列表。 选择ani_Billboard

Menu ▸ Window中打开Animation窗口,然后单击Play以预览广告牌的外观。

9-slice sprite是另一种有用的2D技术。 调整大小时,此功能保留图形元素的角和边界。

转到Assets / RW / Sprites / ani_billboard并选择一个精灵。 在检查器中,单击Sprite Editor图标以编辑精灵的可拉伸部分。

用于此动画的精灵带有9片精灵,因此现在调整大小将不再是问题。 !

这是在广告牌上使用9片切片的效果:

1. Placing the Billboard

现在,您需要将广告牌放置在弹球机上。

转到层次结构中的AniBillboard,将其“位置”的Transform值设置为(X:1.5,Y:4.3,Z:0),并将其Scale更改为(X:-3.5,Y:2,Z:1)

嗯...有点大,不是吗? 要解决此问题,请将“ Sprite Renderer”中的Draw Mode设置Tiled,将Size设置为Width:1 Height:1。 在Tile Mode下拉菜单中,选择Adaptive

好多了!

2. Adding the Score

通过转到Assets / RW / Prefabs,将scoreText拖动到“层次结构”中的Billboard并将其比例更改为(X:0.41,Y:0.4,Z:1),将分数添加到您的广告牌中。

单击Play以其时尚的新动画广告牌预览您的弹球游戏!


Adding the Ping!

设置好“bling”后,就该将“ping”添加到运动场了! 换句话说,您需要添加使游戏有趣的对撞机。

首先转到“层次结构”,然后将“BumperRamps”“ CurveRamp”Static Colliders移动到Interactive Parts中。


Adding the Plunger

玩弹子球的第一件事就是plunger,这样您就可以从桶中射出一个球并开始游戏!

在现实世界中,玩家会拉回与弹簧圈啮合的柱塞。 释放后,弹簧线圈将球推入运动场。 您希望在应用程序中拥有相同的感觉。

要实现这些机制,请在“层次结构”中选择Plunger。 在Inspector中,添加Rendering ▸ Sprite Renderer组件。

选择Sprite Renderer组件,单击Sprite字段旁边的circle图标,然后将cam资源分配给它。 将Sorting Layer设置为Top,并将Transform Position设置为(X:2.66,Y:-4.6,Z:0)

现在,考虑一下plunger的物理原理。 这是一个有两个要素在起作用的春天:

  • The anchor - 锚点:锚固关节的活动部分,从而建立张力。
  • The spring joint - 弹簧接头:接头的运动部分,可产生力。

接下来,您将需要执行物理操作,以使plunger表现出预期的效果。

1. Adding the Anchor

转到Assets / RW / Prefabs,然后将plungerAnchor拖动到层次结构中的Plunger中以创建子实例。 在检查器中,添加Physics 2D ▸ Rigidbody 2D并将其Body Type设置为Kinematic以固定其位置。

2. Adding the Spring Joint

现在,您已经创建了锚点,是时候创建spring joint了。 这就像拉回并启动plunger的弹簧一样。

为此,请单击层次结构中plungerAnchor旁边的箭头符号以显示其嵌套内容。 选择Plunger-springjoint,然后通过Inspector向其中添加一个Spring Joint 2D

确保选择2D Spring joint选项!

注意:所有2D Joint组件均带有强制性的刚体2D(Rigidbody 2D)

Rigidbody 2D中,将Body Type设置为Dynamic,将Mass设置为2

展开Constraints部分,为“X”启用Freeze Position,为Z启用Freeze Rotation

“Spring Joint 2D”中,选中Enable Collision。 禁用自动配置距离(Auto Configure Distance)。 将距离Distance设置为1,将Frequency设置为10

Connected Anchor设置为(X:0,Y:-1),并将plungerAnchor分配为组件的Connected Rigid Body

在层次结构中,将Assets / RW / Prefabs / plungerEffects拖动到Plunger对象中。 这将创建一个子对象实例。

3. Adding the Plunger Script

最后,是时候控制您添加到plungerspring joint中的物体了。

在检查器中,仍然选择Plunger-springjoint,单击Add Component ,然后选择Scripts ▸ Launcher。 双击以在代码编辑器中启动它。

在现有变量下面声明以下变量:

private SpringJoint2D springJoint;
private Rigidbody2D rb;
private float force = 0f;          // current force generated
public float maxForce = 90f;

然后,在Start末尾添加以下内容:

springJoint = GetComponent<SpringJoint2D>();
springJoint.distance = 1f; 
rb = GetComponent<Rigidbody2D>();

Update中的//#1之后,添加以下行:

// calculates current force of exertion
force = powerIndex * maxForce;

最后,在类末尾添加以下FixedUpdate

private void FixedUpdate()
{
    // When force is not 0
    if (force != 0)
    {
        // release springJoint and power up
        springJoint.distance = 1f;
        rb.AddForce(Vector3.up * force);
        force = 0;
    }

    // When the plunger is held down
    if (pressTime != 0)
    {
        // retract the springJoint distance and reduce the power
        springJoint.distance = 0.8f;
        rb.AddForce(Vector3.down * 400);
    }
}

保存文件并返回到Unity

plungerEffects实例中的plungerEfxZoomplungerEfxLight分配给组件的区域。 将Max Force设置为200

4. Test Your Work

现在,您就可以测试您的新工作的pinball plunger了。

Assets / RW / Prefabs / ball拖到层次结构中以创建实例。 将其Transform Position设置为(X:2.84,Y:-1.08,Z:0)。 单击Play,然后按下并释放空格键以测试您的plunger

现在,您正在滚动!


Adding the Flippers

现在,球从枪管射出,进入比赛区,然后从底部掉落并进入太空。

是时候添加flippers了 - pinball胜利的主要武器! 您将从左侧的flipper开始。

在层次结构中,右键单击Flippers,然后选择Create Empty。 重命名GameObject FlipLeft-hingejoint。 在检查器中,将Transform Position设置为(X:-1.26,Y:-3.8,Z:0),将Scale设置为(X:1.05,Y:1.05,Z:1)

对于右flipper,复制左flipper,并将其重命名为FlipRight-hingejoint。 将其位置设置为(X:0.46,Y:-3.8,Z:0)

再次考虑一下flippers将如何工作。 就像plunger一样,只是这一次您需要使用以下组件旋转flippers

  • Hinge joints - 铰链接头:在旋转点处固定可移动部件。
  • Flipper:活动的flipper-y部分。

接下来,转到Assets / RW / Prefabs,然后将flipperLeft预制件拖入FlipLeft-hingejoint,并将flipperRight预制件拖入FlipRight-hingejoint

1. The Hinge Joints

在层次结构中选择FlipLeft-hingejoint。 转到检查器并添加一个Hinge Joint 2D。 将“刚体”的Body Type设置为Kinematic。 这使该关节成为flipper的固定旋转点。

Hinge Joint 2D中,将flipperLeft实例指定为其Connected Rigid Body

启用Use Limits,然后将Angle Limits设置为“下限”为-30,将“上限”设置为30

突击测验! 由于Left HingeJoint的旋转极限在-30至30度之间,您认为Right HingeJoint的旋转极限应该是什么?

FlipRight-hingejoint创建一个新的Hinge Joint 2D组件。 将其Rigidbody 2D Body Type设置为Kinematic

Right HingeJointAngle Limits为:下限:30和上限:-30

请记住,将flipperRight实例分配为其Connected Rigid Body

2. Adding a Script to Flip

现在,添加脚本以使flippers正常工作。

Assets / RW / Scripts中打开FlipControlLeft.cs

在现有变量下面声明以下变量:

public float speed = 0f;
private HingeJoint2D hingeJoint2D;
private JointMotor2D jointMotor;

Start中添加以下内容以获取您的参考:

hingeJoint2D = GetComponent<HingeJoint2D>();
jointMotor = hingeJoint2D.motor;

然后,在FixedUpdate中的if语句中,添加代码以接合joint’s motor

// set motor speed to max
jointMotor.motorSpeed = speed;
hingeJoint2D.motor = jointMotor;

最后,将else语句添加到同一块block中:

else
{
    // snap the motor back again
    jointMotor.motorSpeed = -speed;
    hingeJoint2D.motor = jointMotor;
}

尝试为右flipper重复上述代码:

  • 1) 声明所需的变量,以访问对象的HingeJoint2DJointMotor2D组件。
  • 2) 创建一个变量,该变量存储电动机的速度值。
  • 3) 在FixedUpdate中侦听用户交互并触发其motor速度。

唯一的区别是,您翻转了速度变量,因为您以另一种方式旋转了flipper

FlipControlRight.cs中,声明相同的变量:

public float speed = 0f;
private HingeJoint2D hingeJoint2D;
private JointMotor2D jointMotor;

Start中存储你的引用

hingeJoint2D = GetComponent<HingeJoint2D>();
jointMotor = hingeJoint2D.motor;

FixedUpdate中的if语句中,添加:

// set motor speed to max
jointMotor.motorSpeed = -speed;
hingeJoint2D.motor = jointMotor;

最后,添加其余的else语句到相同的block中:

else
{
    // snap the motor back again
    jointMotor.motorSpeed = speed;
    hingeJoint2D.motor = jointMotor;
}

保存文件并返回到Unity

将脚本组件FlipControlLeft附加到FlipLeft-hingejoint,将FlipControlRight附加到FlipRight-hingejoint。 将其速度值设置为1700

单击Play,然后使用左右箭头键尝试使用flippers


Road Tunnel Zone

如果您能够将球插入,则在运动场顶部的弯曲轨道会增加球进入CurveRamp的机会,从而获得更多分!

在此步骤中,您将在入口处创建一个涡流,将球吸进隧道,并在另一端吐出。 呜!

1. Force Field With Area Effector 2D

将球实例的Transform Position设置为(X:-2.28,Y:1,Z:0)。 在层次结构中,右键单击Road Tunnel Zone,然后选择Create Empty。 将此对象命名为Force Field

单击Add Component,然后选择Physics 2D ▸ Polygon Collider 2D

在检查器中,单击Edit Collider图标,然后将矢量移动到隧道入口之外的区域。 启用Is TriggerUsed By Effector

单击Add Component,然后选择Physics 2D ▸ Area Effector 2D。 启用Use Global Angle。 然后,将Force Angle设置为90,将Force Magnitude设置为20。在Force Target下拉列表中,选择Rigidbody

点击Play并测试您的新漩涡。

注意:将Force Magnitude增加到200还会使球通过隧道。 但是您将无法使用Surface Effectors 2D,因此在本教程中,将其设为弱漩涡。

2. A Guided Path With Surface Effector 2D

“弱”涡旋仅具有将球推到隧道入口的力量。 接下来,您将创建一条路径来引导球穿过隧道的其余部分。

  • 1) 在层次结构中的Road Tunnel Zone上单击鼠标右键,然后选择Create Empty。 将此新对象命名为Road Surface
  • 2) 在检查器中,单击Add Component,然后选择Physics 2D ▸ Edge Collider 2D
  • 3) 单击Edit Collider图标,然后相应地移动向量。
  • 4) 启用Used By Effector并将Edge Radius增加到0.03

接下来,单击Add Component,然后选择Physics 2D ▸ Surface Effector 2D。 将Force Speed设置为15,将Force Scale设置为1。单击Play

等一下,那个球在做什么? 下一部分将修复行为。

3. Mesh Editing in Unity

此时,当您预览作品时,您会看到球的动作很奇怪。

转到“层次结构”,选择Static Colliders/WallBoard,然后在“检查器”中启用Sprite Renderer。 在这里,您会找到罪魁祸首-一些媒介正在阻挡隧道的入口。

要解决此问题,请转到Polygon Collider 2D,单击Edit Collider图标,然后将令人讨厌的向量移开。 差距不要太大。

注意:为了更快地进行网格编辑:

按住Alt键并单击鼠标左键将光标更改为“手形”图标以移动画布。
Command(Mac)Control(Windows)突出显示顶点,然后单击鼠标左键删除。

再次单击播放。 好了,一切顺利!

4. Blocking With Platform Effector 2D

现在,ForceField将球推到路面上,然后将其沿着隧道引导并直接回到射手,然后……

哇...? 它直接从滑道下降到plunger

那不是很正确。

您需要一个对撞机,以防止球掉入Plunger。 但同时,您需要让球在发射后离开射手。

追溯过去,您可能会使用if-else步步为营。 但是现在,Platform Effector 2D在这里可以节省一天!

在层次结构中的Road Tunnel Zone上单击鼠标右键,选择Create Empty并命名新对象Block Platform

在检查器中,单击Add Component,然后选择Physics 2D ▸ Edge Collider 2D。 然后Edit Collider以移动将阻止出口的矢量。 启用Used By Effector并将Edge Radius设置为0.03

接下来,单击Add Component,然后选择Physics 2D ▸ Platform Effector 2D。 禁用Use Collider Mask。 然后,将Rotational Offset的值设置为90,将Surface Arc的值设置为130。启用Use One Way

点击Play...您已经解决了问题!


Float Piece Area

玩家可以得分更高的另一个好地方是浮动区域。

要实现它:

  • 1) 将球实例的Transform Position设置为(X:-2.2,Y:-0.5,Z:0)
  • 2) 转到Assets / RW / Sprites,然后将floatpiece拖动到Hierarchy中的Float Piece Area对象中。
  • 3) 将子实例命名为Float Area
  • 4) 在检查器中,将Transform Position设置为(X:-2.63,Y:0.18,Z:0),然后选择Logo作为其Sorting Layer
  • 5) 单击Add Component,然后选择Physics 2D ▸ Polygon Collider 2D。 启用Is TriggerUsed By Effector
  • 6) 从Physics 2D ▸ Buoyancy Effector 2D中添加另一个组件。 将Density设置为50。在Damping下,将Linear DragAngular Drag设置为10
  • 7) 将Flow Variation设置为-5,可使浮动效果有所移动。

点击Play查看漂浮效果。

1. Code the Float

现在,您将设置浮动持续时间。 在Assets / RW / Scripts中,双击Floatpiece.cs以在代码编辑器中启动文件。

在现有变量下面声明以下变量:

private BuoyancyEffector2D floatEffector;
public float floatingTime = 0f; // floating duration
private float runningTime = 0f; // the current duration since startTime
private float startTime = 0f;

Start下面,添加:

floatEffector = GetComponent<BuoyancyEffector2D>(); // assign component to this instance

替换OnTriggerEnter2Difblock为下面:

// on enter zone, start float
floatEffector.density = 50;
// start timer
if (startTime == 0f)
{
    startTime = Time.time;
    sound.bonus.Play();
    scoreBoard.gamescore += 10;
    golightRenderer.sprite = golightAniController.spriteSet[0];
    StartCoroutine(BeginFloat());
}

替换整个BeginFloat的方法为下面:

IEnumerator BeginFloat()
{
    while (true) 
    {
        // calculate current duration
        runningTime = Time.time - startTime; 

        // play animation loop
        int index = (int)Mathf.PingPong(handcamAniController.fps * 
                    Time.time, handcamAniController.spriteSet.Length);
        handcamRenderer.sprite = handcamAniController.spriteSet[index];
        yield return new WaitForSeconds(0.1f);
        
        // when time is up            
        if (runningTime >= floatingTime)  
        {
            // stop float and reset timer
            floatEffector.density = 0;    
            runningTime = 0f;
            startTime = 0f;
  
            // stop sound & animation 
            sound.bonus.Stop();
            golightRenderer.sprite = golightAniController.spriteSet[1];
            handcamRenderer.sprite = handcamAniController.spriteSet 
                          [handcamAniController.spriteSet.Length - 1];
            break;
        }
    } 
}

单击保存,然后返回到Unity

这是整个教程中需要编写的最多代码! 其中很多是调用已经为您定义的东西。

首先,您声明了一些变量,这是对您在场景中添加的BuoyancyEffector2D组件的引用以及一些计时器。

当球进入Float Area时,您将调用OnTriggerEnter。 您启动计时器,启动一些声音和动画效果,并向玩家奖励一些积分。 然后启动BeginFloat协程。

BeginFloat中,您可以跟踪球在Float Area中的停留时间,并运行一些精灵动画。

时间到时,您将重置所有计时器,停止所有动画和声音效果,并将BuoyancyEffector2D.density减小为0。这将导致球掉落到Float Area中并重新进入比赛!

2. Implementing the Float Area

转到Assets / RW / Prefabs,然后将floatEffects拖动到层次结构中的Float Piece Area对象中,以创建一个子实例。 单击floatEffects旁边的箭头图标以展开内容。

在层次结构中选择Float Area。 单击Add Component,然后选择Scripts ▸ Floatpiece。 在检查器中,将floatEffects分配给Handcam Obj,将StaticLight分配给Golight Obj。 将Floating Time值设置为2

点击Play进行测试:


Triangle Bumpers

弹球游戏几乎完成了! 剩下的就是使用point effectorsphysics material来增强游戏性。

为此,您需要在游戏中添加bumpers。 如果球碰到这些bumpers中的任何一个,它将朝相反的方向射击。

要创建这些bumpers,请转至Assets / RW / Prefabs并将dragerTriangleLeft拖动到层次结构的Bumpy Parts中。 将球ball实例放在bumpers的前面。

单击Play以查看球如何从斜坡上滚下来。

Physics Material 2D Versus Point Effector 2D - 物理材料2D与点效应器2D

在Unity中,要在碰撞时为动画对象添加动量,您有两个选择:

Physics Material 2D:在整个对象表面上,速度始终保持一致,而不管碰撞点如何。

Point Effector 2D:速度取决于对象的质心及其碰撞点。

随意使用两个选项。 使用不同的设置进行实验,以找到游戏中不同碰撞元素的最佳效果。

在“层次结构”中选择bumperTriangleLeft。 在检查器中找到Polygon Collider 2D,并启用Is TriggerUsed By Effector

接下来,单击Add Component,然后选择Physics 2D ▸ Point Effector 2D。 将Force Magnitude设置为500,并将Damping设置调整为Drag: 5000Angular Drag: 1000

现在,将bumperTriangleRightAssets / RW / Prefabs拖动到Bumpy Parts中。 将其设置与左bumpers完全相同。

然后将球实例的Transform Position设置为(X:-1.6,Y:-1.6,Z:0)。 单击Play以测试新的bumpers

看! 球太快了,看不到它。

1. Adding More Bumpers

您可以尝试另外两种预制件,以探索更多的2D物理引擎:bumperCirclesbumperDividers。 要将它们添加到您的弹球游戏中,请将它们拖到HierachyBumpy Parts中。

入门项目已经为您设置了这些。 但是,您可以使用Point Effectors 2DPhysics Material 2D调整碰撞的影响。

最后,将ball实例的位置设置为(X:2.8,Y:-1,Z:0)

单击Play,然后享受“弹指一击”的乐趣!

要扩展此游戏,您可以构建菜单系统并将玩家限制在只有三个球才能获得高分。 或者,您可以将其与Facebook挂钩并设置高分表来挑战您的朋友。

后记

本篇主要讲述了基于Unity 2DPinball游戏的简单实现,感兴趣的给个赞或者关注~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271