对于前端对接unity我是从事前端来都没有接触过的,所以是我的知识盲区。所以只能不断的百度和谷歌去找解决方案。有文章不错,有文章写得模棱两可。真正做起来的时候,即使有部分文章可以,但该踩的坑那是一个不漏的踩上了,哈哈。因为自己曾经踩进去,写这篇文章,就是希望大家能在我踩的坑上,更加顺利的和unity进行对接。
废话不多说了,入正题吧。
我用的是iframe做的开发,所以解决方案都是iframe的。如你要的是vue-unity-webgl可以不往下看,转移下一篇文章
首先是要获取unity的实例,如图,先找到unity打包的实例对象:
我这边unity的实例是unityInstance,那么怎么在页面中iframe调用到这个对象呢。
这儿必须说这个坑,我明明写对了调用,前两次因为缓存。所以没成功,如果你们也这样,请刷新浏览器,清一遍缓存,重启一遍。保证页面没缓存。引入如下(注意看下面的注释,html和js我写一起了,懒得分开了):
//html如上,写好ref="iframe",然后在script标签,iframe加载完后,写点击事件,打印这个对象。
addNode() { //点击事件
// console.log('当前unity对象', this.$refs.iframe.contentWindow.unityInstance)
this.$refs.iframe.contentWindow.unityInstance.SendMessage('WebInvoker', 'Unity_InsertNaviPoint', this.nodeList.length)
},
注意,一定是this.$refs.iframe.contentWindow去找unityInstance,因为父页面调用iframe页面的对象就是用这条方法
打印到了对象就可以开始发命令啦。相信你也看到打印下一行啦。那就是发送命令给unity的。
this.$refs.iframe.contentWindow.unityInstance.SendMessage('WebInvoker', 'Unity_InsertNaviPoint', this.nodeList.length)
第一个参数是unity定义的对象,每个unity工程师喜欢的名字不一样。根据unity工程师给的名字即可,第二个参数是调用unity的哪个方法,比如我这儿就是调用新增节点的命令,第三个就是unity接收的参数。
ok,学会发送,那就到了学会接收unity传过来的数据了。
在这个博客第一张图可以看见在实例unityInstance前面有个对象UnityToJs,没错,这个就是unity向前端传数据的对象
首先回到unity里面的index页面,看对象,如图:
内容如下图:
var UnityToJs = {
///
/// JS的监听方法,
/// 点击 xxxx 时,回传默认值。
JS_OnReceiveView: function (fovMin, fovMax, angleMin, angleMax) {
// console.log(fovMin, fovMax, angleMin, angleMax);
window.top.dispatchEvent(new CustomEvent('getFovDef',{detail:{'fovMin':fovMin, 'fovMax':fovMax, 'angleMin':angleMin,'angleMax': angleMax}}))//自定义事件,然后获取相应的数据
}
}
JS_OnReceiveView: function (fovMin, fovMax, angleMin, angleMax) {
// console.log(fovMin, fovMax, angleMin, angleMax);
}是unity返回的数据,前端要在里面写方法,传递出去,然后获取数据。派发的事件我是参照某个哥们博客的,最底下会放下他的链接。
window.top.dispatchEvent(new CustomEvent('getFovDef',{detail:{'fovMin':fovMin, 'fovMax':fovMax, 'angleMin':angleMin,'angleMax': angleMax}}))
将参数放在detail里面。
ok,事件派出去了,那就到接收了,在相应的页面进行接收,在用到这个数据的页面的mounted里面写上如下代码:
mounted() {
// 恢复默认设置
window.addEventListener('getFovDef', this.unityWatch)
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('getFov', this.unityWatch)
})
},
methods: {
// 恢复默认时,unity回传的
unityWatch(obj) {
const eachObj = obj.detail // 获取当前回来的数据
this.fovValue = [eachObj.fovMin, eachObj.fovMax]
this.fovMin = eachObj.fovMin
this.fovMax = eachObj.fovMax
this.angleMin = eachObj.angleMin
this.angleMax = eachObj.angleMax
},
}
这儿有个要注意的地方,加监听事件记得要移除,还有!!!!请复制粘贴我上面的hook:beforeDestroy,别问我为啥提醒,因为天杀的,我去百度看dispatchEvent时复制粘贴了beforeDestroy,结果那个博主拼错字母!!!导致我后期一直报下面这个错误:
一直说找不到实例对象。完全就是因为切换页面的时候事件没有销毁的原因!!!!!天知道这个坑挖得多大。
unity的发送和接收已经完成,那么unity想自动获取我们的数据呢,怎么做到呢?在unity下面的index的UnityToJs找到需要接收前端数据的函数对象,如下:
///
///Unity 向 Web前端 获取 场景数据。
///如果请求数据尚未返回,请 Web前端 在数据返回来之后,主动调用
///unityInstance.SendMessage("WebInvoker","Unity_LoadScene",data);
///将数据传入Unity
///
JS_GetSceneData:function(){
return window.parent.getSenceData //前端给unity的数据
},
window.parent.getSenceData是前端定义的对象。
在需要返回对象给unity的页面的mounted里面写如下内容:
mounted() {
window.getSenceData = this.getSenceData()// 获取当前场景给unity
},
在方法里面写入这个函数内容,如下:
methods: {
getSenceData() {
if (this.sceneData?.navigation?.autoNavi === true) {
this.sceneData.navigation.autoNavi = false
}
return JSON.stringify(this.sceneData) //数据返回给unity,先转json字符串
}
}
我使用是一进来。在created里面请求了接口获取了数据,并将要给unity的内容赋值到this.sceneData里面。
这样就实现了unity主动从前端获取数据。
以上就是我写得很详细的unity和前端的对接需要用到的方式。挖的坑埋了自己,然后又跳出来。终是辛苦了。
参考的链接是这个哥们的https://blog.csdn.net/weixin_44957482/article/details/114658245https://blog.csdn.net/weixin_44957482/article/details/114658245
个人理解他的觉得不清晰,但参照这个哥们的链接,磕磕碰碰找到了自己的解决方案。还是很感谢这个哥们。
呜呼~搞定这个问题,我的发际线又上移啦。小秃头即将名副其实。下一篇,教你怎么截图unity的canvas并生成图片传给后台。