vue中使用unity3D如何實現(xiàn)webGL將要呈現(xiàn)的效果
1. 什么是webGL
WebGL(Web圖形庫)是一個JavaScript API,可在任何兼容的Web瀏覽器中渲染高性能的交互式3D和2D圖形,而無需使用插件。
WebGL通過引入一個與OpenGL ES 2.0非常一致的API來做到這一點,該API可以在 HTML5 <canvas>元素中使用。
這種一致性使API可以利用用戶設備提供的硬件圖形加速。
1.1 兼容性
目前支持 WebGL 的瀏覽器有:
- Firefox 4+
- Google Chrome 9+
- Opera 12+
- Safari 5.1+
- Internet Explorer 11+
- Microsoft Edge build 10240+
然而, WebGL一些特性也需要用戶的硬件設備支持。
2. 什么是unity3D
Unity 3D 簡稱 U3D 或者 Unity,是當今世界范圍內(nèi)主流的 3D 游戲開發(fā)引擎,用 Unity 3D 開發(fā)的游戲可以在電腦、手機、游戲機、瀏覽器等幾乎所有常見平臺上運行。
Unity 3D 是由 Unity Technologies 公司開發(fā)的一個讓玩家輕松創(chuàng)建諸如三維視頻游戲、建筑可視化、實時三維動畫等類型互動內(nèi)容的多平臺的綜合型游戲開發(fā)工具。
Unity 3D 可以運行在 Windows 和MacOS X下,可發(fā)布游戲至 Windows、Mac、Wii、iPhone、WebGL(需要 HTML5)、Windows Phone 8 和 Android 平臺。也可以利用 Unity Web Player插件發(fā)布網(wǎng)頁游戲,支持Mac和 Windows平臺的網(wǎng)頁瀏覽,是一個全面整合的專業(yè)游戲引擎。
2.1 unity3D 的發(fā)展史
- 2004 年,Unity 3D 誕生于丹麥的阿姆斯特丹。
- 2005 年,發(fā)布了 Unity 1.0 版本,此版本只能應用于 Mac 平臺,主要針對 Web 項目和VR(虛擬現(xiàn)實)的開發(fā)。
- 2008 年,推出 Windows 版本,并開始支持iOS 和Wii,從眾多的游戲引擎中脫穎而出。
- 2009 年,榮登 2009 年游戲引擎的前五,此時 Unity 的注冊人數(shù)已經(jīng)達到了 3.5 萬。
- 2010 年,Unity 3D 開始支持 Android,繼續(xù)擴大影響力。
- 2011 年,開始支持 PS3 和 XBox360,此時全平臺的構建完成。
- 2012 年,Unity Technologies公司正式推出 Unity 4.0版本,新加入對于DirectX 11 的支持和Mecanim動畫工具,以及為用戶提供Linux及 Adobe Flash Player的部署預覽功能。
- 2013 年,Unity 3D引擎覆蓋了越來越多的國家,全球用戶已經(jīng)超過 150 萬,Unity 4.0引擎已經(jīng)能夠支持在包括MacOS X、Android、iOS、Windows 等在內(nèi)的 10 個平臺上發(fā)布游戲。同時,Unity Technologies公司 CEO David Helgason 發(fā)布消息稱,游戲引擎Unity 3D 今后將不再支持Flash 平臺,且不再銷售針對 Flash 開發(fā)者的軟件授權。
- 2014 年,發(fā)布 Unity 4.6 版本,更新了屏幕自動旋轉等功能。
- 2016 年,發(fā)布 Unity 5.4 版本,專注于新的視覺功能,為開發(fā)人員提供了最新的理想實驗和原型功能模式,極大地提高了其在 VR 畫面展現(xiàn)上的性能。
2.2 從 JavaScript 調(diào)用 Unity 腳本函數(shù)
有時需要從瀏覽器的 JavaScript 向 Unity 腳本發(fā)送一些數(shù)據(jù)或通知。建議的做法是調(diào)用內(nèi)容中的游戲?qū)ο笊系姆椒?。如果要從嵌入在項目中?JavaScript 插件執(zhí)行調(diào)用,可使用以下代碼:
unityInstance.SendMessage(objectName, methodName, value)
其中,objectName是場景中的對象名稱;methodName 是當前附加到該對象的腳本中的方法名稱;value 可以是字符串、數(shù)字,也可為空。例如:
unityInstance.SendMessage('MyGameObject', 'MyFunction') unityInstance.SendMessage('MyGameObject', 'MyFunction', 5) unityInstance.SendMessage('MyGameObject', 'MyFunction', 'MyString')
如果您計劃從嵌入頁面的全局范圍中調(diào)用內(nèi)部 JavaScript 函數(shù),應始終假設該頁面上嵌入了多個構建,因此應顯式指定要引用的構建。例如,如果內(nèi)容已被實例化為:
var unityInstance = UnityLoader.instantiate("unityContainer", "Build/build.json", {onProgress: UnityProgress})
則可以使用 unityInstance.SendMessage() 向構建發(fā)送消息,或使用 unityInstance.Module 訪問構建 Module 對象。
2.3 WebGL 性能注意事項
2.3.1可在 WebGL 上期待什么樣的性能?
通常,您獲得的性能應該接近于 GPU 上的原生應用程序,這是因為 WebGL圖形 API 使用 GPU 進行硬件加速渲染。將 WebGL API 調(diào)用和著色器轉換為操作系統(tǒng)圖形 API(通常是 Windows 上的DirectX,或者是 Mac或 Linux上的OpenGL)會有少量開銷。
在 CPU 上,Emscripten會將您的代碼轉換為 WebAssembly,因此性能取決于 Web 瀏覽器。有關更多信息,請參閱 Unity 博客文章 WebAssembly 加載時間和性能 (WebAssembly Load Times and Performance)。
JavaScript 語言不支持多線程和 SIMD。受益于這些功能的任何代碼可能比其他代碼都要慢。無法在腳本中為 WebGL 編寫線程代碼和 SIMD 代碼,但有些引擎部分通常為多線程或經(jīng)過 SIMD 優(yōu)化,因此在 WebGL 上的性能會降低。
2.3.2 影響性能的 WebGL 特有設置
為獲得最佳性能,請在 Build Player 對話框中將優(yōu)化級別設置為 Fastest,并在 WebGL 的 Player 設置中將 Exception support 設置為 None。
2.3.3 WebGL 性能分析
WebGL 支持 Unity 性能分析器。請參閱 性能分析器 文檔以了解如何設置性能分析器。
2.3.4 后臺標簽中的 WebGL 內(nèi)容
如果在 WebGL 平臺的 Player 設置中啟用了 Run in background,或者如果啟用了 Application.runInBackground,您的內(nèi)容將在畫布或瀏覽器窗口失去焦點時繼續(xù)運行。
但是,某些瀏覽器可能會限制在后臺標簽頁中運行的內(nèi)容。如果包含該內(nèi)容的標簽頁不可見,在大多數(shù)瀏覽器中,您的內(nèi)容每秒才會更新一次。請注意,這將導致 Time.time 比平常采用默認設置時更慢,因為 Time.maximumDeltaTime 的默認值小于一秒。
2.3.5 限制 WebGL 性能
在某些情況下,可能希望以較低的幀率運行 WebGL 內(nèi)容,以降低 CPU 使用率。與其他平臺一樣,可使用 Application.targetFrameRate API 來實現(xiàn)此目的。
如果不想限制性能,請將此 API 設置為默認值 –1,而不是較高的值。如此,瀏覽器便可調(diào)整幀率以便在瀏覽器的渲染循環(huán)中實現(xiàn)最平滑的動畫,獲得的效果可能好于 Unity 嘗試執(zhí)行自身的主循環(huán)時序來匹配目標幀率。
3. 如何在vue中使用unity3D和webGL
3.1 新建一個掛載unity3d加載器的vue組件
新建一個一個unity3d加載器的vue組件顧名思義就是為了引入unity3d的加載器來加載。
<template> ?? ?<div class="webgl-content"> ?? ??? ?<div ?? ??? ??? ?id="unity-container" ?? ??? ??? ?:style="{ ?? ??? ??? ??? ?width: width + 'px', ?? ??? ??? ??? ?height: height + 'px' ?? ??? ??? ?}" ?? ??? ?></div> ?? ?</div> </template>
<script> import Vue from 'vue' export default { ?? ?name: 'vue-unity-webgl', ?? ?props: ['width', 'height', 'config', 'unityLoader', 'onProgress'], ?? ?data() { ?? ??? ?return { ?? ??? ??? ?instance: null, ?? ??? ??? ?loaded: false ?? ??? ?} ?? ?}, ?? ?beforeMount() { ?? ??? ?if (!this.eventBus) { ?? ??? ??? ?this.eventBus = new Vue({ ?? ??? ??? ??? ?data: { ?? ??? ??? ??? ??? ?ready: false, ?? ??? ??? ??? ??? ?load: false ?? ??? ??? ??? ?} ?? ??? ??? ?}) ?? ??? ?} ?? ??? ?if (typeof UnityLoader === 'undefined' && !this.eventBus.load) { ?? ??? ??? ?const script = document.createElement('script') ?? ??? ??? ?script.setAttribute('id', 'vue-unity-webgl-loader') ?? ??? ??? ?script.setAttribute('src', this.unityLoader) ?? ??? ??? ?script.setAttribute('async', '') ?? ??? ??? ?script.setAttribute('defer', '') ?? ??? ??? ?document.body.appendChild(script) ?? ??? ??? ?script.addEventListener('load', () => { ?? ??? ??? ??? ?this.eventBus.ready = true ?? ??? ??? ??? ?this.eventBus.$emit('onload') ?? ??? ??? ?}) ?? ??? ?} else { ?? ??? ??? ?this.eventBus.ready = true ?? ??? ?} ?? ??? ?this.eventBus.load = true ?? ?}, ?? ?mounted() { ?? ??? ?const instantiate = () => { ?? ??? ??? ?if (typeof UnityLoader === 'undefined') { ?? ??? ??? ??? ?return Promise.reject('UnityLoader 未定義') ?? ??? ??? ?} ?? ??? ??? ?if (!this.config) { ?? ??? ??? ??? ?return Promise.reject('config 未定義配置') ?? ??? ??? ?} ?? ??? ??? ?let params = {} ?? ??? ??? ?params.onProgress = (instance, progress) => { ?? ??? ??? ??? ?this.onProgress && this.onProgress(instance, progress) ?? ??? ??? ??? ?this.loaded = progress === 1 ?? ??? ??? ?} ?? ??? ??? ?if (this.module) { ?? ??? ??? ??? ?params.Module = this.module ?? ??? ??? ?} ?? ??? ??? ?this.instance = UnityLoader.instantiate('unity-container', this.config, params) ?? ??? ?} ?? ??? ?if (this.eventBus.ready) { ?? ??? ??? ?instantiate() ?? ??? ?} else { ?? ??? ??? ?this.eventBus.$on('onload', () => { ?? ??? ??? ??? ?instantiate() ?? ??? ??? ??? ?this.$emit('onload') ?? ??? ??? ?}) ?? ??? ?} ?? ?}, ?? ?methods: { ?? ??? ?message(object, method, params) { ?? ??? ??? ?if (params === null) { ?? ??? ??? ??? ?params = '' ?? ??? ??? ?} ?? ??? ??? ?if (this.instance !== null) { ?? ??? ??? ??? ?this.instance.SendMessage(object, method, params) ?? ??? ??? ?} else { ?? ??? ??? ??? ?return Promise.reject('vue-unity-webgl: 你給 Unity 發(fā)送的信息, 沒有被接收到') ?? ??? ??? ?} ?? ??? ?} ?? ?} } </script>
<style lang="scss" scoped> .webgl-content { ?? ?border-radius: 5px; ?? ?text-align: center; } #unity-container { ?? ?display: inline-block; ?? ?border-radius: 5px; } </style>
3.2 使用新建的vue-unity-webgl組件
<template> ?? ?<div id="webgl-box-warpper" v-loading="is_loading"> ?? ??? ?<vue-unity-webgl ?? ??? ??? ?v-if="is_show_webgl" ?? ??? ??? ?ref="vueUnityWebgl" ?? ??? ??? ?:config="webglConfig" ?? ??? ??? ?:unity-loader="webglUnityLoader" ?? ??? ??? ?:width="webglWidth" ?? ??? ??? ?:height="webglHeight" ?? ??? ??? ?:on-progress="listenWebglProgress" ?? ??? ?></vue-unity-webgl> ?? ?</div> </template>
<script> import VueUnityWebgl from '@/components/vue-unity-webgl' export default { ?? ?components: { ?? ??? ?VueUnityWebgl ?? ?}, ?? ?data() { ?? ??? ?return { ?? ??? ??? ?is_loading: false, ?? ??? ??? ?is_show_webgl: true, ?? ??? ??? ?webglConfig: '/Scenes1/Build/Scenes1.json', ?? ??? ??? ?webglUnityLoader: '/Scenes1/Build/UnityLoader.js' ?? ??? ??? ?webglWith: 1000, ?? ??? ??? ?webglHeight: 600 ?? ??? ?} ?? ?}, ?? ?created() { ?? ??? ?window.toVueWebgl = (action) => { ?? ??? ??? ?action && this.sendWebglMessage('{}', '第二次發(fā)送JSON數(shù)據(jù)') ?? ??? ?} ?? ?}, ?? ?mounted() { ?? ??? ?window.ReportReady = () => { ?? ??? ??? ?this.sendWebglMessage('1', '第一次發(fā)送內(nèi)容標識') ?? ??? ?} ?? ?}, ?? ?methods: { ?? ??? ?listenWebglProgress(instance, progress) { ?? ??? ??? ?this.is_loading = true ?? ??? ??? ?if (progress === 1) { ?? ??? ??? ??? ?this.is_loading = false ?? ??? ??? ?} ?? ??? ?}, ?? ??? ?sendWebglMessage(message, info) { ?? ??? ??? ?console.log(info) ?? ??? ??? ?this.$refs.vueUnityWebgl.message('JsTalker', 'toUnityWebgl', message) ?? ??? ?} ?? ?} } </script>
4. 演示效果
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue3+element-plus props中的變量使用 v-model 報錯及解決方案
這篇文章主要介紹了vue3+element-plus props中的變量使用 v-model 報錯及解決方案,prop 是單向數(shù)據(jù)流,這里只能用:model-value,不能用v-model,本文給大家介紹的非常詳細,需要的朋友可以參考下2023-10-10