unity-webgl

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

unity-webgl - npm Package Compare versions

Comparing version
3.5.6
to
4.0.0

@@ -1,7 +0,52 @@

type CanvasElement = HTMLCanvasElement | string;
type BooleanLike = 0 | 1;
interface EventListener {
(...args: any[]): void;
_?: EventListener;
}
type EventListenerOptions = {
once?: boolean;
};
declare class UnityWebglEvent {
private _e;
constructor();
/**
* Register event listener
* @param name event name
* @param listener event listener
* @param options event listener options
*/
on(name: string, listener: EventListener, options?: EventListenerOptions): this;
/**
* Remove event listener
* @param name event name
* @param listener event listener
*/
off(name: string, listener?: EventListener): this;
/**
* Dispatch event
* @param name event name
* @param args event args
*/
emit(name: string, ...args: any[]): this;
/**
* clear all event listeners
*/
protected clear(): void;
/**
* Register event listener for unity client
* @param name event name
* @param listener event listener
*/
addUnityListener(name: string, listener: EventListener, options?: EventListenerOptions): this;
/**
* Remove event listener from unity client
* @param name event name
* @param listener event listener
*/
removeUnityListener(name: string, listener?: EventListener): this;
}
/**
* UnityWebgl configuration
*/
type IUnityConfig = Pick<IUnityArguments, 'dataUrl' | 'frameworkUrl' | 'codeUrl' | 'streamingAssetsUrl' | 'memoryUrl' | 'symbolsUrl' | 'companyName' | 'productName' | 'productVersion' | 'devicePixelRatio' | 'matchWebGLToCanvasSize' | 'webglContextAttributes'> & {
type UnityConfig = Pick<UnityArguments, 'dataUrl' | 'frameworkUrl' | 'codeUrl' | 'streamingAssetsUrl' | 'memoryUrl' | 'symbolsUrl' | 'companyName' | 'productName' | 'productVersion' | 'devicePixelRatio' | 'matchWebGLToCanvasSize' | 'webglContextAttributes'> & {
/**

@@ -18,3 +63,3 @@ * The url to the build json file generated by Unity. When using a relative url,

*/
interface IUnityArguments {
interface UnityArguments {
/**

@@ -130,60 +175,3 @@ * The url to the build data file generated by Unity. When using a relative url,

}
type UnityModule = {
/**
* Stringifies a pointer to a string.
* @param pointer The pointer to the string.
* @param length The length of the string.
* @deprecated Deprecated in Unity 2021.2, use UTF8ToString instead.
*/
Pointer_stringify(pointer: number, length: number): string;
/**
* Converts a pointer to a string.
* @param pointer The pointer to the string.
*/
UTF8ToString(pointer: number): string;
/**
* Enables or disabled the fullscreen mode of the UnityInstance.
* @param fullScreen sets the fullscreen mode.
*/
SetFullscreen(fullScreen: BooleanLike): void;
/**
* A reference to the Unity Instance's Canvas.
*/
canvas?: HTMLCanvasElement;
};
/**
* Type declaration for the UnityInstance.
*/
declare class UnityInstance {
/**
* Creates a new instance of Unity Instance.
*/
constructor();
/**
* Sends a message to the UnityInstance to invoke a public method.
* @public
* @param objectName the name of the game object in your Unity scene.
* @param methodName the name of the public method on the game object.
* @param parameter an optional parameter to pass along to the method.
*/
SendMessage(objectName: string, methodName: string, parameter?: string | number | boolean): void;
/**
* Enables or disabled the fullscreen mode of the UnityInstance.
* @public
* @param fullScreen sets the fullscreen mode.
*/
SetFullscreen(fullScreen: BooleanLike): void;
/**
* Quits the Unity WebGL application
* and removes it from the memory.
* @public
* @returns {Promise<void>} a promise whether the application did quit.
*/
Quit(): Promise<void>;
/**
* The Unity Module.
*/
Module: UnityModule;
}
/**
* WebGLContextAttributes object that contains the actual context parameters.

@@ -272,59 +260,88 @@ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes

};
type EventName = string | symbol;
type EventHandler = (...args: any[]) => any;
type EventMap = Record<EventName, EventHandler>;
declare class EventBus {
private _eventMap;
constructor(_eventMap?: EventMap);
on(name: EventName, handler: EventHandler): this;
off(name: EventName): this;
once(name: EventName, handler: EventHandler): this;
emit(name: EventName, ...args: any[]): void;
clear(): void;
}
type UnityBooleanLike = 0 | 1;
type UnityModule = {
/**
* Stringifies a pointer to a string.
* @param pointer The pointer to the string.
* @param length The length of the string.
* @deprecated Deprecated in Unity 2021.2, use UTF8ToString instead.
*/
Pointer_stringify(pointer: number, length: number): string;
/**
* Converts a pointer to a string.
* @param pointer The pointer to the string.
*/
UTF8ToString(pointer: number): string;
/**
* Enables or disabled the fullscreen mode of the UnityInstance.
* @param fullScreen sets the fullscreen mode.
*/
SetFullscreen(fullScreen: UnityBooleanLike): void;
/**
* A reference to the Unity Instance's Canvas.
*/
canvas?: HTMLCanvasElement;
};
/**
* UnityWebgl
* // new UnityWebgl(canvasElement, unityConfig, bridge)
* Type declaration for the UnityInstance.
*/
declare class UnityWebgl extends EventBus {
unityConfig: IUnityConfig;
canvasElement: HTMLCanvasElement | null;
unityLoader: (() => void) | null;
unityInstance: UnityInstance | null;
declare class UnityInstance {
/**
* UnityWebgl constructor
* @param canvas htmlCanvasElement
* @param config configuration
* @param bridge Bridge name, global communication collector.
* Creates a new instance of Unity Instance.
*/
constructor(config: IUnityConfig, bridge?: string);
constructor(canvas: CanvasElement, config: IUnityConfig, bridge?: string);
get bridge(): string;
set bridge(name: string);
constructor();
/**
* 创建 Unity应用实例并渲染至画布
* @param canvas 画布
* @returns
* Sends a message to the UnityInstance to invoke a public method.
* @public
* @param objectName the name of the game object in your Unity scene.
* @param methodName the name of the public method on the game object.
* @param parameter an optional parameter to pass along to the method.
*/
create(canvas: CanvasElement): void;
SendMessage(objectName: string, methodName: string, parameter?: string | number | boolean): void;
/**
* 销毁并重新加载Unity应用
* @param config 配置项
* Enables or disabled the fullscreen mode of the UnityInstance.
* @public
* @param fullScreen sets the fullscreen mode.
*/
reload(config?: IUnityConfig): void;
SetFullscreen(fullScreen: UnityBooleanLike): void;
/**
* Quits the Unity WebGL application
* and removes it from the memory.
* @public
* @returns {Promise<void>} a promise whether the application did quit.
*/
Quit(): Promise<void>;
/**
* The Unity Module.
*/
Module: UnityModule;
}
type CanvasElementOrString = HTMLCanvasElement | string;
declare class UnityWebgl extends UnityWebglEvent {
private _config;
private _unity;
private _loader;
private _canvas;
constructor(canvas: CanvasElementOrString, config: UnityConfig);
constructor(config: UnityConfig);
/**
* Creating Unity Instance
* @param canvas The target html canvas element.
*/
create(canvas: CanvasElementOrString): Promise<void>;
/**
* Sends a message to the UnityInstance to invoke a public method.
* @param {string} objectName Unity scene name.
* @param {string} methodName public method name.
* @param {any} params an optional method parameter.
* @param {any} value an optional method parameter.
* @returns
*/
send(objectName: string, methodName: string, params?: any): this;
sendMessage(objectName: string, methodName: string, value?: any): this;
/**
* Asynchronously ask for the pointer to be locked on current canvas. To track
* the success or failure of the request, it is necessary to listen for the
* pointerlockchange and pointerlockerror events at the Document level.
* @public
* @deprecated Use sendMessage instead.
*/
send(objectName: string, methodName: string, value?: any): this;
/**
* Asynchronously ask for the pointer to be locked on current canvas.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/requestPointerLock

@@ -334,9 +351,8 @@ */

/**
* Takes a screenshot of the canvas and returns a data URL containing image
* data. The image data is in .png format unless otherwise specified.
* @param {string} dataType The image format of the screenshot, ["image/png" | "image/jpeg" | "image/webp"]
* @param {number} quality The quality of the jpg or webp screenshot
* @returns a data URL containing image data of a snapshot of the canvas
* Takes a screenshot of the canvas and returns a base64 encoded string.
* @param {string} dataType Defines the type of screenshot, e.g "image/jpeg"
* @param {number} quality Defines the quality of the screenshot, e.g 0.92
* @returns A base 64 encoded string of the screenshot.
*/
takeScreenshot(dataType?: 'image/png' | 'image/jpeg' | 'image/webp', quality?: number): string | undefined;
takeScreenshot(dataType?: string, quality?: any): string | undefined;
/**

@@ -352,5 +368,3 @@ * Enables or disabled the Fullscreen mode of the Unity Instance.

/**
* Detatches the Unity Instance from the React DOM, by doing so, the Unity
* Instance can be unloaded from the memory while the Unity component can be
* unmounted safely.
* 保障Unity组件可以安全卸载. 在unity实例从内存中销毁之前保障Dom存在.
*

@@ -361,5 +375,5 @@ * Warning! This is a workaround for the fact that the Unity WebGL instances

*/
_unsafe_unload(): Promise<void>;
unsafe_unload(): Promise<void>;
}
export { UnityWebgl as default };
export { type IWebGLContextAttributes, type UnityArguments, type UnityConfig, UnityInstance, UnityWebgl as default };
/*!
* unity-webgl.js v3.5.6
* (c) 2024 Mervin<mengqing723@gmail.com>
* Released under the MIT License.
* unity-webgl v4.0.0
* Copyright (c) 2024 Mariner<mengqing723@gmail.com>
* Released under the Apache-2.0 License.
*/

@@ -9,13 +9,13 @@ 'use strict';

const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
const isPlainObject = arg => Object.prototype.toString.call(arg) === '[object Object]';
const msgPrefix = '[UnityWebgl]: ';
const log = (msg) => {
console.log(msgPrefix, msg);
};
log.warn = (msg) => console.warn(msgPrefix, msg);
log.error = (msg) => console.error(msgPrefix, msg);
const getType = (value) => Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
const isObject = (value) => getType(value) === 'object';
function omit(obj, keys) {
const result = Object.assign({}, obj);
keys.forEach((key) => {
delete result[key];
});
return result;
}
/**
* query CanvasElement
* @param {string | HTMLCanvasElement} canvas
* @returns
*/

@@ -26,106 +26,146 @@ function queryCanvas(canvas) {

}
else if (typeof canvas === 'string') {
return document.querySelector(canvas);
}
else {
log.warn('CanvasElement not found.');
return null;
}
return document.querySelector(canvas);
}
class EventBus {
constructor(_eventMap = {}) {
this._eventMap = _eventMap;
class UnityWebglEvent {
constructor() {
this._e = {};
if (isBrowser) {
// Register Unity event trigger to the window object
window.dispatchUnityEvent = (name, ...args) => {
if (!name.startsWith('unity:')) {
name = `unity:${name}`;
}
this.emit.apply(this, [name, ...args]);
};
}
}
on(name, handler) {
if (typeof handler !== 'function') {
throw new TypeError(msgPrefix + 'The argument handler must be function');
/**
* Register event listener
* @param name event name
* @param listener event listener
* @param options event listener options
*/
on(name, listener, options) {
if (typeof listener !== 'function') {
throw new TypeError('listener must be a function');
}
this._eventMap[name] = handler;
if (!this._e[name]) {
this._e[name] = [];
}
if (options === null || options === void 0 ? void 0 : options.once) {
const onceListener = (...args) => {
this.off(name, onceListener);
listener.apply(this, args);
};
onceListener._ = listener;
this._e[name].push(onceListener);
}
else {
this._e[name].push(listener);
}
return this;
}
off(name) {
delete this._eventMap[name];
return this;
}
once(name, handler) {
const ctx = this;
function fn(...args) {
if (typeof handler === 'function') {
ctx.off(name);
handler.apply(ctx, args);
/**
* Remove event listener
* @param name event name
* @param listener event listener
*/
off(name, listener) {
if (!listener) {
delete this._e[name];
}
else {
const listeners = this._e[name];
if (listeners) {
this._e[name] = listeners.filter((l) => l !== listener && l._ !== listener);
}
}
return this.on(name, fn);
return this;
}
/**
* Dispatch event
* @param name event name
* @param args event args
*/
emit(name, ...args) {
const handler = this._eventMap[name];
if (handler) {
handler.apply(this, args);
if (!this._e[name]) {
console.warn(`No listener for event ${name}`);
return this;
}
this._e[name].forEach((listener) => listener(...args));
return this;
}
/**
* clear all event listeners
*/
clear() {
for (const name in this._eventMap) {
delete this._eventMap[name];
this._e = {};
}
/**
* Register event listener for unity client
* @param name event name
* @param listener event listener
*/
addUnityListener(name, listener, options) {
if (!name.startsWith('unity:')) {
name = `unity:${name}`;
}
return this.on(name, listener, options);
}
/**
* Remove event listener from unity client
* @param name event name
* @param listener event listener
*/
removeUnityListener(name, listener) {
if (!name.startsWith('unity:')) {
name = `unity:${name}`;
}
return this.off(name, listener);
}
}
/**
* The unity loader
* @param {string} src loaderUrl
* @param {object} callbackObj callbackObj
* @param {Function} callbackObj.resolve resolve
* @param {Function} callbackObj.reject reject
* @returns
* Loading Unity Loader Scripts
* @param src script src
* @param callbacks callbacks
*/
function unityLoader(src, { resolve, reject }) {
function unityLoader(src, callbacks = {}) {
const { resolve, reject } = callbacks;
if (!isBrowser)
return;
return null;
if (!src) {
reject && reject(new Error(`${msgPrefix} loaderUrl not found.`));
return;
reject && reject(new Error(`${src} not found.`));
return null;
}
/* if (typeof window.createUnityInstance === 'function') {
log('Unity Loader already exists')
resolve && resolve()
return
} */
function handler(code) {
if (code === 'ready') {
if (code === 'loaded') {
resolve && resolve();
}
else {
reject && reject(new Error(`${msgPrefix} ${src} loading failure.`));
reject && reject(new Error(`${src} loading failure.`));
}
}
let script = window.document.querySelector(`script[src="${src}"]`);
if (script === null) {
if (!script) {
script = window.document.createElement('script');
script.type = 'text/javascript';
script.src = src;
script.async = true;
script.setAttribute('data-status', 'loading');
function setAttrListener(status) {
script === null || script === void 0 ? void 0 : script.setAttribute('data-status', status);
handler(status);
}
script.addEventListener('load', () => setAttrListener('loaded'));
script.addEventListener('error', () => setAttrListener('error'));
script.src = src;
window.document.body.appendChild(script);
const setAttributeFromEvent = function (event) {
const _status = event.type === 'load' ? 'ready' : 'error';
script === null || script === void 0 ? void 0 : script.setAttribute('data-status', _status);
// handler(_status)
};
script.addEventListener('load', setAttributeFromEvent);
script.addEventListener('error', setAttributeFromEvent);
}
else {
handler(script.getAttribute('data-status'));
handler(script.getAttribute('data-status') === 'loaded' ? 'loaded' : 'error');
}
const setStateFromEvent = function (event) {
handler(event.type === 'load' ? 'ready' : 'error');
};
script.addEventListener('load', setStateFromEvent);
script.addEventListener('error', setStateFromEvent);
return function () {
if (script) {
script.removeEventListener('load', setStateFromEvent);
script.removeEventListener('error', setStateFromEvent);
window.document.body.removeChild(script);
// Return cleanup function
return function remove() {
if (script && script.parentNode) {
script.parentNode.removeChild(script);
}

@@ -135,148 +175,103 @@ };

let BRIDGE_NAME = '__UnityLib__';
const defaultConfig = {
streamingAssetsUrl: 'StreamingAssets',
companyName: 'Unity',
productName: 'Unity'
};
/**
* generate UnityInstance arguments
* @param {object} unityContext unityContext
* @returns
*/
function generateUnityArguments(unity) {
const unityInstanceArgs = Object.assign({}, unity.unityConfig);
unityInstanceArgs.print = function (message) {
unity.emit('debug', message);
function createUnityArgs(ctx, config) {
const unityArgs = omit(config, ['loaderUrl']);
unityArgs.print = function (msg) {
ctx.emit('debug', msg);
};
unityInstanceArgs.printError = function (message) {
unity.emit('error', message);
unityArgs.printError = function (msg) {
ctx.emit('error', msg);
};
// delete unityInstanceArgs['lodaderUrl']
return unityInstanceArgs;
return unityArgs;
}
/**
* UnityWebgl
* // new UnityWebgl(canvasElement, unityConfig, bridge)
*/
class UnityWebgl extends EventBus {
constructor(canvas, config, bridge) {
let window;
window = globalThis || window;
bridge = bridge !== null && bridge !== void 0 ? bridge : BRIDGE_NAME;
if (isPlainObject(canvas) && typeof config === 'string') {
bridge = config || bridge;
class UnityWebgl extends UnityWebglEvent {
constructor(canvas, config) {
super();
this._unity = null;
this._loader = null;
this._canvas = null;
if (!(typeof canvas === 'string' || canvas instanceof HTMLCanvasElement || isObject(canvas))) {
throw new TypeError('Parameter canvas is not valid');
}
if (bridge in window) {
log.error(msgPrefix + `window.${bridge} already exists.`);
// config
if (isObject(canvas)) {
config = canvas;
}
BRIDGE_NAME = bridge;
super((window[bridge] = {}));
this.canvasElement = null;
this.unityLoader = null;
this.unityInstance = null;
if (isPlainObject(canvas)) {
this.unityConfig = Object.assign({}, defaultConfig, canvas);
if (!config ||
!config.loaderUrl ||
!config.dataUrl ||
!config.frameworkUrl ||
!config.codeUrl) {
throw new TypeError('UnityConfig is not valid');
}
else {
this.unityConfig = Object.assign({}, defaultConfig, config);
const $canvas = queryCanvas(canvas);
if ($canvas) {
this.create($canvas);
}
this._config = config;
// canvas
if (typeof canvas === 'string' || canvas instanceof HTMLCanvasElement) {
this.create(canvas);
}
}
get bridge() {
return BRIDGE_NAME;
}
set bridge(name) {
//!window
window[name] = window[BRIDGE_NAME];
delete window[BRIDGE_NAME];
BRIDGE_NAME = name;
}
/**
* 创建 Unity应用实例并渲染至画布
* @param canvas 画布
* @returns
* Creating Unity Instance
* @param canvas The target html canvas element.
*/
create(canvas) {
if (!isBrowser)
return;
if (this.unityInstance && this.canvasElement && this.unityLoader) {
log.warn('Unity Instance already exists!');
return void 0;
return Promise.resolve();
if (this._unity && this._canvas && this._loader) {
console.warn('Unity instance already created');
return Promise.resolve();
}
const canvasElement = queryCanvas(canvas);
if (!canvasElement) {
log.warn('CanvasElement not found.');
return void 0;
}
this.canvasElement = canvasElement;
const ctx = this;
const unityArguments = generateUnityArguments(this);
this.emit('beforeMount', this);
this.unityLoader = unityLoader(this.unityConfig.loaderUrl, {
resolve() {
try {
// Creates the Unity Instance, this method is made available globally by the Unity Loader.
window
.createUnityInstance(canvasElement, unityArguments, (val) => ctx.emit('progress', val))
.then((unity) => {
ctx.unityInstance = unity;
ctx.emit('created', unity); // todo 待删除
ctx.emit('mounted', ctx);
})
.catch((err) => {
return new Promise((resolve, reject) => {
try {
const $canvas = queryCanvas(canvas);
if (!$canvas) {
throw new Error('CanvasElement is not found');
}
this._canvas = $canvas;
const ctx = this;
// Create Unity instantiation Arguments
const unityArgs = createUnityArgs(this, this._config);
this.emit('beforeMount', this);
this._loader = unityLoader(this._config.loaderUrl, {
resolve() {
window
.createUnityInstance($canvas, unityArgs, (val) => ctx.emit('progress', val))
.then((ins) => {
ctx._unity = ins;
ctx.emit('mounted', ctx, ins);
resolve();
})
.catch((err) => {
throw err;
});
},
reject(err) {
throw err;
});
}
catch (err) {
ctx.unityInstance = null;
ctx.emit('error', err);
}
},
reject(err) {
log.error(err.message);
ctx.emit('error', err);
},
});
}
catch (err) {
this._unity = null;
this.emit('error', err);
reject(err);
}
});
}
/**
* 销毁并重新加载Unity应用
* @param config 配置项
*/
reload(config) {
var _a, _b;
const canvasElement = this.canvasElement || ((_b = (_a = this.unityInstance) === null || _a === void 0 ? void 0 : _a.Module) === null || _b === void 0 ? void 0 : _b.canvas);
if (this.unityInstance && canvasElement) {
this.unityInstance.Quit().then(() => {
this.unityLoader = null;
this.unityConfig = Object.assign({}, this.unityConfig, config);
this.emit('reload', this);
this.create(canvasElement);
}).catch(err => {
this.emit('error', err);
});
}
}
/**
* Sends a message to the UnityInstance to invoke a public method.
* @param {string} objectName Unity scene name.
* @param {string} methodName public method name.
* @param {any} params an optional method parameter.
* @param {any} value an optional method parameter.
* @returns
*/
send(objectName, methodName, params) {
if (this.unityInstance) {
if (params === undefined || params === null) {
this.unityInstance.SendMessage(objectName, methodName);
}
else {
const _params = typeof params === 'object' ? JSON.stringify(params) : params;
this.unityInstance.SendMessage(objectName, methodName, _params);
}
sendMessage(objectName, methodName, value) {
if (!this._unity) {
console.warn('Unable to Send Message while Unity is not Instantiated.');
return this;
}
if (value === undefined || value === null) {
this._unity.SendMessage(objectName, methodName);
}
else {
log.warn('Unable to Send Message while Unity is not Instantiated.');
const _value = typeof value === 'object' ? JSON.stringify(value) : value;
this._unity.SendMessage(objectName, methodName, _value);
}

@@ -286,35 +281,30 @@ return this;

/**
* Asynchronously ask for the pointer to be locked on current canvas. To track
* the success or failure of the request, it is necessary to listen for the
* pointerlockchange and pointerlockerror events at the Document level.
* @public
* @deprecated Use sendMessage instead.
*/
send(objectName, methodName, value) {
return this.sendMessage(objectName, methodName, value);
}
/**
* Asynchronously ask for the pointer to be locked on current canvas.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/requestPointerLock
*/
requestPointerLock() {
var _a, _b;
const canvasElement = this.canvasElement || ((_b = (_a = this.unityInstance) === null || _a === void 0 ? void 0 : _a.Module) === null || _b === void 0 ? void 0 : _b.canvas);
if (canvasElement) {
canvasElement.requestPointerLock();
if (!this._unity || !this._unity.Module.canvas) {
console.warn('Unable to requestPointerLock while Unity is not Instantiated.');
return;
}
this._unity.Module.canvas.requestPointerLock();
}
/**
* Takes a screenshot of the canvas and returns a data URL containing image
* data. The image data is in .png format unless otherwise specified.
* @param {string} dataType The image format of the screenshot, ["image/png" | "image/jpeg" | "image/webp"]
* @param {number} quality The quality of the jpg or webp screenshot
* @returns a data URL containing image data of a snapshot of the canvas
* Takes a screenshot of the canvas and returns a base64 encoded string.
* @param {string} dataType Defines the type of screenshot, e.g "image/jpeg"
* @param {number} quality Defines the quality of the screenshot, e.g 0.92
* @returns A base 64 encoded string of the screenshot.
*/
takeScreenshot(dataType = 'image/jpeg', quality) {
var _a, _b, _c;
const canvasElement = this.canvasElement || ((_b = (_a = this.unityInstance) === null || _a === void 0 ? void 0 : _a.Module) === null || _b === void 0 ? void 0 : _b.canvas);
if (!canvasElement) {
log.warn('Unable to Take Screenshot while Unity is not Instantiated or Canvas is not available.');
takeScreenshot(dataType, quality) {
if (!this._unity || !this._unity.Module.canvas) {
console.warn('Unable to take Screenshot while Unity is not Instantiated.');
return;
}
if (((_c = this.unityConfig.webglContextAttributes) === null || _c === void 0 ? void 0 : _c.preserveDrawingBuffer) !== true) {
log.warn('Taking a screenshot requires "preserveDrawingBuffer".');
}
// Takes a screenshot by converting Canvas's render-context's buffer into
// a Data URL of the specified data type and quality.
return canvasElement.toDataURL(dataType, quality);
return this._unity.Module.canvas.toDataURL(dataType, quality);
}

@@ -326,8 +316,7 @@ /**

setFullscreen(enabled) {
if (!this.unityInstance) {
// Guarding the Unity Instance.
log.warn('Unable to Set Fullscreen while Unity is not Instantiated.');
if (!this._unity) {
console.warn('Unable to set Fullscreen while Unity is not Instantiated.');
return;
}
this.unityInstance.SetFullscreen(enabled ? 1 : 0);
this._unity.SetFullscreen(enabled ? 1 : 0);
}

@@ -338,21 +327,23 @@ /**

unload() {
if (!this.unityInstance) {
// Guarding the Unity Instance.
log.warn('Unable to Quit Unity while Unity is not Instantiated.');
return Promise.reject(new Error('Unity is not Instantiated.'));
if (!this._unity) {
console.warn('Unable to Quit Unity while Unity is not Instantiated.');
return Promise.reject();
}
this.emit('beforeUnmount', this);
// Unmount unity.loader.js from the DOM
if (typeof this.unityLoader === 'function') {
this.unityLoader();
this.unityLoader = null;
// Unmount unity.loader.js from DOM
if (typeof this._loader === 'function') {
this._loader();
this._loader = null;
}
return this.unityInstance.Quit().then(() => {
this.unityInstance = null;
this.canvasElement = null;
delete window[BRIDGE_NAME];
// Unmount unityInstance from memory
return this._unity
.Quit()
.then(() => {
this._unity = null;
this._canvas = null;
this.clear();
this.emit('unmounted');
this.emit('destroyed'); // todo 待删除
}).catch((err) => {
log.error('Unable to Unload Unity');
})
.catch((err) => {
console.error('Unable to Unload Unity');
this.emit('error', err);

@@ -363,5 +354,3 @@ throw err;

/**
* Detatches the Unity Instance from the React DOM, by doing so, the Unity
* Instance can be unloaded from the memory while the Unity component can be
* unmounted safely.
* 保障Unity组件可以安全卸载. 在unity实例从内存中销毁之前保障Dom存在.
*

@@ -372,7 +361,6 @@ * Warning! This is a workaround for the fact that the Unity WebGL instances

*/
_unsafe_unload() {
unsafe_unload() {
try {
if (this.unityInstance === null || !this.unityInstance.Module.canvas) {
// Guarding the Unity Instance.
log.warn('No Unity Instance found.');
if (!this._unity || !this._unity.Module.canvas) {
console.warn('No Unity Instance found.');
return Promise.reject();

@@ -383,9 +371,6 @@ }

// canvas will be hidden while it is being unloaded.
const canvas = this.unityInstance.Module.canvas;
const canvas = this._unity.Module.canvas;
document.body.appendChild(canvas);
canvas.style.display = 'none';
// Unloads the Unity Instance.
return this.unload().then(() => {
// Eventually the canvas will be removed from the DOM. This has to be done
// manually since the canvas is no longer controlled by the React DOM.
canvas.remove();

@@ -395,3 +380,2 @@ });

catch (e) {
log.error(e.message);
return Promise.reject(e);

@@ -398,0 +382,0 @@ }

{
"name": "unity-webgl",
"version": "3.5.6",
"version": "4.0.0",
"description": "Unity-Webgl provides an easy solution for embedding Unity WebGL builds in your webApp or Vue.js project, with two-way communication between your webApp and Unity application with advanced API's.",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"unpkg": "dist/index.global.js",
"jsdelivr": "dist/index.global.js",
"module": "dist/index.mjs",
"unpkg": "dist/index.min.js",
"jsdelivr": "dist/index.min.js",
"types": "dist/index.d.ts",

@@ -13,11 +13,11 @@ "exports": {

"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.esm.js",
"default": "./dist/index.global.js"
"import": "./dist/index.mjs",
"module": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./vue": {
"types": "./vue/index.d.ts",
"require": "./vue/index.js",
"import": "./vue/index.esm.js",
"default": "./vue/index.global.js"
"types": "./dist/vue.d.ts",
"import": "./dist/vue.mjs",
"module": "./dist/vue.mjs",
"require": "./dist/vue.js"
},

@@ -27,12 +27,15 @@ "./*": "./*"

"files": [
"dist",
"types",
"vue"
"dist"
],
"treeShaking": true,
"scripts": {
"clean": "rimraf -rf ./dist && rimraf -rf ./vue",
"dev": "cross-env NODE_ENV=development rollup -c rollup.config.js -w",
"build": "npm run clean && cross-env NODE_ENV=production rollup -c rollup.config.mjs"
"buildOptions": {
"input": "src/index.ts",
"filename": "dist/index",
"name": "UnityWebgl",
"dts": true
},
"sideEffects": false,
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"keywords": [

@@ -46,30 +49,17 @@ "unity webgl",

"unity3d player",
"vue unity",
"vue unity webgl",
"vue unity player"
"vue unity"
],
"homepage": "https://github.com/Meqn/UnityWebGL.js",
"author": "Mariner <mengqing723@gmail.com>",
"license": "Apache-2.0",
"homepage": "https://github.com/Marinerer/unity-webgl",
"repository": {
"type": "git",
"url": "git+https://github.com/Meqn/UnityWebGL.js.git"
"url": "git+https://github.com/Marinerer/unity-webgl.git"
},
"author": "Mervin <mengqing723@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/Meqn/UnityWebGL.js/issues"
"url": "https://github.com/Marinerer/jotter/issues"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"devDependencies": {
"@vue/composition-api": "^1.7.0",
"vue": "^3.2.38"
},
"dependencies": {
"vue-demi": "latest"
},
"peerDependencies": {
"@vue/composition-api": "^1.7.0",
"vue": "^2.5.0 || >=3.0.0"
"@vue/composition-api": "^1.7.2",
"vue": "^2.0.0 || >=3.0.0"
},

@@ -80,3 +70,9 @@ "peerDependenciesMeta": {

}
},
"dependencies": {
"vue-demi": "latest"
},
"scripts": {
"build": "node ../../scripts/build.mjs"
}
}
}

@@ -6,24 +6,24 @@ # unity-webgl

[![size](https://img.shields.io/bundlephobia/minzip/unity-webgl?style=flat-square)](https://bundlephobia.com/package/unity-webgl)
[![languages](https://img.shields.io/github/languages/top/meqn/UnityWebGL.js?style=flat-square)](https://github.com/Meqn/UnityWebGL.js)
[![license](https://img.shields.io/npm/l/unity-webgl?style=flat-square)](https://github.com/Meqn/UnityWebGL.js)
[![license](https://img.shields.io/npm/l/unity-webgl?style=flat-square)](https://github.com/Marinerer/unity-webgl)
[ [English](https://github.com/Meqn/UnityWebGL.js/blob/main/README.md) | [中文](https://github.com/Meqn/UnityWebGL.js/blob/main/README.zh_CN.md) ]
[ English | [中文](./README.zh_CN.md) ]
`unity-webgl` provides an easy solution for embedding `Unity WebGL` builds in your web applications, with two-way communication and interaction between your webApp and Unity application with advanced API's.
> Framework agnostic, usable in any web project.
> Currently includes Vue components, supporting both Vue 2/3.
UnityWebGL.js provides an easy solution for embedding `Unity WebGL` builds in your `webApp` or `Vue.js` project, with two-way communication and interaction between your webApp and Unity application with advanced API's.
Based on [react-unity-webgl](https://github.com/jeffreylanters/react-unity-webgl)
## Features
based on [react-unity-webgl](https://github.com/jeffreylanters/react-unity-webgl)
- 📦 Easy integration, framework-agnostic
- 📩 Bidirectional communication between WebApp and Unity
- ⏰ Comprehensive event handling mechanism
- 🧲 Built-in Vue components (vue2/3)
## Features
- 📦 No framework restrictions, support any web project.
- 📬 two-way communication and interaction (`webApp` & `Unity`).
- 💌 Built-in event-listening mechanism.
- 🧲 On-demand import vue component. (Supports [Vue@2.x](https://stackblitz.com/edit/unity-webgl-vue2-demo?file=src%2FApp.vue) & [Vue@3.x](https://stackblitz.com/edit/unity-webgl-vue3-demo?file=src%2FApp.vue))
## Installation
## Install
**npm**
### npm
```bash

@@ -33,384 +33,310 @@ npm install unity-webgl

### browser
```bash
https://cdn.jsdelivr.net/npm/unity-webgl/dist/index.global.js
**Browser**
# vue component
https://cdn.jsdelivr.net/npm/unity-webgl/vue/index.global.js
```html
<script src="https://cdn.jsdelivr.net/npm/unity-webgl/dist/index.min.js"></script>
```
## Usage
## Quick Start
> 🚨 Reminder:
> You can only communicate and interact with the web application once the `Unity` instance has been successfully created (i.e. the `mounted` event is triggered).
> It is recommended to add a loading when opening a page, wait for Unity resources to finish loading and close it.
- [Live Demo]()
- [vue2 Demo](https://stackblitz.com/edit/unity-webgl-vue2-demo)
- [vue3 Demo](https://stackblitz.com/edit/unity-webgl-vue3-demo)
### html
<details>
<summary>html demo</summary>
> 🚨 **Important:**
> Communication and interaction with the web application are only possible after the Unity instance is successfully created (when the `mounted` event is triggered).
> Recommended to include a loading progress bar when opening the page.
```html
<canvas id="canvas" style="width: 100%; height: 100%"></canvas>
```javascript
import UnityWebgl from 'unity-webgl'
<button onclick="postMessage()">postMessage</button>
<button onclick="onFullscreen()">Fullscreen</button>
<button onclick="onUnload()">Unload</button>
<script>
var unityContext = new UnityWebgl('#canvas', {
loaderUrl: '/Build/unity.loader.js',
dataUrl: "/Build/unity.data",
frameworkUrl: "/Build/unity.framework.js",
codeUrl: "/Build/unity.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Unity",
productVersion: "0.1",
const unityContext = new UnityWebgl('#canvas', {
loaderUrl: 'path/to/unity.loader.js',
dataUrl: 'path/to/unity.data',
frameworkUrl: 'path/to/unity.framework.js',
codeUrl: 'path/to/unity.code',
})
unityContext
.on('progress', (progress) => console.log('Loaded: ', progress))
.on('mounted', () => {
// ⚠️ Resources are loaded and ready to communicate with unity
unityContext.send('mainScene', 'init', {})
console.log('Unity Instance created.')
})
.on('unmounted', () => console.log('Unity Instance unmounted.'))
.on('progress', (progress) => console.log('Loaded: ', progress))
.on('mounted', () => {
// ⚠️ Unity instance created, ready for communication
unityContext.sendMessage('GameObject', 'ReceiveRole', 'Tanya')
})
function postMessage() {
unityContext.send('objectName', 'methodName', {
id: 'B0001',
name: 'Building#1',
location: [150, 75]
})
}
function onUnload() {
unityContext.unload()
}
function onFullscreen() {
unityContext.setFullscreen(true)
}
</script>
```
You can also:
```js
var unityContext = new UnityWebgl({
loaderUrl: '/Build/unity.loader.js',
dataUrl: "/Build/unity.data",
frameworkUrl: "/Build/unity.framework.js",
codeUrl: "/Build/unity.wasm"
// For Unity to call
unityContext.addUnityListener('gameStart', (msg) => {
console.log('from Unity : ', msg)
})
unityContext.create(document.querySelector('#canvas'))
// window.dispatchUnityEvent('gameStart', '{score: 0}')
```
</details>
### Vue
- [Vue@2.x Live](https://stackblitz.com/edit/unity-webgl-vue2-demo?file=src%2FApp.vue)
- [Vue@3.x Live](https://stackblitz.com/edit/unity-webgl-vue3-demo?file=src/App.vue)
<details>
<summary>Vue demo</summary>
<summary>Vue Demo</summary>
```html
<script setup>
import UnityWebgl from 'unity-webgl';
import VueUnity from 'unity-webgl/vue'
import UnityWebgl from 'unity-webgl'
import VueUnity from 'unity-webgl/vue'
const unityContext = new UnityWebgl({
loaderUrl: '/Build/OUT_BIM.loader.js',
dataUrl: "/Build/OUT_BIM.data",
frameworkUrl: "/Build/OUT_BIM.framework.js",
codeUrl: "/Build/OUT_BIM.wasm",
})
const unityContext = new UnityWebgl({
loaderUrl: 'path/to/unity.loader.js',
dataUrl: 'path/to/unity.data',
frameworkUrl: 'path/to/unity.framework.js',
codeUrl: 'path/to/unity.code',
})
unityContext.on('device', () => alert('click device ...'))
unityContext.addUnityListener('gameStart', (msg) => {
console.log('from Unity : ', msg)
})
</script>
<template>
<VueUnity :unity="unityContext" width="800" height="600" />
<VueUnity :unity="unityContext" width="800" height="600" />
</template>
```
</details>
## API
### Constructor
## API
```typescript
unityContext = new UnityWebgl(
canvas: HTMLCanvasElement | string,
config: IUnityConfig,
bridge?: string
)
```
Or
```typescript
// 1. Initialize UnityWebgl
unityContext = new UnityWebgl(
config: IUnityConfig,
bridge?: string
)
new UnityWebgl(canvas: HTMLCanvasElement | string, config?:UnityConfig)
// 2. Create unity instance and render on canvas
// or
const unityContext = new UnityWebgl(config: UnityConfig)
unityContext.create(canvas: HTMLCanvasElement | string)
```
### canvas
Rendering Unity's canvas elements
- type : `string | HTMLCanvasElement`
- `canvas` : Render Unity canvas elements or selectors.
- `config` : Initializes the Unity application's configuration items.
### bridge
The name of the bridge to communicate with Unity. It mounts on window and is used to collect registered methods for Unity to call.
- type : `string`
- default : `__UnityLib__`
#### config
### config
Initializes the configuration of the Unity application.
> The configuration must contain the four most basic properties `loaderUrl`, `dataUrl`, `frameworkUrl`, `codeUrl`, which are the resource files needed to initialize the Unity application.
Initializes the Unity application's configuration items.
| Property | Type | Description |
| ---------------------- | ---- | ----------- |
| `loaderUrl` ⭐️ | string | The url to the build json file generated by Unity |
| `dataUrl` ⭐️ | string | The url to the build data file generated by Unity |
| `frameworkUrl` ⭐️ | string | The url to the framework file generated by Unity |
| `codeUrl` ⭐️ | string | The url to the unity code file generated by Unity |
| `streamingAssetsUrl` | string | The url where the streaming assets can be found |
| `memoryUrl` | string | External memory file |
| `symbolsUrl` | string | Providing debugging symbols |
| `companyName` | string | The applications company name |
| `productName` | string | The applications product name |
| `productVersion` | string | The applications product version |
| `devicePixelRatio` | number | Uncomment this to override low DPI rendering on high DPI displays. see [MDN@devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) |
| `matchWebGLToCanvasSize` | boolean | Uncomment this to separately control WebGL canvas render size and DOM element size. see [unity3d@matchWebGLToCanvasSize](https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size) |
| `webglContextAttributes` | object | This object allow you to configure WebGLRenderingContext creation options. see [MDN@WebGLRenderingContext](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes) |
| Property | Type | Description | Required |
| ------------------------ | ------- | -------------------------------------------------------------------------------------------------- | -------- |
| `loaderUrl` | string | Unity resource loader file | ✅ |
| `dataUrl` | string | File containing resource data and scenes | ✅ |
| `frameworkUrl` | string | File with runtime and plugin code | ✅ |
| `codeUrl` | string | WebAssembly binary file with native code | ✅ |
| `streamingAssetsUrl` | string | URL for streaming resources | Optional |
| `memoryUrl` | string | URL for generated framework files | Optional |
| `symbolsUrl` | string | URL for generated Unity code files | Optional |
| `companyName` | string | Metadata: Company name | Optional |
| `productName` | string | Metadata: Product name | Optional |
| `productVersion` | string | Metadata: Product version | Optional |
| `devicePixelRatio` | number | Canvas device pixel ratio. @see[devicePixelRatio][devicePixelRatio-url] | Optional |
| `matchWebGLToCanvasSize` | boolean | Disable automatic WebGL canvas size sync. @see[matchWebGLToCanvasSize][matchWebGLToCanvasSize-url] | Optional |
| `webglContextAttributes` | object | WebGL rendering context options. @see[WebGLRenderingContext][webglContextAttributes-url] | Optional |
[devicePixelRatio-url]: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
[matchWebGLToCanvasSize-url]: https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size
[webglContextAttributes-url]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes
### Methods
UnityWebgl Instance Methods
#### `create(canvasElement: HTMLCanvasElement | string): void`
Create Unity instances and render them on the canvas.
- `canvasElement` : canvas canvas elements
**Instance methods :**
#### `unload(): Promise<void>`
Quits the Unity instance and clears it from memory so that Unmount from the DOM.
> The `unmounted` event will be triggered after the operation is completed.
#### ⭐️ `create(canvas: HTMLCanvasElement | string): void;`
#### `send(objectName: string, methodName: string, params?: any)`
⭐️ Sends a message to the UnityInstance to invoke a public method.
- `objectName`: Where objectName is the name of an object in your scene.
- `methodName`: methodName is the name of a C-Sharp method in the script, currently attached to that object.
- `params`: Parameters can be any type of value or not defined at all.
Create a Unity WebGL instance on the specified canvas.
#### `on(eventName: string, eventListener: Function)`
⭐️ Register an event or method to listen for the trigger event or for the Unity script to call.
- `canvas` : canvas element
#### `setFullscreen(enabled: boolean): void`
Enables or disabled the fullscreen mode of the UnityInstance.
```javascript
await unityContext.create('#canvas')
```
#### `requestPointerLock(): void`
Allows you to asynchronously request that the mouse pointer be locked to the Canvas element of your Unity application.
#### ⭐️ `unload(): Promise<void>;`
#### `takeScreenshot(dataType: 'image/png' | 'image/jpeg' | 'image/webp', quality?: number)`
Takes a screenshot of the canvas and returns a data URL containing image data.
- `dataType`: the type of the image data
- `quality`: the quality of the image
Unload the Unity WebGL instance.
#### `once(eventName: string, eventListener: Function)`
The registration event is executed only once
```javascript
await unityContext.unload()
```
#### `off(eventName: string)`
Cancel listening event
#### ⭐️ `sendMessage(objectName: string, methodName: string, value?: any): this;`
#### `emit(eventName: string)`
Trigger listening event
Send a message to invoke a public method in the Unity scene.
- `objectName`: Object Name in Unity Scene
- `methodName`: Unity script method name
- `value`: Passed value
### Events
Events triggered by a Unity instance from creation to destruction.
#### beforeMount
Before Unity resources start loading. (The Unity instance has not been created yet.)
```js
unityContext.on('beforeMount', (unityContext) => {})
```javascript
unityContext.sendMessage('GameObject', 'gameStart', { role: 'Tanya' })
```
#### progress
Unity resource loading. (Show loading progress)
```js
unityContext.on('progress', (number) => {})
```
#### `requestPointerLock(): void;`
#### mounted
The Unity instance is successfully created and rendered. (At this point the webApp and Unity can communicate with each other)
```js
unityContext.on('mounted', (unityContext) => {})
```
Request pointer lock on the Unity canvas.
#### beforeUnmount
Before the Unity instance exits.
```js
unityContext.on('beforeUnmount', (unityContext) => {})
```
#### `takeScreenshot(dataType?: string, quality?: any): string | undefined;`
#### unmounted
The Unity instance has been exited and cleared from memory.
```js
unityContext.on('unmounted', () => {})
Capture a screenshot of the Unity canvas.
- `dataType`: Type of image data
- `quality`: Image quality
```javascript
const screenshot = unityContext.takeScreenshot('image/jpeg', 0.92)
```
#### error
Error messages caught by Unity instances during creation.
```js
unityContext.on('error', (error) => {})
#### `setFullscreen(enabled: boolean): void;`
Toggle fullscreen mode.
```javascript
unityContext.setFullscreen(true)
```
**Event methods :**
#### `on(name: string, listener: EventListener, options?: { once?: boolean }): this;`
## Vue component
Vue components, compatible with `vue2.x` and `vue3.x`.
Register for listening events.
### props
- `unity` : UnityWebgl instance.
- `width` : canvas element width, default: `100%`
- `height` : canvas element height, default: `100%`
- `tabindex` : Set the Canvas element tabindex.
```javascript
unityContext.on('progress', (progress) => {
console.log('Progress:', progress)
})
```
#### `off(name: string, listener?: EventListener): this;`
Remove event listener.
## Communication
```javascript
unityContext.off('progress', listener)
```
* [**WebGL: Interacting with browser scripting**@Unity3d.Docs](https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html)
**Unity Communication methods :**
### Calling JavaScript functions from Unity scripts
#### `addUnityListener(name: string, listener: EventListener, options?: { once?: boolean }): this;`
1, First, you should register a `showDialog` method, which be bind to the `__UnityLib__` global object by default.
Register a specific listener for Unity to call.
```js
// # in webApp
const unityContext = new UnityWebgl()
// Register functions
unityContext.on('showDialog', (data) => {
console.log(data)
$('#dialog').show()
```javascript
unityContext.addUnityListener('GameStarted', (level) => {
console.log('Game started at level:', level)
})
// you also can call function.
unityContext.emit('showDialog', data)
// then call it in Unity
window.dispatchUnityEvent('GameStarted', 3)
```
2, In the Unity project, add the registered `showDialog` method to the project, and then call those functions directly from your script code. To do so, place files with JavaScript code using the `.jslib` extension under a “Plugins” subfolder in your Assets folder. The plugin file needs to have a syntax like this:
#### `removeUnityListener(name: string, listener?: EventListener): this;`
```js
// javascript_extend.jslib
Remove registered listeners.
mergeInto(LibraryManager.library, {
// this is you code
showDialog: function (str) {
// var data = Pointer_stringify(str);
var data = UTF8ToString(str); // In Unity 2021.2 onwards
// '__UnityLib__' is a global function collection.
__UnityLib__.showDialog(data);
},
Hello: function () {
window.alert("Hello, world!");
}
});
```javascript
unityContext.removeUnityListener('GameStarted', listener)
```
Then you can call these functions from your C# scripts like this:
### `window.dispatchUnityEvent(name: string, ...args: any[])`
```c#
using UnityEngine;
using System.Runtime.InteropServices;
The way to dispatch a registered listener on the Unity side. (Calling JS methods in unity)
public class NewBehaviourScript : MonoBehaviour {
```javascript
window.dispatchUnityEvent('GameStarted', 3)
```
[DllImport("__Internal")]
private static extern void Hello();
### Events
[DllImport("__Internal")]
private static extern void showDialog(string str);
| Event Name | Description |
| --------------- | ---------------------------------------- |
| `beforeMount` | Triggered before Unity instance creation |
| `mounted` | Triggered after Unity instance creation |
| `beforeUnmount` | Triggered before Unity instance unload |
| `unmounted` | Triggered after Unity instance unload |
| `progress` | Unity resource loading progress |
| `error` | Error events |
| `debug` | Debug messages from Unity |
void Start() {
Hello();
showDialog("This is a string.");
}
}
```
## Unity-JavaScript Communication
### Calling Unity scripts functions from JavaScript
- [Unity Docs: Interaction with browser scripting](https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html)
```js
const Unity = new UnityWebgl()
### 1. Call Unity script functions from JavaScript
```javascript
const unityContext = new UnityWebgl()
/**
* Sends a message to the UnityInstance to invoke a public method.
* @param {string} objectName Unity scene name.
* @param {string} methodName public method name.
* @param {any} params an optional method parameter.
* @param {string} objectName Name of an object in your scene.
* @param {string} methodName Public method name.
* @param {any} value Passed value.
*/
Unity.send(objectName, methodName, params)
unityContext.sendMessage('GameObject', 'StartGame', { role: 'Tanya' })
```
// e.g. Initialize Building#001 data
Unity.send('mainScene', 'init', {
id: 'b001',
name: 'building#001',
length: 95,
width: 27,
height: 120
### 2. Call JavaScript functions from Unity scripts
1. First register the listener for Unity to call via `addUnityListener` on the web side.
```javascript
unityContext.addUnityListener('gameStart', (level) => {
console.log('Game started at level:', level)
})
```
2. Add the registered `gameStart` method to your Unity project.
```javascript
// javascript_extend.jslib
mergeInto(LibraryManager.library, {
Hello: function () {
window.alert('Hello, world!')
},
## ChangeLog
GameStart: function (level) {
//window.alert(UTF8ToString(str));
window.dispatchUnityEvent('gameStart', UTF8ToString(level))
},
})
```
### v3.5.0
#### 🚀 Features
- feat: Add `reload` method and event.
- perf: Optimize the `create` and `unload` methods.
3. Call these functions in unity's `C#` scripts:
```csharp
using UnityEngine;
using System.Runtime.InteropServices;
### v3.4.0
#### 🚀 Features
- feat: Add configuration and changes to the global object `bridge`.
- feat: Unify events from creation to destruction of Unity applications.
- Adds `beforeMount`, `mounted`, `beforeUnmount`, `unmounted` events;
- Remove `created`, `destroyed` events.
- perf: Simplify the built-in event listener.
- perf: Optimize built-in vue components.
- perf: update typescript types.
- perf: Unified error message alert.
- docs: Optimize the use of documentation.
public class WebGLPluginJS : MonoBehaviour
{
[DllImport("__Internal")]
public static extern void Hello();
#### 🐞 Bug Fixes
- fix: Repair SPA unload error
[DllImport("__Internal")]
public static extern void GameStart(string level);
void Start()
{
Hello();
GameStart("2");
}
}
```
### v3.0.0
#### 🚀 Features
- feat: Rewrite in Typescript
- feat: Vue components are compatible with vue2.x and vue3.x
- perf: Introducing vue components on demand
## Issues
#### 🐞 Bug Fixes
- fix: Fix createUnityInstance multiple times
- fix: Fix vue component width/height size problem
- [Keyboard Input and Focus Handling](https://docs.unity3d.com/Manual/webgl-input.html)
- [Debug and troubleshoot Web builds](https://docs.unity3d.com/Manual/webgl-debugging.html)
- [Web performance considerations](https://docs.unity3d.com/Manual/webgl-performance.html)
### v2.x
- [v2.x Docs](https://github.com/Meqn/UnityWebGL.js/blob/v2.x/README.md)
## Contributing
### v1.x
- [v1.x Docs](https://github.com/Meqn/UnityWebGL.js/blob/v1.x/README.md)
Contributions are welcome! Please submit a [Pull Request](https://github.com/Marinerer/unity-webgl/pulls).
## License
Apache-2.0 License
## Support
For issues or questions, please file an issue on the [GitHub repository](https://github.com/Marinerer/unity-webgl).

@@ -6,419 +6,338 @@ # unity-webgl

[![size](https://img.shields.io/bundlephobia/minzip/unity-webgl?style=flat-square)](https://bundlephobia.com/package/unity-webgl)
[![languages](https://img.shields.io/github/languages/top/meqn/UnityWebGL.js?style=flat-square)](https://github.com/Meqn/UnityWebGL.js)
[![license](https://img.shields.io/npm/l/unity-webgl?style=flat-square)](https://github.com/Meqn/UnityWebGL.js)
[![license](https://img.shields.io/npm/l/unity-webgl?style=flat-square)](https://github.com/Marinerer/unity-webgl)
[ [English](https://github.com/Meqn/UnityWebGL.js/blob/main/README.md) | [中文](https://github.com/Meqn/UnityWebGL.js/blob/main/README.zh_CN.md) ]
[ [English](./README.md) | 中文 ]
`unity-webgl` 提供了一个简单的解决方案,用于将 `Unity WebGL` 构建嵌入到 Web 应用程序中,同时为 Unity 和 WebApp 应用之间的双向通信和交互提供 API。
> 无框架限制,可用于任何 Web 项目。
> 目前仅内置vue组件,支持 `vue2/3`。
UnityWebgl.js 提供了一种简单的解决方案,用于将 `Unity WebGL` 构建嵌入到 Web 应用程序中,同时为 `Unity` 和 `WebApp` 应用之间的双向通信和交互提供 API。
Based on [react-unity-webgl](https://github.com/jeffreylanters/react-unity-webgl)
> 无框架限制,可用于任何web项目。
> 目前仅内置vue组件,支持`vue2.x`和`vue3.x`。
based on [react-unity-webgl](https://github.com/jeffreylanters/react-unity-webgl)
## Features
- 📦 无框架限制,支持任何web项目;
- 📬 支持在`WebApp` 和 `Unity` 之间双向通信和交互;
- 💌 使用事件监听机制,调用简单灵活;
- 🧲 按需引入vue组件,兼容[Vue@2.x](https://stackblitz.com/edit/unity-webgl-vue2-demo?file=src%2FApp.vue) 和 [Vue@3.x](https://stackblitz.com/edit/unity-webgl-vue3-demo?file=src%2FApp.vue)。
📦 集成简单,无框架限制
📩 支持 `WebApp` 与 `Unity` 双向通信和交互
⏰ 全面的事件处理机制
🧲 内置 `vue` 组件 (vue2/3)
## Installation
## Install
**npm**
### npm
```bash
```
npm install unity-webgl
```
### browser
```bash
https://cdn.jsdelivr.net/npm/unity-webgl/dist/index.global.js
**browser**
# vue component
https://cdn.jsdelivr.net/npm/unity-webgl/vue/index.global.js
```
https://cdn.jsdelivr.net/npm/unity-webgl/dist/index.min.js
```
## Usage
## Quick Start
- [Live Demo]()
- [vue2 Demo](https://stackblitz.com/edit/unity-webgl-vue2-demo)
- [vue3 Demo](https://stackblitz.com/edit/unity-webgl-vue3-demo)
> 🚨 提醒:
> 只有当`Unity`实例创建成功之后(即触发 `mounted` 事件)才能和web应用程序进行通信和交互。
> 建议在打开页面时添加一个 loading,等待Unity资源加载完毕后关闭即可。
> 仅在 `Unity` 实例成功创建后(触发 `mounted` 事件时)才能进行 Web 应用程序的通信和交互。
> 建议在页面打开时添加加载进度条。
### html
<details>
<summary>html demo</summary>
```javascript
import UnityWebgl from 'unity-webgl'
```html
<canvas id="canvas" style="width: 100%; height: 100%"></canvas>
<button onclick="postMessage()">postMessage</button>
<button onclick="onFullscreen()">Fullscreen</button>
<button onclick="onUnload()">Unload</button>
<script>
var unityContext = new UnityWebgl('#canvas', {
loaderUrl: '/Build/unity.loader.js',
dataUrl: "/Build/unity.data",
frameworkUrl: "/Build/unity.framework.js",
codeUrl: "/Build/unity.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Unity",
productVersion: "0.1",
const unityContext = new UnityWebgl('#canvas', {
loaderUrl: 'path/to/unity.loader.js',
dataUrl: 'path/to/unity.data',
frameworkUrl: 'path/to/unity.framework.js',
codeUrl: 'path/to/unity.code',
})
unityContext
.on('progress', (progress) => console.log('Loaded: ', progress))
.on('mounted', () => {
// ⚠️ 资源加载完成,可与unity进行通信
unityContext.send('mainScene', 'init', {})
console.log('Unity Instance created.')
})
.on('unmounted', () => console.log('Unity Instance unmounted.'))
.on('progress', (progress) => console.log('Loaded: ', progress))
.on('mounted', () => {
// ⚠️ unity实例已创建,可与unity侧进行通信
unityContext.sendMessage('GameObject', 'ReceiveRole', 'Tanya')
})
function postMessage() {
unityContext.send('objectName', 'methodName', {
id: 'B0001',
name: 'Building#1',
location: [150, 75]
})
}
function onUnload() {
unityContext.unload()
}
function onFullscreen() {
unityContext.setFullscreen(true)
}
</script>
```
You can also:
```js
var unityContext = new UnityWebgl({
loaderUrl: '/Build/unity.loader.js',
dataUrl: "/Build/unity.data",
frameworkUrl: "/Build/unity.framework.js",
codeUrl: "/Build/unity.wasm"
// 供unity 端调用
unityContext.addUnityListener('gameStart', (msg) => {
console.log('from Unity : ', msg)
})
unityContext.create(document.querySelector('#canvas'))
// window.dispatchUnityEvent('gameStart', '{score: 0}')
```
</details>
### Vue
- [Vue@2.x Live](https://stackblitz.com/edit/unity-webgl-vue2-demo?file=src%2FApp.vue)
- [Vue@3.x Live](https://stackblitz.com/edit/unity-webgl-vue3-demo?file=src/App.vue)
<details>
<summary>Vue demo</summary>
<summary>Vue Demo</summary>
```html
<script setup>
import UnityWebgl from 'unity-webgl';
import VueUnity from 'unity-webgl/vue'
import UnityWebgl from 'unity-webgl'
import VueUnity from 'unity-webgl/vue'
const unityContext = new UnityWebgl({
loaderUrl: '/Build/OUT_BIM.loader.js',
dataUrl: "/Build/OUT_BIM.data",
frameworkUrl: "/Build/OUT_BIM.framework.js",
codeUrl: "/Build/OUT_BIM.wasm",
})
const unityContext = new UnityWebgl({
loaderUrl: 'path/to/unity.loader.js',
dataUrl: 'path/to/unity.data',
frameworkUrl: 'path/to/unity.framework.js',
codeUrl: 'path/to/unity.code',
})
unityContext.on('device', () => alert('click device ...'))
unityContext.addUnityListener('gameStart', (msg) => {
console.log('from Unity : ', msg)
})
</script>
<template>
<VueUnity :unity="unityContext" width="800" height="600" />
<VueUnity :unity="unityContext" width="800" height="600" />
</template>
```
</details>
## API
### Constructor
## API
```typescript
unityContext = new UnityWebgl(
canvas: HTMLCanvasElement | string,
config: IUnityConfig,
bridge?: string
)
```
```typescript
// 1. 初始化 UnityWebgl
unityContext = new UnityWebgl(
config: IUnityConfig,
bridge?: string
)
new UnityWebgl(canvas: HTMLCanvasElement | string, config?:UnityConfig)
// 2. 创建unity实例,并在canvas上渲染
// or
const unityContext = new UnityWebgl(config: UnityConfig)
unityContext.create(canvas: HTMLCanvasElement | string)
```
> 备注:
> `unityContext` : 表示 `UnityWebgl`实例;
> `unityInstance` : 表示 Unity应用程序实例。
- `canvas` : 渲染Unity的画布元素或选择器。
- `config` : 初始化 Unity 应用程序的配置项。
### canvas
渲染Unity的画布元素
- type : `string | HTMLCanvasElement`
#### config
### bridge
与Unity通信的桥接名称。它挂载window上,用于收集已注册的方法供Unity调用。
- type : `string`
- default : `__UnityLib__`
初始化 Unity 应用程序的配置项。
### config
初始化 Unity 应用程序的配置项。
> 配置项必须包含最基本的四个属性`loaderUrl`, `dataUrl`, `frameworkUrl`, `codeUrl` ,这四个属性都是初始化 Unity 应用程序所需的资源文件。
| Property | Type | Description | Required |
| ------------------------ | ------- | ------------------------------------------------------------------------------------- | -------- |
| `loaderUrl` | string | Unity 资源加载器文件 | ✅ |
| `dataUrl` | string | 包含资源数据和场景的文件 | ✅ |
| `frameworkUrl` | string | 包含运行时和插件代码的文件 | ✅ |
| `codeUrl` | string | 包含原生代码的 WebAssembly 二进制文件 | ✅ |
| `streamingAssetsUrl` | string | 流媒体资源的 URL | 可选 |
| `memoryUrl` | string | 生成的框架文件的 URL | 可选 |
| `symbolsUrl` | string | 生成的 Unity 代码文件的 URL | 可选 |
| `companyName` | string | 元数据:公司名称 | 可选 |
| `productName` | string | 元数据:产品名称 | 可选 |
| `productVersion` | string | 元数据:产品版本 | 可选 |
| `devicePixelRatio` | number | 画布设备像素比率. @see[devicePixelRatio][devicePixelRatio-url] | 可选 |
| `matchWebGLToCanvasSize` | boolean | 禁用 WebGL 画布大小自动同步. @see[matchWebGLToCanvasSize][matchWebGLToCanvasSize-url] | 可选 |
| `webglContextAttributes` | object | WebGL 渲染上下文选项. @see[WebGLRenderingContext][webglContextAttributes-url] | 可选 |
| Property | Type | Description |
| ---------------------- | ---- | ----------- |
| `loaderUrl` ⭐️ | string | Unity资源加载器文件 |
| `dataUrl` ⭐️ | string | 包含资源数据和场景的文件 |
| `frameworkUrl` ⭐️ | string | 包含运行时和插件代码的文件 |
| `codeUrl` ⭐️ | string | 包含本机代码的 Web Assembly 二进制文件 |
| `streamingAssetsUrl` | string | 可以找到流媒体资源的网址 |
| `memoryUrl` | string | 生成的框架文件的网址 |
| `symbolsUrl` | string | 生成的unity代码文件的网址 |
| `companyName` | string | 元数据: 公司名称 |
| `productName` | string | 元数据: 产品名称 |
| `productVersion` | string | 元数据: 产品版本 |
| `devicePixelRatio` | number | 设置画布的设备像素比率. @详见[MDN@devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) |
| `matchWebGLToCanvasSize` | boolean | 禁用WebGL画布的渲染尺寸自动同步标识。@详见[unity3d@matchWebGLToCanvasSize](https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size) |
| `webglContextAttributes` | object | 配置 WebGLRenderingContext 创建选项。@详见[MDN@WebGLRenderingContext](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes) |
[devicePixelRatio-url]: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
[matchWebGLToCanvasSize-url]: https://issuetracker.unity3d.com/issues/webgl-builds-dont-allow-separate-control-on-canvas-render-buffer-size
[webglContextAttributes-url]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getContextAttributes
### Methods
**Instance methods :**
### Methods
UnityWebgl 实例方法
#### ⭐️ `create(canvas: HTMLCanvasElement | string): void;`
#### `create(canvasElement: HTMLCanvasElement | string): void`
创建Unity实例并在画布上渲染。
- `canvasElement` : canvas画布元素
在指定画布上创建 Unity WebGL 实例。
#### `unload(): Promise<void>`
退出Unity实例并将其从内存中清除,以便从DOM中Unmount。此时也会删除所有已注册的方法。
> 操作完成之后会触发 `unmounted` 事件
- `canvas` : canvas画布元素
#### `send(objectName: string, methodName: string, params?: any)`
⭐️ 向Unity实例对象发送消息,调用一个公共方法。
- `objectName`: Unity场景中对象的名称
- `methodName`: Unity脚本中方法的名称
- `params`: 传递的参数
```javascript
await unityContext.create('#canvas')
```
#### `on(eventName: string, eventListener: Function)`
⭐️ 注册一个事件或方法,用于监听触发事件或供Unity脚本调用。
#### ⭐️ `unload(): Promise<void>;`
#### `setFullscreen(enabled: boolean): void`
启用或禁用 Unity 画布的全屏模式。
卸载 Unity WebGL 实例。
#### `requestPointerLock(): void`
允许您异步地请求将鼠标指针锁定在Unity应用的Canvas元素上。
```javascript
await unityContext.unload()
```
#### `takeScreenshot(dataType: 'image/png' | 'image/jpeg' | 'image/webp', quality?: number)`
获取画布的屏幕截图并返回包含图像数据的数据 URL。
- `dataType`: 图像数据的类型
- `quality`: 图像的质量
#### ⭐️ `sendMessage(objectName: string, methodName: string, value?: any): this;`
#### `once(eventName: string, eventListener: Function)`
注册事件仅执行一次
向 `Unity` 场景中发送消息以调用公共方法。
#### `off(eventName: string)`
取消监听事件
- `objectName`: Unity场景中对象名称
- `methodName`: Unity脚本中方法名称
- `value`: 传递的值
#### `emit(eventName: string)`
触发监听事件
```javascript
unityContext.sendMessage('GameObject', 'gameStart', { role: 'Tanya' })
```
#### `requestPointerLock(): void;`
### Events
Unity 实例从创建到销毁过程中触发的事件。
请求锁定 Unity 画布的指针。
#### beforeMount
Unity 资源开始加载之前。(此时Unity实例还未创建)
```js
unityContext.on('beforeMount', (unityContext) => {})
```
#### `takeScreenshot(dataType?: string, quality?: any): string | undefined;`
#### progress
Unity 资源加载中。(显示加载进度)
```js
unityContext.on('progress', (number) => {})
```
对 Unity 画布进行屏幕截图并返回包含图像数据的数据 URL。
#### mounted
Unity 实例创建成功,并完成渲染。(此时webApp与Unity可以相互通信)
```js
unityContext.on('mounted', (unityContext) => {})
```
- `dataType`: 图像数据的类型
- `quality`: 图像的质量
#### beforeUnmount
Unity 实例退出之前。
```js
unityContext.on('beforeUnmount', (unityContext) => {})
```javascript
const screenshot = unityContext.takeScreenshot('image/jpeg', 0.92)
```
#### unmounted
Unity实例已退出并将其从内存中清除。
```js
unityContext.on('unmounted', () => {})
```
#### `setFullscreen(enabled: boolean): void;`
#### error
Unity实例在创建过程中捕获的错误信息
```js
unityContext.on('error', (error) => {})
切换全屏模式。
```javascript
unityContext.setFullscreen(true)
```
**Event methods :**
#### `on(name: string, listener: EventListener, options?: { once?: boolean }): this;`
## Vue component
Vue组件,兼容 `vue2.x` 和 `vue3.x`
监听事件。
### props
- `unity` : UnityWebgl实例
- `width` : canvas元素宽度, default: `100%`
- `height` : canvas元素高度, default: `100%`
- `tabindex` : 设置Canvas元素tabindex
```javascript
unityContext.on('progress', (progress) => {
console.log('Progress:', progress)
})
```
#### `off(name: string, listener?: EventListener): this;`
移除事件监听器。
## Communication
```javascript
unityContext.off('progress', listener)
```
* [Unity3d官方文档:**WebGL:与浏览器脚本交互**](https://docs.unity3d.com/cn/2020.3/Manual/webgl-interactingwithbrowserscripting.html)
**Unity Communication methods :**
### 从 Unity 脚本调用 JavaScript 函数
#### `addUnityListener(name: string, listener: EventListener, options?: { once?: boolean }): this;`
1. 先在前端项目中通过 `Unity.on()` 注册 `showDialog` 方法,该方法会默认绑定在 `window['__UnityLib__']`对象上。
注册特定监听器供 Unity 端调用。
```js
// # in webApp
const unityContext = new UnityWebgl()
// Register functions
unityContext.on('showDialog', (data) => {
console.log(data)
$('#dialog').show()
```javascript
unityContext.addUnityListener('GameStarted', (level) => {
console.log('Game started at level:', level)
})
// you also can call function.
unityContext.emit('showDialog', data)
// then call it in Unity
window.dispatchUnityEvent('GameStarted', 3)
```
2. 在Unity项目中,将注册的`showDialog`方法添加到项目中。
注意📢 :请使用 `.jslib` 扩展名将包含 JavaScript 代码的文件放置在 Assets 文件夹中的“Plugins”子文件夹下。插件文件需要有如下所示的语法:
#### `removeUnityListener(name: string, listener?: EventListener): this;`
```js
// javascript_extend.jslib
移除注册的监听器。
mergeInto(LibraryManager.library, {
// this is you code
showDialog: function (str) {
// var data = Pointer_stringify(str);
var data = UTF8ToString(str);
// '__UnityLib__' is a global function collection.
__UnityLib__.showDialog(data);
},
Hello: function () {
window.alert("Hello, world!");
}
});
```javascript
unityContext.removeUnityListener('GameStarted', listener)
```
然后你可以像这样从C#脚本中调用这些函数:
### `window.dispatchUnityEvent(name: string, ...args: any[])`
```c#
using UnityEngine;
using System.Runtime.InteropServices;
在 Unity 端派发注册的监听器的方式。(在 unity 中调用 JS 的方法)
public class NewBehaviourScript : MonoBehaviour {
```javascript
window.dispatchUnityEvent('GameStarted', 3)
```
[DllImport("__Internal")]
private static extern void Hello();
### Events
[DllImport("__Internal")]
private static extern void showDialog(string str);
Unity 实例从创建到销毁过程中触发的事件。
void Start() {
Hello();
showDialog("This is a string.");
}
}
```
| event name | description |
| ----------------------------- | ----------------------- |
| `beforeMount(unityContext)` | 创建 Unity 实例之前触发 |
| `mounted(unityContext)` | 创建 Unity 实例后触发 |
| `beforeUnmount(unityContext)` | 卸载 Unity 实例之前触发 |
| `unmounted()` | 卸载 Unity 实例后触发 |
| `progress(val: number)` | unity 资源加载进度更新 |
| `error(err: Event\|string)` | 发生错误 |
| `debug(msg: string)` | 来自 Unity 的调试消息 |
### 使用 JavaScript 调用 Unity 脚本函数
## Unity-JavaScript Communication
```js
const Unity = new UnityWebgl()
- [Unity官方文档:与浏览器脚本交互](https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html)
### 1. Call Unity script functions from JavaScript
```javascript
const unityContext = new UnityWebgl()
/**
* Sends a message to the UnityInstance to invoke a public method.
* @param {string} objectName Unity scene name.
* @param {string} objectName name of an object in your scene.
* @param {string} methodName public method name.
* @param {any} params an optional method parameter.
* @param {any} value send value.
*/
Unity.send(objectName, methodName, params)
unityContext.sendMessage('GameObject', 'StartGame', { role: 'Tanya' })
```
// e.g. Initialize Building#001 data
Unity.send('mainScene', 'init', {
id: 'b001',
name: 'building#001',
length: 95,
width: 27,
height: 120
### 2. Call JavaScript functions from Unity scripts
1. 首先在 web 端通过 `addUnityListener` 注册供 Unity 调用的监听器。
```javascript
unityContext.addUnityListener('gameStart', (level) => {
console.log('Game started at level:', level)
})
```
2. 在Unity项目中,将注册的 `gameStart` 方法添加到项目中。
```javascript
// javascript_extend.jslib
mergeInto(LibraryManager.library, {
Hello: function () {
window.alert('Hello, world!')
},
## ChangeLog
GameStart: function (level) {
//window.alert(UTF8ToString(str));
window.dispatchUnityEvent('gameStart', UTF8ToString(level))
},
})
```
### v3.5.0
#### 🚀 Features
- feat: 新增 `reload` 方法和事件
- perf: 优化 `create` 和 `unload` 方法
3. 在 `C#` 脚本中调用这些函数:
### v3.4.0
#### 🚀 Features
- feat: 增加全局对象`bridge`的配置和更改
- feat: 统一化Unity应用程序从创建到销毁的事件
- 增加 `beforeMount`, `mounted`, `beforeUnmount`, `unmounted` 事件
- 移除 `created`, `destroyed` 事件
- perf: 简化内置事件监听器
- perf: 优化内置vue组件
- perf: 更新typescript types
- perf: 统一错误信息提示
- docs: 优化使用文档
```csharp
using UnityEngine;
using System.Runtime.InteropServices;
#### 🐞 Bug Fixes
- fix: 修复单页应用unload报错
public class WebGLPluginJS : MonoBehaviour
{
[DllImport("__Internal")]
public static extern void Hello();
[DllImport("__Internal")]
public static extern void GameStart(string level);
### v3.0.0
#### 🚀 Features
- feat: 使用Typescript重写
- feat: Vue组件兼容vue2.x和vue3.x
- perf: 按需引入vue component
void Start()
{
Hello();
GameStart("2");
}
}
```
#### 🐞 Bug Fixes
- fix: 修复createUnityInstance执行多次
- fix: 修复vue组件width/height尺寸问题
## Issues
### v2.x
- [v2.x文档](https://github.com/Meqn/UnityWebGL.js/blob/v2.x/README.md)
- [键盘输入和焦点处理](https://docs.unity3d.com/cn/2023.2/Manual/webgl-input.html)
- [调试 WebGL 构建并排除故障](https://docs.unity3d.com/cn/2023.2/Manual/webgl-debugging.html)
- [WebGL 性能考虑因素](https://docs.unity3d.com/cn/2023.2/Manual/webgl-performance.html)
### v1.x
- [v1.x文档](https://github.com/Meqn/UnityWebGL.js/blob/v1.x/README.md)
## License
MIT License
## Contributing
Contributions are welcome! Please feel free to submit a [Pull Request](https://github.com/Marinerer/unity-webgl/pulls).
## Support
For issues or questions, please file an issue on the [GitHub repository](https://github.com/Marinerer/unity-webgl).