2DPlatformer 是 Unity3D 的一个官方 Demo。本文将介绍使用 JSBinging + SharpKit 转换 2DPlatformer 的过程。
本文并不详细介绍每个步骤的细节。因为他们将在其他文章里做详细介绍。
准备工作:首先准备好 JSBinding 的工程,正确导入 JSBinding 插件。
2DPlatformer 是Unity3D的第一个示例代码,一共不到10M。麻雀虽小,五脏俱全。牵扯到很多东西,比如 prefab 的使用,结构体序列化,场景切换,音乐等等。
我们的目标是:在已有的工程中,不添加/更新任何C#代码,不用JS重写任何C#代码,花费最少的时间把整个 2DPlatformer 游戏添加进去。
分析:
下载:
Unity官方原版 2DPlatformer:https://www.assetstore.unity3d.com/en/#!/content/11228
可用于本实战的版本(有稍微修改,去除Coroutine等,改动很少,您可以和原版比较一下):http://pan.baidu.com/s/1eQEkIH0
已经转换完成的Windows可执行版本(注意:可以使用Firefox进行调试):http://pan.baidu.com/s/1sj2sXNf
以下是具体步骤:
1. 将 2DPlatformer 导入到工程中,并确定C#版本能够正确运行
放在哪里都可以,为了方便,直接放在 Assets/ 目录下。如图。
放完后一定要确保能够正常运行,因为有些项目包含 Project Settings ,如果没有正确导入,C#版本本身就会出错。
2. 生成JS绑定
点击菜单:[JSB/Generate JS and CS Bindings]
(如果 Unity 版本没改,类的列表也没有变化,此步骤如已执行过不需要再执行)
3. 正确配置 JSBindingSettings 里的各个导出路径设置
需要配置以下几个参数,路径都是相对于 Assets 文件夹:
PathsNotToJavaScript:简称为A,是指哪些路径不要转换成JS。比如说类库,或者 JSBinding 本身。
PathsToJavaScript:简称为B,是指那些在A中路径下的,但是又要导出的。
有点乱,详细解释一下。A和B是用于配置哪些路径要保留C#,哪些路径下的C#要转换成JS。
通常来说,基础框架代码是不需要转换成JS的,而且是相对固定的,比较少会进行改动。所以把这些路径配置到A数组。
这样就表示,除了A以外的其他路径里的C#类,都将被标记 [JsType(...)]标签,之后将被 SharpKit 编译生成JS代码。
而B是啥呢?B只是用于对A做一些例外,就是属于A数组,但是又要被转换成JS的。比如说,JSBinding/ 因为是插件源代码,肯定不转换成JS,所以 JSBinding/ 会配置在A数组里。
但是我们在 JSBinding/Samples 里放了一些示例代码,我希望他们被编译成JS,所以我就把 JSBinding/Samples 配置在B里,表示要转换。
PathsNotToCheckOrReplace:简称C。
跟A和B类似,但是用于说明 prefab 的处理。对于脚本,我们是将其编译成JS,才可以进行更新。对于 prefab,因为 prefab 上绑定了脚本,那么必须要解除这个绑定关系才可以。
解除的方法是将脚本都替换成 JSComponent,这里不详细解释。C这个数组用于说明,不要对哪些路径下的 prefab 进行处理。比如说 "JSBinding/Prefabs/_JSEngine.prefab" 是不需要处理的。
NGUI/ 路径下的 prefab 也不需要处理,因为这些 prefab 不会绑定要被导成JS的C#脚本。
1 /* 2 * Formula: 3 * All C# scripts - PathsNotToJavaScript + PathsToJavaScript = C# scripts to export to javascript 4 * see JSAnalyzer.MakeJsTypeAttributeInSrc for more information 5 */ 6 public static string[] PathsNotToJavaScript = new string[] 7 { 8 "JSBinding/", 9 "Stealth/", 10 "DaikonForge Tween (Pro)/", 11 "NGUI/", 12 }; 13 public static string[] PathsToJavaScript = new string[] 14 { 15 "JSBinding/Samples/", 16 "DaikonForge Tween (Pro)/Examples/Scripts", 17 }; 18 /// <summary> 19 /// By default, menu 20 /// 21 /// JSB | Check All Monos for all Prefabs and Scenes 22 /// JSB | Replace All Monos for all Prefabs and Scenes 23 /// 24 /// handles all Prefabs and Scenes in whole project 25 /// add paths(directory or file name) to this array if you want to skip them 26 /// </summary> 27 public static string[] PathsNotToCheckOrReplace = new string[] 28 { 29 "JSBinding/", 30 "JSBinding/Prefabs/_JSEngine.prefab", 31 "Plugins/", 32 "Resources/", 33 "Src/", 34 "StreamingAssets/", 35 "UnityVS/", 36 "DaikonForge Tween (Pro)/", 37 "NGUI/", 38 };
4. 往2DPlatformer 的所有 C# 源代码中的类和结构体添加 [JsType()] 标记。
上一个步骤已经配置好了,这一步只要运行菜单即可。
运行菜单:[JSB/Tool/Add JsType Attribute for all structs and classes]
// 原来的代码
1 using UnityEngine; 2 using System.Collections; 3 4 public class Gun : MonoBehaviour 5 { 6 public GameObject rocketGO; // Prefab of the rocket. 7 public float speed = 20f; // The speed the rocket will fire at.
// 执行菜单后(生成了 [JsType()] 标记):
1 using UnityEngine; 2 using System.Collections; 3 4 using SharpKit.JavaScript; 5 [JsType(JsMode.Clr,"../../StreamingAssets/JavaScript/SharpKitGenerated/2DPlatformer/Scripts/Gun.javascript")] 6 public class Gun : MonoBehaviour 7 { 8 public GameObject rocketGO; // Prefab of the rocket. 9 public float speed = 20f; // The speed the rocket will fire at.
5. 用 SharpKit 生成 JS 代码
SharpKit工程的编译的时候,会自动识别带有 JsType 标记的类和结构体,将其所有代码全部编译成 JS 代码并输出。输出的路径在 JsType 属性中已经指定。
编译SharpKit工程:
编译完成后 将在 StreamingAssets/JavaScript/SharpKitGenerated/2DPlatformer/ 文件夹下生成所有JS代码。
SharpKitGenerated 文件夹下的结构和原来的结构是一样的。
6. 生成一个 js 文件,里面对 SharpKit 生成的文件进行了 require。
执行菜单:[JSB/Tool/Gen JsType file list]
这一步生成了文件:StreamingAssets/JavaScript/SharpKitGeneratedFiles.javascript
1 /* Generated by JSBinding. 2 * see JSAnalyzer.cs / OutputAllTypesWithJsTypeAttribute() function 3 * better not modify manually. 4 */ 5 6 CS.require("SharpKitGenerated/2DPlatformer/Scripts/BackgroundParallax.javascript"); 7 CS.require("SharpKitGenerated/2DPlatformer/Scripts/BackgroundPropSpawner.javascript"); 8 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Bomb.javascript"); 9 CS.require("SharpKitGenerated/2DPlatformer/Scripts/BombPickup.javascript"); 10 CS.require("SharpKitGenerated/2DPlatformer/Scripts/CameraFollow.javascript"); 11 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Destroyer.javascript"); 12 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Enemy_Data.javascript"); 13 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Enemy.javascript"); 14 CS.require("SharpKitGenerated/2DPlatformer/Scripts/FollowPlayer.javascript"); 15 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Gun.javascript"); 16 CS.require("SharpKitGenerated/2DPlatformer/Scripts/HealthPickup.javascript"); 17 CS.require("SharpKitGenerated/2DPlatformer/Scripts/LayBombs.javascript"); 18 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Pauser.javascript"); 19 CS.require("SharpKitGenerated/2DPlatformer/Scripts/PickupSpawner.javascript"); 20 CS.require("SharpKitGenerated/2DPlatformer/Scripts/PlayerControl.javascript"); 21 CS.require("SharpKitGenerated/2DPlatformer/Scripts/PlayerHealth.javascript"); 22 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Remover.javascript"); 23 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Rocket.javascript"); 24 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Score.javascript"); 25 CS.require("SharpKitGenerated/2DPlatformer/Scripts/ScoreShadow.javascript"); 26 CS.require("SharpKitGenerated/2DPlatformer/Scripts/SetParticleSortingLayer.javascript"); 27 CS.require("SharpKitGenerated/2DPlatformer/Scripts/Spawner.javascript"); 28 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/DebugMessages.javascript"); 29 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/Message.javascript"); 30 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/MuchTweenSoWow.javascript"); 31 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestEasingFunctions.javascript"); 32 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestFPS.javascript"); 33 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestHighConcurrency.javascript"); 34 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestHighConcurrencyGroup.javascript"); 35 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestShakeObject.javascript"); 36 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestSlinky.javascript"); 37 CS.require("SharpKitGenerated/DaikonForge Tween (Pro)/Examples/Scripts/TestSplineTween.javascript"); 38 CS.require("SharpKitGenerated/JSBinding/Samples/PerformanceTest1.javascript"); 39 CS.require("SharpKitGenerated/JSBinding/Samples/Serialization/SerializeSimple.javascript"); 40 CS.require("SharpKitGenerated/JSBinding/Samples/Serialization/SerializeStruct.javascript"); 41 CS.require("SharpKitGenerated/JSBinding/Samples/Serialization/AppleInfo.javascript"); 42 CS.require("SharpKitGenerated/JSBinding/Samples/V3Test.javascript"); 43 CS.require("SharpKitGenerated/Src/testEnable2.javascript"); 44 CS.require("SharpKitGenerated/testEnable.javascript");
7. 解除所有 prefab 及 场景中GameObject 对 C# 源代码的引用
因为我们最终的目的是要删除整个 2DPlatformer/Scripts 文件夹,那么任何 prefab 及 GameObject 显然都不可以引用任何 C# 源代码。
对于 MonoBehaviour 来说,我们的做法是将其替换成固定的类 JSComponent,这个类足够强大,可以支持绝大部分继承于 MonoBehaviour 的类,最主要的是支持序列化。
对于其他类或结构体,他们都将被转换为 JS 代码,GameObject 不会引用到。
在真正的项目中使用时,最好先备份,再执行这个菜单。
执行菜单:[JSB/Replace all monos for prefabs and scenes]
Replace.txt 示例。显示了所有将要被处理的 prefab 及 scene。刚好包含了所有 2DPlatformer 的所有东西。确定好了就点OK吧!让奇迹发生~
1 2DPlatformer/Prefabs/Characters/enemy1.prefab 2 2DPlatformer/Prefabs/Characters/enemy2.prefab 3 2DPlatformer/Prefabs/Characters/hero.prefab 4 2DPlatformer/Prefabs/Environment/backgroundAnimation.prefab 5 2DPlatformer/Prefabs/Environment/backgrounds.prefab 6 2DPlatformer/Prefabs/Environment/Bus.prefab 7 2DPlatformer/Prefabs/Environment/Cab.prefab 8 2DPlatformer/Prefabs/Environment/env_clouds.prefab 9 2DPlatformer/Prefabs/Environment/env_fog.prefab 10 2DPlatformer/Prefabs/Environment/env_riverMid.prefab 11 2DPlatformer/Prefabs/Environment/env_riverTop.prefab 12 2DPlatformer/Prefabs/Environment/Foregrounds.prefab 13 2DPlatformer/Prefabs/FX/part_splash.prefab 14 2DPlatformer/Prefabs/FX/part_warp.prefab 15 2DPlatformer/Prefabs/FX/splash.prefab 16 2DPlatformer/Prefabs/killTrigger.prefab 17 2DPlatformer/Prefabs/mainCamera.prefab 18 2DPlatformer/Prefabs/pickupManager.prefab 19 2DPlatformer/Prefabs/platformEnd.prefab 20 2DPlatformer/Prefabs/Props/bomb.prefab 21 2DPlatformer/Prefabs/Props/bombCrate.prefab 22 2DPlatformer/Prefabs/Props/explosionCircle.prefab 23 2DPlatformer/Prefabs/Props/explosionParticle.prefab 24 2DPlatformer/Prefabs/Props/healthCrate.prefab 25 2DPlatformer/Prefabs/Props/rocket.prefab 26 2DPlatformer/Prefabs/Props/rocketExplosion.prefab 27 2DPlatformer/Prefabs/Props/swan.prefab 28 2DPlatformer/Prefabs/spawner.prefab 29 2DPlatformer/Prefabs/UI/ui_100points.prefab 30 2DPlatformer/Prefabs/UI/ui_bombHUD.prefab 31 2DPlatformer/Prefabs/UI/ui_healthDisplay.prefab 32 2DPlatformer/Scenes/Level.unity
菜单执行前:
执行菜单后:
添加一个 JSEngine.prefab 到场景中
场景是:2DPlatformer/Scenes/Level.unity
运行!
删除 2DPlatformer/Scripts/ 文件夹!
Windows版本可执行程序截图: