使用Unity 5和JavaScript创建WebGL游戏

Nilson Jacques CollinsMarc TowlerMatt Burnett对本文进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

Unity是跨平台的游戏引擎,用于为PC,控制台,移动设备和网站开发视频游戏。 WebGL导出器随附了最新版本(Unity 5) 这意味着开发人员可以轻松地将其游戏发布到Web上。 顾名思义,WebGL导出器利用了WebGL (一种用于渲染交互式3D计算机图形的JavaScript API)和asm.js (一种由Mozilla开发的JavaScript子集),被吹捧为“ Web汇编语言”。 您可以在此处阅读有关Unity和Unreal Engine的Asm.js和WebGL的更多信息。

在本教程中,我将向您展示如何启动和运行Unity。 我还将向您展示如何使用JavaScript在Unity中创建简单的游戏以及如何将游戏导出到网络。

您可以在此处签出完成的游戏 (您需要使用支持WebGL的桌面浏览器),也可以从我们的GitHub存储库下载游戏文件和项目文件。

因此,让我们开始吧……

关于Unity中JavaScript的一句话

当我们谈论Unity中的JavaScript时,我们实际上是在谈论UnityScript,这是一种类型化的JS方言。 Unity本身经常引用这种JavaScript ,但是更多的愤世嫉俗的观察者认为“ Unity会使用JavaScript”是一种营销策略 。 无论哪种方式,我们都应该清楚UnityScript不符合任何ECMAScript规范的事实,也不会这样做。 您可以在此处找到有关差异很好概述

安装Unity

要开始本教程,我们需要有一个正在运行的Unity版本,可以在此处下载 。 Unity拥有适用于Windows和Mac OS X的安装程序。Linux用户可能可以通过Wine运行Unity ,但是您的工作量可能会有所不同。

Unity的默认安装对话框

安装完成后,我们一切顺利! 因此,让我们打开Unity并创建一个新的3D项目。

通过项目创建对话框,我们可以设置项目名称并更改保存项目的路径。

项目设置

Unity首次打开后,我们应该花一点时间在主窗口中找到方法:

Unity的默认编辑器视图

  1. 最左侧的面板是Hierarchy ,它概述了当前场景中的所有元素。 场景类似于游戏视图,例如关卡或菜单。 此刻应该有一个Main Camera元素和一个Directional Light元素。
  2. 中间是“ 场景”视图,通过图标说明3D空间中的相机和灯光。
  3. 场景”选项卡旁边有一个“ 游戏”选项卡,显示了游戏本身,就像玩家会看到的一样。 用于在编辑器中测试游戏。
  4. 右侧是“ 检查器”面板,可以在其中修改元素设置。 让我们通过在“ 层次结构”中单击“ 定向光”来进行尝试。 现在,我们应该可以看到有关此灯的大量信息,并能够使用“ 阴影类型:无阴影”来关闭其阴影。
  5. 在底部的“ 项目”窗口显示了我们开发游戏所需文件的视图。

现在我们熟悉Unity的界面,在开始开发之前,还有一件事情要做:保存当前场景。 “文件”>“保存场景”将打开一个“ 保存场景”对话框,该对话框会指向名为Assets的文件夹。 在Unity中组织文件的一种常用方法是使用子文件夹。 因此,将一个新文件夹添加到名为ScenesAssets文件夹中,并将场景以Level.unity的名称保存在此文件夹中。

创建英雄

我们的游戏将包括一个英雄,一个平台一个平台跳得更高。 如果它错过了一个并被遗忘了,那么游戏将会失败。 因此,让我们从创建英雄开始。 因为玩家可以从第一人称视角观看游戏,所以英雄的外表并不重要,我们可以使用标准的球体几何形状。 球体的好处在于它可以通过几个步骤创建,并且适合我们跳跃所需的物理原理。 通过单击“ 层次结构”中的“ 创建”来添加球体,并使用检查器编辑以下属性:

Position { X: 0, Y: 2.5, Z: 0 }
Scale { X: 0.3, Y: 0.3, Z: 0.3 }

具有已编辑属性的球体

让我们按一下播放按钮来测试我们所做的事情。 我们应该在天际线前面的3D空间中看到一个球体。

为了使英雄跌倒,必须增加体重。 因此,我们需要通过单击“ 检查器”中的相应按钮并选择“ 刚体”将组件添加到球体中。 并且由于我们不希望英雄旋转,因此我们通过打开“ 约束”并选择“ 旋转”行中的所有轴将其冻结在“ Rigidbody组件中。 再次播放场景时,我们应该能够看到英雄掉落。

添加刚体组件

为了使英雄免于无休止的跌倒,我们将创建一个用作平台的扁平盒子。 为此,我们必须添加一个多维数据集并将Scale.Y值设置为0.1 。 重播场景可以确认英雄可以安全地降落在平台上,尽管我必须承认这看起来并不自然。 那么我们如何让英雄弹跳呢? 通过添加一些物理材料。

使英雄弹跳

首先,我们需要为该球体创建新的物理材料以使其具有弹性。 为此,在Assets文件夹中创建一个名为Materials的新文件夹,然后在此处创建一个新的物理材料。 我们称其为Bouncy_Sphere 。 我们需要在检查器中调整的值为:

Dynamic Friction: 10
Static Friction: 10
Bounciness: 1
Friction Combine: Maximum
Bounce Combine: Maximum

如果我们将此材料添加到“ 球体对撞器”中 ,这将使球体上下反弹,但始终达到相等的高度。 为了使球体每次跳动都跳得越来越高,我们也必须在平台上添加一些物理材料。 为此,我们创建了另一个名为Bouncy_Platform ,并将其值更改为:

Dynamic Friction: 0.9
Static Friction: 0.9
Bounciness: 1
Friction Combine: Average
Bounce Combine: Multiply

为了达到此处的一致性,我们还应该通过在Hierarchy中两次将多维数据集元素重命名为Platform 。 现在开始游戏时,我们会注意到球体每次跳得越来越高。

我们还将创建一种称为“ Platform的新标准材料,为Platform提供一些颜色。 创建此材质后,使用#C8FF00作为Albedo颜色( Albedo是Unity UI中的标签),然后将该材质拖放到平台元素上。 现在应该是黄色。

添加第一人称视角

要添加第一人称视角,我们将摄像机(在Hierarchy中 )拖放到球体上。 这将使摄影机成为英雄的子元素,并使摄影机跟随球体移动。 相机属性也必须调整为:

Position { X: 0, Y: 1, Z: 0 }
Rotation { X: 90, Y: 0, Z: 0 }
Scale { X: 2.5, Y: 2.5, Z: 2.5 }
Clear Flags: Solid Color
Background: #000
Field of View: 80.3

我们还将创建一个聚光灯作为球的第二个子对象。 这将使玩家对英雄当前的跳跃高度有所了解。 将Spotlight的值调整为:

Rotation { X:90, Y:0, Z:0 }

编程控制器

我们的目标是使用鼠标或触控板允许玩家向特定方向移动。 为此,我们将编写第一个脚本。 与Rigidbody一样 ,脚本也作为组件添加到游戏元素中。 在本例中,我们将向相机添加一个名为InputController的JavaScript脚本。 另外,与场景和两种材质一样,我们应该在“ 项目”面板中创建一个名为“ Scripts的新文件夹。 这应该包含脚本。 通过双击新脚本,Unity将在默认编辑器MonoDevelop中将其打开。 默认编辑器可以更改为任何编辑器( Unity>首选项>外部工具 ),但这并不重要。

如您所见,脚本已经包含一些代码。 首先,我们必须在第1行#pragma strict (在Unity上下文中强制键入)之后创建一些变量。

#pragma strict

public var Hero : GameObject;
private var halfScreenWidth : float;
private var  halfScreenHeight : float;

function Start () {}

function Update () {}

第一个变量是public,类型是GameObject ; 它必须参考球体。 在仍然选择摄像机的情况下切换回Unity,我们可以在一个带有空值的输入字段旁边看到此公共变量。 让我们将球体拖放到此插槽中,然后为变量分配一个值。

其他两个变量都是私有变量,将在“ 开始”功能中为其分配值。 开始场景后,将调用一次此功能。 这两个私有变量将分别分配当前屏幕宽度和高度的一半,为此,我们使用Unity的内置Screen类:

function Start () {
  halfScreenWidth = Screen.width / 2;
  halfScreenHeight = Screen.height / 2;
}

InputController脚本中,唯一要做的就是只要移动鼠标就从鼠标中获取值。 为此,我们使用Update函数,每一帧都会调用一次:

function Update () {
  var x : float = 0.0;
  var z : float = 0.0;

  x = ( Input.mousePosition.x - halfScreenWidth ) / halfScreenWidth;
  z = ( Input.mousePosition.y - halfScreenHeight ) / halfScreenHeight;

  Hero.GetComponent( HeroController ).SetPosition( x, z );
}

新变量xz代表相应的轴。 当我们向下看y轴时,我们看到一个水平的x轴和一个垂直的z轴。 在这些轴上,我们希望在收到鼠标输入后调整英雄的位置。 为此,我们使用Input.mousePosition ,它返回一个二维向量 。 零值在左下角的向量必须被处理到我们的坐标系中,其原点位于屏幕中间。 这发生在以下几行中。 最后,我们调用一个函数setHeroPosition ,将两个计算值作为参数。 我们将在连接到球体的名为HeroController的新脚本中编写此函数:

#pragma strict

public function SetPosition ( x : float, z : float ) {
  transform.position.x = x;
  transform.position.z = z;
}

