Puerts for Unity 加载独立.js
文件
在上一节中,完成了 Puerts 的基本接入,但是 JavaScrip (后称为 Js)代码还是以字符串的形式存在 c# 代码之中。
在实际项目中,肯定不能是这样。所有的 Js 一定都是以独立文件的形式存在。
所以,需要通过自定义 Puerts Loader 告诉 Puerts 该从磁盘什么位置加载 Js 文件。
创建入口 Js 代码文件
先将上一节的 Js 代码字符复制出来并创建为 main.js
,并保存到 Assets/StreamingAssets/Scripts/
目录中(下一节中,Ts 编译输出目录也将指向此地)。
// Assets/StreamingAssets/Scripts/main.js 文件内容
const CS = require('csharp');
let gameObject = new CS.UnityEngine.GameObject('test');
CS.UnityEngine.Debug.Log(gameObject.name);
为什么要保存在此目录?
StreamingAssets
是 Unity 规定的 流媒体资源存放目录。
在该目录下的资源不会参与引擎编译,也方便使用 AssetBundle 资源热更新方法进行资源热更。
自定义 Loader
在 Assets/Cs/
创建 Loader.cs
的 c# 文件,代码如下:
using System.IO;
using UnityEngine;
using Puerts;
public class Loader : ILoader{
// 限制 debugRoot 属性外部只可访问,不可设置
public string debugRoot {get; private set;}
/// <summary>
/// 获取 Puerts 自带模块路径
/// </summary>
/// <param name="filePath">Puerts 自带模块名称</param>
/// <returns>模块完整路径</returns>
private string GetPuertsModulePath(string filePath) {
return PathUnified(Application.dataPath,"Puerts/Src/Resources/",filePath) + ".txt";
}
/// <summary>
/// 判断模块是否为 Puerts自带模块
/// </summary>
/// <param name="filePath">模块名称</param>
/// <returns>true/false</returns>
private bool IsPuertsModule(string filePath){
return filePath.StartsWith("puerts/");
}
/// <summary>
/// 构造方法
/// </summary>
/// <param name="debugRoot">Js 脚本存放目录</param>
public Loader(string debugRoot){
this.debugRoot = debugRoot;
}
/// <summary>
/// * 接口要求实现
/// 判断文件是否存在
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>true/false</returns>
public bool FileExists(string filePath){
// Puerts 需要调用到其目录下的一些 js 文件,这里通通判为存在
if (IsPuertsModule(filePath)) return true;
#if UNITY_EDITOR
return File.Exists(PathUnified(debugRoot, filePath));
#else
return true;
#endif
}
/// <summary>
/// * 接口要求实现
/// 文件内容读取
/// </summary>
/// <param name="filePath">模块路径</param>
/// <param name="debugPath">文件完整路径</param>
/// <returns>文本内容</returns>
public string ReadFile(string filePath,out string debugPath){
bool isPuerts = IsPuertsModule(filePath);
debugPath = isPuerts ? GetPuertsModulePath(filePath) : PathUnified(debugRoot, filePath);
// Puerts 本身调用的 Js 存放在 Resource 目录下,所以可以直接用 Resources.Load 获取
return isPuerts ? Resources.Load<TextAsset>(filePath).text : File.ReadAllText(debugPath);
}
/// <summary>
/// 纠正路径(Windows下路径斜杠不正确的问题)
/// </summary>
/// <param name="args"></param>
/// <returns>纠正之后的路径</returns>
private string PathUnified(params string[] args){
return Path.Combine(args).Replace("\\","/");
}
}
调整入口文件
现在需要对 Assets/Cs/Main.cs
进行些许改造,增加调试开关、调试通信端口号,再把定义好的 Loader 传进去并调用 js 入口文件。
最终代码如下:
using UnityEngine;
using Puerts; // 引用 Puerts
using System.IO;
class Main : MonoBehaviour{
public bool isDebug = false; // 是否开启调试
public int debugPort = 43990; // 调试端口号
public JsEnv jsEnv; // 定义 jsEnv
private Loader loader;
private string scriptsDir = Path.Combine(Application.streamingAssetsPath,"Scripts");
void Start(){
loader = new Loader(scriptsDir);
jsEnv = new JsEnv(loader,debugPort); // 实例化 js 虚拟机
if(isDebug){ // 启用调试
jsEnv.WaitDebugger();
}
jsEnv.Eval("require('main')");
}
void Update(){
jsEnv.Tick();
}
}
最后,回到游戏场景中再次运行游戏。看 Js 文件应该有被正确执行。