让我们通过移动鼠标或触控板并让英雄从平台掉下来测试我们的代码。

逐步创建平台

为了自动创建平台,我们需要某种平台模板。 这在Unity中称为“预制件”。 要创建预制件,我们必须将平台从Hierarchy中拖放到新的assets文件夹中(与我们的命名约定一致),称为Prefabs预制件可能会在其层次结构中通过蓝色识别。 所有平台(第一个平台除外)将通过一个称为GameManager的新脚本创建,该脚本已附加到相机上。 我们通过引用必要的变量来启动此脚本:

#pragma strict

public var Platform : GameObject;
public var Hero : GameObject;

private var boundary : float;
private var rotation: Quaternion;
private var lastPlatformPosition : Vector3;

function Start () {
  boundary = 1.0;
  rotation = Quaternion.identity;
  lastPlatformPosition = new Vector3( 0, 0, 0 );
}

function Update () {}

我们需要引用预制面板和球体,因此必须将它们拖放到编辑器中的特定插槽中。 我们还将创建三个私有变量,这些私有变量将用于实例化预制面板:

  1. 边界标记了y轴的极限。 每当英雄跳到高于此高度时,都必须创建一个新面板。
  2. 第二个变量是实例化预制件所需的旋转。 Quaternion.identity根本不会旋转 ,这正是我们所需要的。
  3. 变量lastPlatformPosition将最后一个平台的位置保存为三维向量

现在,对于每一帧,我们将检查球体是否在边界上方。 如果是,我们将提高边界并实例化一个新面板:

function Update () {
  if ( Hero.transform.position.y > boundary ) {
    var position : Vector3;

    boundary += 1.0;
    position = getNextPlatformPosition();
    Instantiate( Platform, position, rotation );
  }
}

接下来,我们可以添加代码以获取下一个面板位置。 我们将其放置在一个额外的函数中,以保持可读性:

private function getNextPlatformPosition () {
  var position : Vector3;

  do {
    position = new Vector3( Random.Range( -1, 2 ), boundary, Random.Range( -1, 2 ) );
  } while ( position.x == lastPlatformPosition && position.z == lastPlatformPosition );

  lastPlatformPosition = position;

  return position;
}

为了确保位置向量的新xz值与先前的值不同,我们使用do while循环。 Unity的Random.Range函数是获取xz值的随机值的正确方法。 在这两种情况下,我们都希望它们在-1和2之间。最后,将新位置保存为面板的最后位置,然后将其返回。

添加游戏菜单

在这种状态下,玩家可以通过在相应方向上移动鼠标来在平台上跳得更高。 但是,如果玩家摔倒并错过所有的平台,球体将无限下落。 这就是我们现在要解决的问题。 我们将检查球体是否跌落到第一个平台以下,并在这种情况下加载新场景。

首先,让我们检查英雄是否低于某个特定点。 为此,让我们在GameManager脚本的update功能中编辑if语句。 else if语句将检查球体的y位置是否低于-2.0单位。 在这种情况下,我们将调用私有函数gameOver

function Update () {
  if ( Hero.transform.position.y > boundary ) {
    var position : Vector3;

    boundary += 1.0;
    position = getNextPlatformPosition();
    Instantiate( Platform, position, rotation );
  } else if (Hero.transform.position.y < -2.0) {
    gameOver();
  }
}

我们将使用一个新函数来处理游戏结束状态,如下所示:

private function gameOver () {
  Application.LoadLevel( 'Menu' );
}

在这里,我们使用Unity的Application类该类使我们能够访问LoadLevel方法,可用来加载名为Menu的新场景。 为了使此代码起作用,我们首先必须通过“ 文件”>“新场景”创建场景 ,然后将其保存为名称Menu 。 之后,我们需要将两个场景都添加到构建过程中。 可以通过“ 文件”>“构建设置”打开构建设置 。 菜单场景仍应处于打开状态,因此让我们单击“ 添加当前”按钮,以将场景添加到构建设置中。 在关卡场景打开的情况下重复此操作。 现在,当我们完成游戏时,我们应该进入新创建的游戏菜单场景。

添加一个按钮开始游戏

为了使游戏具有可玩性,我们需要创建一个带有播放按钮的游戏菜单。 让我们切换到游戏菜单场景,然后首先将检查器中的相机设置调整为:

Clear Flags: Solid Color
Background: #000
Width: 200
Height: 60

要添加按钮,我们使用Unity的UI元素,可以通过Hierarchy像3D元素一样添加它。 添加UI按钮后,我们应该在“ 层次结构”中看到以下新元素:

  • EventSystem元素和
  • 具有以下内容的Canvas元素
  • 一个子Button元素,以及
  • 其子Text元素。

画布是所有UI元素的容器,并且可以使其具有响应性。 为此,我们必须将Inspector中的Canvas Scaler:UI Scale Mode设置从“ 恒定像素大小”更改为“ 随屏幕大小缩放” 。 现在我们可以更改按钮的位置:

Rect Transform { Pos X: 0, Pos Y: 0, Pos Z: 0 }
Rect Transform { Width: 200, Height: 60 }

删除按钮的源图像并将颜色设置为#C8FF00将使菜单更#C8FF00 。 最后,我们通过将Text元素的文本编辑为“ PLAY PREJUMP”并将字体大小设置为16来更改文本。为了使按钮起作用,我们将使用一个新函数,该函数将添加到Button上的新UIController脚本中。元件。 它包含一个用于加载关卡场景的功能:

public function StartGame () {
  Application.LoadLevel( 'Level' );
}

我们可以在按钮的检查器设置中应用此功能。 在“ Button (Script)组件设置中,只要玩家单击它,我们就可以执行一个功能。 为此,我们通过单击+图标将新功能添加到On Click ()事件中。 现在我们可以将按钮本身拖放到输入字段上。 然后,选择刚刚从UIController脚本( UIController.StartGame )中编写的函数。

最终比赛

作为WebGL浏览器游戏发布项目

Unity能够将项目导出为WebGL应用程序。 打开构建设置后,我们选择WebGL作为平台。 然后,我们通过单击“ 切换平台”按钮来切换导出目标。 然后,我们只需要单击Build按钮并为我们的游戏选择一个名称。 构建过程完成后,我们可以使用支持WebGL的桌面浏览器打开html文件。

在“构建设置”中将平台切换到WebGL

我们从这里去哪里?

当然,可以通过例如得分,更多平台类型,其他输入方法,音频等来改进此小游戏。 但是我们在本教程中看到的是,跨平台游戏引擎Unity提供了所见即所得编辑器和脚本编制功能的组合,我们可以将其与JavaScript类似的语言一起使用。 根据我们特定的项目要求,Unity可能是WebGL框架的不错替代品。

您在项目中使用Unity吗? 您是否曾使用Unity制作过想要分享的炫酷游戏? 在下面的评论中让我知道。

From: https://www.sitepoint.com/creating-webgl-game-unity-5-javascript/

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Webgl中,可以使用JS和Unity之间的通信来实现两者之间的交互。以下是一些实现方法: 1. 使用UnityWebGL桥接器 Unity提供了一个WebGL桥接器,可以使用JavaScript API与Unity进行通信。可以使用UnityObject2.js文件将Unity嵌入到HTML页面中,并在JavaScript代码中使用UnityObject2.getObjectById()方法获取Unity对象。 例如,以下代码创建了一个Unity对象,然后调用其中的一个方法: ``` <div id="unityContainer" style="width: 960px; height: 600px"></div> <script src="UnityObject2.js"></script> <script> var unityObject = UnityObject2.createObject("unityContainer", "MyUnityFile.unity3d", { onProgress: UnityProgress }); function callUnityMethod() { var unity = unityObject.getObjectById("unityPlayer"); unity.SendMessage("MyGameObject", "MyMethod", "Hello Unity!"); } </script> ``` 这将调用名为"MyMethod"的方法,其参数为"Hello Unity!",其中"MyGameObject"是Unity场景中的游戏对象名称。 2. 使用JavaScript插件与Unity通信 除了Unity提供的WebGL桥接器之外,还可以使用第三方JavaScript插件(如jQuery)与Unity进行通信。可以使用Unity的ExternalCall方法从JavaScript代码中调用Unity方法,并使用Unity的Application.ExternalCall方法从Unity中调用JavaScript方法。 例如,以下代码使用jQuery从JavaScript调用Unity方法: ``` <script src="jquery.js"></script> <script> function callUnityMethod() { $.get("MyUnityFile.unity3d", function() { var unity = $("#unityPlayer")[0]; unity.SendMessage("MyGameObject", "MyMethod", "Hello Unity!"); }); } </script> ``` 3. 使用WebGL插件与Unity通信 另一种方法是使用WebGL插件(如emscripten)来将C++代码编译为JavaScript,并与Unity进行通信。可以使用Unity的Runtime.JS()方法从JavaScript代码中调用Unity方法,并使用WebGL插件中的EXPORT函数从Unity中调用JavaScript方法。 例如,以下代码使用emscripten将C++代码编译为JavaScript,并与Unity进行通信: ``` <script src="MyPlugin.js"></script> <script> function callUnityMethod() { var unity = UnityLoader.instantiate("unityContainer", "MyUnityFile.unity3d"); unity.callFunction("MyPlugin", "MyMethod", "Hello Unity!"); } </script> ``` 这将调用名为"MyMethod"的方法,其参数为"Hello Unity!",其中"MyPlugin"是WebGL插件中的函数名称。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值