├── Build ├── UnityLoader.js ├── example.data.unityweb ├── example.json ├── example.wasm.code.unityweb └── example.wasm.framework.unityweb ├── LICENSE.md ├── README.md ├── assets ├── css │ ├── reset.css │ └── style.css └── images │ ├── readme-demo.gif │ ├── readme-folder.png │ └── readme-template.png ├── index.html ├── responsive-template-2020 ├── MyLoader.js ├── assets │ └── css │ │ ├── reset.css │ │ └── style.css ├── index.html └── thumbnail.png └── responsive-template ├── assets └── css │ ├── reset.css │ └── style.css ├── index.html └── thumbnail.png /Build/UnityLoader.js: -------------------------------------------------------------------------------- 1 | var UnityLoader=UnityLoader||{Compression:{identity:{require:function(){return{}},decompress:function(e){return e}},gzip:{require:function(e){var t={"inflate.js":function(e,t,r){"use strict";function n(e){if(!(this instanceof n))return new n(e);this.options=s.assign({chunkSize:16384,windowBits:0,to:""},e||{});var t=this.options;t.raw&&t.windowBits>=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0===(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new c,this.strm.avail_out=0;var r=i.inflateInit2(this.strm,t.windowBits);if(r!==l.Z_OK)throw new Error(u[r]);this.header=new f,i.inflateGetHeader(this.strm,this.header)}function o(e,t){var r=new n(t);if(r.push(e,!0),r.err)throw r.msg||u[r.err];return r.result}function a(e,t){return t=t||{},t.raw=!0,o(e,t)}var i=e("./zlib/inflate"),s=e("./utils/common"),d=e("./utils/strings"),l=e("./zlib/constants"),u=e("./zlib/messages"),c=e("./zlib/zstream"),f=e("./zlib/gzheader"),h=Object.prototype.toString;n.prototype.push=function(e,t){var r,n,o,a,u,c,f=this.strm,p=this.options.chunkSize,w=this.options.dictionary,m=!1;if(this.ended)return!1;n=t===~~t?t:t===!0?l.Z_FINISH:l.Z_NO_FLUSH,"string"==typeof e?f.input=d.binstring2buf(e):"[object ArrayBuffer]"===h.call(e)?f.input=new Uint8Array(e):f.input=e,f.next_in=0,f.avail_in=f.input.length;do{if(0===f.avail_out&&(f.output=new s.Buf8(p),f.next_out=0,f.avail_out=p),r=i.inflate(f,l.Z_NO_FLUSH),r===l.Z_NEED_DICT&&w&&(c="string"==typeof w?d.string2buf(w):"[object ArrayBuffer]"===h.call(w)?new Uint8Array(w):w,r=i.inflateSetDictionary(this.strm,c)),r===l.Z_BUF_ERROR&&m===!0&&(r=l.Z_OK,m=!1),r!==l.Z_STREAM_END&&r!==l.Z_OK)return this.onEnd(r),this.ended=!0,!1;f.next_out&&(0!==f.avail_out&&r!==l.Z_STREAM_END&&(0!==f.avail_in||n!==l.Z_FINISH&&n!==l.Z_SYNC_FLUSH)||("string"===this.options.to?(o=d.utf8border(f.output,f.next_out),a=f.next_out-o,u=d.buf2string(f.output,o),f.next_out=a,f.avail_out=p-a,a&&s.arraySet(f.output,f.output,o,a,0),this.onData(u)):this.onData(s.shrinkBuf(f.output,f.next_out)))),0===f.avail_in&&0===f.avail_out&&(m=!0)}while((f.avail_in>0||0===f.avail_out)&&r!==l.Z_STREAM_END);return r===l.Z_STREAM_END&&(n=l.Z_FINISH),n===l.Z_FINISH?(r=i.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===l.Z_OK):n!==l.Z_SYNC_FLUSH||(this.onEnd(l.Z_OK),f.avail_out=0,!0)},n.prototype.onData=function(e){this.chunks.push(e)},n.prototype.onEnd=function(e){e===l.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},r.Inflate=n,r.inflate=o,r.inflateRaw=a,r.ungzip=o},"utils/common.js":function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;r.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var r=t.shift();if(r){if("object"!=typeof r)throw new TypeError(r+"must be non-object");for(var n in r)r.hasOwnProperty(n)&&(e[n]=r[n])}}return e},r.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var o={arraySet:function(e,t,r,n,o){if(t.subarray&&e.subarray)return void e.set(t.subarray(r,r+n),o);for(var a=0;a=252?6:d>=248?5:d>=240?4:d>=224?3:d>=192?2:1;s[254]=s[254]=1,r.string2buf=function(e){var t,r,n,a,i,s=e.length,d=0;for(a=0;a>>6,t[i++]=128|63&r):r<65536?(t[i++]=224|r>>>12,t[i++]=128|r>>>6&63,t[i++]=128|63&r):(t[i++]=240|r>>>18,t[i++]=128|r>>>12&63,t[i++]=128|r>>>6&63,t[i++]=128|63&r);return t},r.buf2binstring=function(e){return n(e,e.length)},r.binstring2buf=function(e){for(var t=new o.Buf8(e.length),r=0,n=t.length;r4)l[o++]=65533,r+=i-1;else{for(a&=2===i?31:3===i?15:7;i>1&&r1?l[o++]=65533:a<65536?l[o++]=a:(a-=65536,l[o++]=55296|a>>10&1023,l[o++]=56320|1023&a)}return n(l,o)},r.utf8border=function(e,t){var r;for(t=t||e.length,t>e.length&&(t=e.length),r=t-1;r>=0&&128===(192&e[r]);)r--;return r<0?t:0===r?t:r+s[e[r]]>t?r:t}},"zlib/inflate.js":function(e,t,r){"use strict";function n(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function o(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new y.Buf16(320),this.work=new y.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=P,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new y.Buf32(we),t.distcode=t.distdyn=new y.Buf32(me),t.sane=1,t.back=-1,O):R}function i(e){var t;return e&&e.state?(t=e.state,t.wsize=0,t.whave=0,t.wnext=0,a(e)):R}function s(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=(t>>4)+1,t<48&&(t&=15)),t&&(t<8||t>15)?R:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=r,n.wbits=t,i(e))):R}function d(e,t){var r,n;return e?(n=new o,e.state=n,n.window=null,r=s(e,t),r!==O&&(e.state=null),r):R}function l(e){return d(e,ye)}function u(e){if(ge){var t;for(m=new y.Buf32(512),b=new y.Buf32(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(U(E,e.lens,0,288,m,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;U(k,e.lens,0,32,b,0,e.work,{bits:5}),ge=!1}e.lencode=m,e.lenbits=9,e.distcode=b,e.distbits=5}function c(e,t,r,n){var o,a=e.state;return null===a.window&&(a.wsize=1<=a.wsize?(y.arraySet(a.window,t,r-a.wsize,a.wsize,0),a.wnext=0,a.whave=a.wsize):(o=a.wsize-a.wnext,o>n&&(o=n),y.arraySet(a.window,t,r-n,o,a.wnext),n-=o,n?(y.arraySet(a.window,t,r-n,n,0),a.wnext=n,a.whave=a.wsize):(a.wnext+=o,a.wnext===a.wsize&&(a.wnext=0),a.whave>>8&255,r.check=v(r.check,Le,2,0),f=0,h=0,r.mode=T;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&f)<<8)+(f>>8))%31){e.msg="incorrect header check",r.mode=fe;break}if((15&f)!==S){e.msg="unknown compression method",r.mode=fe;break}if(f>>>=4,h-=4,Ue=(15&f)+8,0===r.wbits)r.wbits=Ue;else if(Ue>r.wbits){e.msg="invalid window size",r.mode=fe;break}r.dmax=1<>8&1),512&r.flags&&(Le[0]=255&f,Le[1]=f>>>8&255,r.check=v(r.check,Le,2,0)),f=0,h=0,r.mode=D;case D:for(;h<32;){if(0===d)break e;d--,f+=o[i++]<>>8&255,Le[2]=f>>>16&255,Le[3]=f>>>24&255,r.check=v(r.check,Le,4,0)),f=0,h=0,r.mode=F;case F:for(;h<16;){if(0===d)break e;d--,f+=o[i++]<>8),512&r.flags&&(Le[0]=255&f,Le[1]=f>>>8&255,r.check=v(r.check,Le,2,0)),f=0,h=0,r.mode=q;case q:if(1024&r.flags){for(;h<16;){if(0===d)break e;d--,f+=o[i++]<>>8&255,r.check=v(r.check,Le,2,0)),f=0,h=0}else r.head&&(r.head.extra=null);r.mode=V;case V:if(1024&r.flags&&(m=r.length,m>d&&(m=d),m&&(r.head&&(Ue=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),y.arraySet(r.head.extra,o,i,m,Ue)),512&r.flags&&(r.check=v(r.check,o,m,i)),d-=m,i+=m,r.length-=m),r.length))break e;r.length=0,r.mode=z;case z:if(2048&r.flags){if(0===d)break e;m=0;do Ue=o[i+m++],r.head&&Ue&&r.length<65536&&(r.head.name+=String.fromCharCode(Ue));while(Ue&&m>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=j;break;case G:for(;h<32;){if(0===d)break e;d--,f+=o[i++]<>>=7&h,h-=7&h,r.mode=le;break}for(;h<3;){if(0===d)break e;d--,f+=o[i++]<>>=1,h-=1,3&f){case 0:r.mode=K;break;case 1:if(u(r),r.mode=re,t===W){f>>>=2,h-=2;break e}break;case 2:r.mode=$;break;case 3:e.msg="invalid block type",r.mode=fe}f>>>=2,h-=2;break;case K:for(f>>>=7&h,h-=7&h;h<32;){if(0===d)break e;d--,f+=o[i++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=fe;break}if(r.length=65535&f,f=0,h=0,r.mode=Q,t===W)break e;case Q:r.mode=_;case _:if(m=r.length){if(m>d&&(m=d),m>l&&(m=l),0===m)break e;y.arraySet(a,o,i,m,s),d-=m,i+=m,l-=m,s+=m,r.length-=m;break}r.mode=j;break;case $:for(;h<14;){if(0===d)break e;d--,f+=o[i++]<>>=5,h-=5,r.ndist=(31&f)+1,f>>>=5,h-=5,r.ncode=(15&f)+4,f>>>=4,h-=4,r.nlen>286||r.ndist>30){e.msg="too many length or distance symbols",r.mode=fe;break}r.have=0,r.mode=ee;case ee:for(;r.have>>=3,h-=3}for(;r.have<19;)r.lens[We[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,Ee={bits:r.lenbits},xe=U(x,r.lens,0,19,r.lencode,0,r.work,Ee),r.lenbits=Ee.bits,xe){e.msg="invalid code lengths set",r.mode=fe;break}r.have=0,r.mode=te;case te:for(;r.have>>24,be=Be>>>16&255,ye=65535&Be,!(me<=h);){if(0===d)break e;d--,f+=o[i++]<>>=me,h-=me,r.lens[r.have++]=ye;else{if(16===ye){for(ke=me+2;h>>=me,h-=me,0===r.have){e.msg="invalid bit length repeat",r.mode=fe;break}Ue=r.lens[r.have-1],m=3+(3&f),f>>>=2,h-=2}else if(17===ye){for(ke=me+3;h>>=me,h-=me,Ue=0,m=3+(7&f),f>>>=3,h-=3}else{for(ke=me+7;h>>=me,h-=me,Ue=0,m=11+(127&f),f>>>=7,h-=7}if(r.have+m>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=fe;break}for(;m--;)r.lens[r.have++]=Ue}}if(r.mode===fe)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=fe;break}if(r.lenbits=9,Ee={bits:r.lenbits},xe=U(E,r.lens,0,r.nlen,r.lencode,0,r.work,Ee),r.lenbits=Ee.bits,xe){e.msg="invalid literal/lengths set",r.mode=fe;break}if(r.distbits=6,r.distcode=r.distdyn,Ee={bits:r.distbits},xe=U(k,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,Ee),r.distbits=Ee.bits,xe){e.msg="invalid distances set",r.mode=fe;break}if(r.mode=re,t===W)break e;case re:r.mode=ne;case ne:if(d>=6&&l>=258){e.next_out=s,e.avail_out=l,e.next_in=i,e.avail_in=d,r.hold=f,r.bits=h,A(e,w),s=e.next_out,a=e.output,l=e.avail_out,i=e.next_in,o=e.input,d=e.avail_in,f=r.hold,h=r.bits,r.mode===j&&(r.back=-1);break}for(r.back=0;Be=r.lencode[f&(1<>>24,be=Be>>>16&255,ye=65535&Be,!(me<=h);){if(0===d)break e;d--,f+=o[i++]<>ge)],me=Be>>>24,be=Be>>>16&255,ye=65535&Be,!(ge+me<=h);){if(0===d)break e;d--,f+=o[i++]<>>=ge,h-=ge,r.back+=ge}if(f>>>=me,h-=me,r.back+=me,r.length=ye,0===be){r.mode=de;break}if(32&be){r.back=-1,r.mode=j;break}if(64&be){e.msg="invalid literal/length code",r.mode=fe;break}r.extra=15&be,r.mode=oe;case oe:if(r.extra){for(ke=r.extra;h>>=r.extra,h-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=ae;case ae:for(;Be=r.distcode[f&(1<>>24,be=Be>>>16&255,ye=65535&Be,!(me<=h);){if(0===d)break e;d--,f+=o[i++]<>ge)],me=Be>>>24,be=Be>>>16&255,ye=65535&Be,!(ge+me<=h);){if(0===d)break e;d--,f+=o[i++]<>>=ge,h-=ge,r.back+=ge}if(f>>>=me,h-=me,r.back+=me,64&be){e.msg="invalid distance code",r.mode=fe;break}r.offset=ye,r.extra=15&be,r.mode=ie;case ie:if(r.extra){for(ke=r.extra;h>>=r.extra,h-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=fe;break}r.mode=se;case se:if(0===l)break e;if(m=w-l,r.offset>m){if(m=r.offset-m,m>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=fe;break}m>r.wnext?(m-=r.wnext,b=r.wsize-m):b=r.wnext-m,m>r.length&&(m=r.length),we=r.window}else we=a,b=s-r.offset,m=r.length;m>l&&(m=l),l-=m,r.length-=m;do a[s++]=we[b++];while(--m);0===r.length&&(r.mode=ne);break;case de:if(0===l)break e;a[s++]=r.length,l--,r.mode=ne;break;case le:if(r.wrap){for(;h<32;){if(0===d)break e;d--,f|=o[i++]<>>16&65535|0,i=0;0!==r;){i=r>2e3?2e3:r,r-=i;do o=o+t[n++]|0,a=a+o|0;while(--i);o%=65521,a%=65521}return o|a<<16|0}t.exports=n},"zlib/crc32.js":function(e,t,r){"use strict";function n(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}function o(e,t,r,n){var o=a,i=n+r;e^=-1;for(var s=n;s>>8^o[255&(e^t[s])];return e^-1}var a=n();t.exports=o},"zlib/inffast.js":function(e,t,r){"use strict";var n=30,o=12;t.exports=function(e,t){var r,a,i,s,d,l,u,c,f,h,p,w,m,b,y,g,v,A,U,x,E,k,B,L,W;r=e.state,a=e.next_in,L=e.input,i=a+(e.avail_in-5),s=e.next_out,W=e.output,d=s-(t-e.avail_out),l=s+(e.avail_out-257),u=r.dmax,c=r.wsize,f=r.whave,h=r.wnext,p=r.window,w=r.hold,m=r.bits,b=r.lencode,y=r.distcode,g=(1<>>24,w>>>=U,m-=U,U=A>>>16&255,0===U)W[s++]=65535&A;else{if(!(16&U)){if(0===(64&U)){A=b[(65535&A)+(w&(1<>>=U,m-=U),m<15&&(w+=L[a++]<>>24,w>>>=U,m-=U,U=A>>>16&255,!(16&U)){if(0===(64&U)){A=y[(65535&A)+(w&(1<u){e.msg="invalid distance too far back",r.mode=n;break e}if(w>>>=U,m-=U,U=s-d,E>U){if(U=E-U,U>f&&r.sane){e.msg="invalid distance too far back",r.mode=n;break e}if(k=0,B=p,0===h){if(k+=c-U,U2;)W[s++]=B[k++],W[s++]=B[k++],W[s++]=B[k++],x-=3;x&&(W[s++]=B[k++],x>1&&(W[s++]=B[k++]))}else{k=s-E;do W[s++]=W[k++],W[s++]=W[k++],W[s++]=W[k++],x-=3;while(x>2);x&&(W[s++]=W[k++],x>1&&(W[s++]=W[k++]))}break}}break}}while(a>3,a-=x,m-=x<<3,w&=(1<=1&&0===q[R];R--);if(C>R&&(C=R),0===R)return w[m++]=20971520,w[m++]=20971520,y.bits=1,0;for(N=1;N0&&(e===s||1!==R))return-1;for(V[1]=0,O=1;Oa||e===l&&P>i)return 1;for(;;){k=O-I,b[M]E?(B=z[Z+b[M]],L=D[F+b[M]]):(B=96,L=0),g=1<>I)+v]=k<<24|B<<16|L|0;while(0!==v);for(g=1<>=1;if(0!==g?(T&=g-1,T+=g):T=0,M++,0===--q[O]){if(O===R)break;O=t[r+b[M]]}if(O>C&&(T&U)!==A){for(0===I&&(I=C),x+=N,H=O-I,S=1<a||e===l&&P>i)return 1;A=T&U,w[A]=C<<24|H<<16|x-m|0}}return 0!==T&&(w[x+T]=O-I<<24|64<<16|0),y.bits=C,0}}};for(var r in t)t[r].folder=r.substring(0,r.lastIndexOf("/")+1);var n=function(e){var r=[];return e=e.split("/").every(function(e){return".."==e?r.pop():"."==e||""==e||r.push(e)})?r.join("/"):null,e?t[e]||t[e+".js"]||t[e+"/index.js"]:null},o=function(e,t){return e?n(e.folder+"node_modules/"+t)||o(e.parent,t):null},a=function(e,t){var r=t.match(/^\//)?null:e?t.match(/^\.\.?\//)?n(e.folder+t):o(e,t):n(t);if(!r)throw"module not found: "+t;return r.exports||(r.parent=e,r(a.bind(null,r),r,r.exports={})),r.exports};return a(null,e)},decompress:function(e){this.exports||(this.exports=this.require("inflate.js"));try{return this.exports.inflate(e)}catch(e){}},hasUnityMarker:function(e){var t=10,r="UnityWeb Compressed Content (gzip)";if(t>e.length||31!=e[0]||139!=e[1])return!1;var n=e[3];if(4&n){if(t+2>e.length)return!1;if(t+=2+e[t]+(e[t+1]<<8),t>e.length)return!1}if(8&n){for(;te.length)return!1;t++}return 16&n&&String.fromCharCode.apply(null,e.subarray(t,t+r.length+1))==r+"\0"}},brotli:{require:function(e){var t={"decompress.js":function(e,t,r){t.exports=e("./dec/decode").BrotliDecompressBuffer},"dec/bit_reader.js":function(e,t,r){function n(e){this.buf_=new Uint8Array(a),this.input_=e,this.reset()}const o=4096,a=8224,i=8191,s=new Uint32Array([0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215]);n.READ_SIZE=o,n.IBUF_MASK=i,n.prototype.reset=function(){this.buf_ptr_=0,this.val_=0,this.pos_=0,this.bit_pos_=0,this.bit_end_pos_=0,this.eos_=0,this.readMoreInput();for(var e=0;e<4;e++)this.val_|=this.buf_[this.pos_]<<8*e,++this.pos_;return this.bit_end_pos_>0},n.prototype.readMoreInput=function(){if(!(this.bit_end_pos_>256))if(this.eos_){if(this.bit_pos_>this.bit_end_pos_)throw new Error("Unexpected end of input "+this.bit_pos_+" "+this.bit_end_pos_)}else{var e=this.buf_ptr_,t=this.input_.read(this.buf_,e,o);if(t<0)throw new Error("Unexpected end of input");if(t=8;)this.val_>>>=8,this.val_|=this.buf_[this.pos_&i]<<24,++this.pos_,this.bit_pos_=this.bit_pos_-8>>>0,this.bit_end_pos_=this.bit_end_pos_-8>>>0},n.prototype.readBits=function(e){32-this.bit_pos_>>this.bit_pos_&s[e];return this.bit_pos_+=e,t},t.exports=n},"dec/context.js":function(e,t,r){r.lookup=new Uint8Array([0,0,0,0,0,0,0,0,0,4,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12,16,12,12,20,12,16,24,28,12,12,32,12,36,12,44,44,44,44,44,44,44,44,44,44,32,32,24,40,28,12,12,48,52,52,52,48,52,52,52,48,52,52,52,52,52,48,52,52,52,52,52,48,52,52,52,52,52,24,12,28,12,12,12,56,60,60,60,56,60,60,60,56,60,60,60,60,60,56,60,60,60,60,60,56,60,60,60,60,60,24,12,28,12,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,56,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22,22,22,23,23,23,23,24,24,24,24,25,25,25,25,26,26,26,26,27,27,27,27,28,28,28,28,29,29,29,29,30,30,30,30,31,31,31,31,32,32,32,32,33,33,33,33,34,34,34,34,35,35,35,35,36,36,36,36,37,37,37,37,38,38,38,38,39,39,39,39,40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,44,44,44,44,45,45,45,45,46,46,46,46,47,47,47,47,48,48,48,48,49,49,49,49,50,50,50,50,51,51,51,51,52,52,52,52,53,53,53,53,54,54,54,54,55,55,55,55,56,56,56,56,57,57,57,57,58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,62,62,62,62,63,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]),r.lookupOffsets=new Uint16Array([1024,1536,1280,1536,0,256,768,512])},"dec/decode.js":function(e,t,r){function n(e){var t;return 0===e.readBits(1)?16:(t=e.readBits(3),t>0?17+t:(t=e.readBits(3),t>0?8+t:17))}function o(e){if(e.readBits(1)){var t=e.readBits(3);return 0===t?1:e.readBits(t)+(1<1&&0===i)throw new Error("Invalid size byte");o.meta_block_length|=i<<8*n}}else for(n=0;n4&&0===s)throw new Error("Invalid size nibble");o.meta_block_length|=s<<4*n}return++o.meta_block_length,o.input_end||o.is_metadata||(o.is_uncompressed=e.readBits(1)),o}function s(e,t,r){var n;return r.fillBitWindow(),t+=r.val_>>>r.bit_pos_&D,n=e[t].bits-T,n>0&&(r.bit_pos_+=T,t+=e[t].value,t+=r.val_>>>r.bit_pos_&(1<0;){var c,f=0;if(n.readMoreInput(),n.fillBitWindow(),f+=n.val_>>>n.bit_pos_&31,n.bit_pos_+=l[f].bits,c=255&l[f].value,c>c);else{var h,p,w=c-14,m=0;if(c===R&&(m=a),s!==m&&(i=0,s=m),h=i,i>0&&(i-=2,i<<=w),i+=n.readBits(w)+3,p=i-h,o+p>t)throw new Error("[ReadHuffmanCodeLengths] symbol + repeat_delta > num_symbols");for(var b=0;b0;++s){var b,y=V[s],g=0;n.fillBitWindow(),g+=n.val_>>>n.bit_pos_&15, 2 | n.bit_pos_+=m[g].bits,b=m[g].value,h[y]=b,0!==b&&(p-=32>>b,++w)}if(1!==w&&0!==p)throw new Error("[ReadHuffmanCode] invalid num_codes or space");d(h,e,i,n)}if(a=L(t,r,T,i,e),0===a)throw new Error("[ReadHuffmanCode] BuildHuffmanTable failed: ");return a}function u(e,t,r){var n,o;return n=s(e,t,r),o=O.kBlockLengthPrefixCode[n].nbits,O.kBlockLengthPrefixCode[n].offset+r.readBits(o)}function c(e,t,r){var n;return e>>5]),this.htrees=new Uint32Array(t)}function w(e,t){var r,n,a,i={num_htrees:null,context_map:null},d=0;t.readMoreInput();var u=i.num_htrees=o(t)+1,c=i.context_map=new Uint8Array(e);if(u<=1)return i;for(r=t.readBits(1),r&&(d=t.readBits(4)+1),n=[],a=0;a=e)throw new Error("[DecodeContextMap] i >= context_map_size");c[a]=0,++a}else c[a]=f-d,++a}return t.readBits(1)&&h(c,e),i}function m(e,t,r,n,o,a,i){var d,l=2*r,u=r,c=s(t,r*F,i);d=0===c?o[l+(1&a[u])]:1===c?o[l+(a[u]-1&1)]+1:c-2,d>=e&&(d-=e),n[r]=d,o[l+(1&a[u])]=d,++a[u]}function b(e,t,r,n,o,a){var i,s=o+1,d=r&o,l=a.pos_&E.IBUF_MASK;if(t<8||a.bit_pos_+(t<<3)0;)a.readMoreInput(),n[d++]=a.readBits(8),d===s&&(e.write(n,s),d=0);else{if(a.bit_end_pos_<32)throw new Error("[CopyUncompressedBlockToOutput] br.bit_end_pos_ < 32");for(;a.bit_pos_<32;)n[d]=a.val_>>>a.bit_pos_,a.bit_pos_+=8,++d,--t;if(i=a.bit_end_pos_-a.bit_pos_>>3,l+i>E.IBUF_MASK){for(var u=E.IBUF_MASK+1-l,c=0;c=s){e.write(n,s),d-=s;for(var c=0;c=s;){if(i=s-d,a.input_.read(n,d,i)t.buffer.length){var ve=new Uint8Array(x+re);ve.set(t.buffer),t.buffer=ve}if(L=ge.input_end,J=ge.is_uncompressed,ge.is_metadata)for(y(U);re>0;--re)U.readMoreInput(),U.readBits(8);else if(0!==re)if(J)U.bit_pos_=U.bit_pos_+7&-8,b(t,re,x,h,f,U),x+=re;else{for(r=0;r<3;++r)ae[r]=o(U)+1,ae[r]>=2&&(l(ae[r]+2,v,r*F,U),l(I,A,r*F,U),ne[r]=u(A,r*F,U),se[r]=1);for(U.readMoreInput(),j=U.readBits(2),X=z+(U.readBits(4)<0;){var xe,Ee,ke,Be,Le,We,Oe,Me,Ne,Re,Ce;for(U.readMoreInput(),0===ne[1]&&(m(ae[1],v,1,oe,ie,se,U),ne[1]=u(A,F,U),te=Z[1].htrees[oe[1]]),--ne[1],xe=s(Z[1].codes,te,U),Ee=xe>>6,Ee>=2?(Ee-=2,Oe=-1):Oe=0,ke=O.kInsertRangeLut[Ee]+(xe>>3&7),Be=O.kCopyRangeLut[Ee]+(7&xe),Le=O.kInsertLengthPrefixCode[ke].offset+U.readBits(O.kInsertLengthPrefixCode[ke].nbits),We=O.kCopyLengthPrefixCode[Be].offset+U.readBits(O.kCopyLengthPrefixCode[Be].nbits),q=h[x-1&f],V=h[x-2&f],Re=0;Re4?3:We-2),me=ue[we+Ne],Oe=s(Z[2].codes,Z[2].htrees[me],U),Oe>=X){var He,Ie,Se;Oe-=X,Ie=Oe&K,Oe>>=j,He=(Oe>>1)+1,Se=(2+(1&Oe)<R){if(!(We>=k.minDictionaryWordLength&&We<=k.maxDictionaryWordLength))throw new Error("Invalid backward reference. pos: "+x+" distance: "+Me+" len: "+We+" bytes left: "+re);var Se=k.offsetsByLength[We],Pe=Me-R-1,Te=k.sizeBitsByLength[We],De=(1<>Te;if(Se+=Fe*We,!(qe=g){t.write(h,d);for(var ze=0;ze0&&(T[3&D]=Me,++D),We>re)throw new Error("Invalid backward reference. pos: "+x+" distance: "+Me+" len: "+We+" bytes left: "+re);for(Re=0;Re>=1;return(e&r-1)+r}function a(e,t,r,o,a){do o-=r,e[t+o]=new n(a.bits,a.value);while(o>0)}function i(e,t,r){for(var n=1<0;--U[c])u=new n(255&c,65535&v[f++]),a(e,t+h,p,y,u),h=o(h,c);for(m=g-1,w=-1,c=r+1,p=2;c<=s;++c,p<<=1)for(;U[c]>0;--U[c])(h&m)!==w&&(t+=y,b=i(U,c,r),y=1<>r),p,y,u),h=o(h,c);return g}},"dec/prefix.js":function(e,t,r){function n(e,t){this.offset=e,this.nbits=t}r.kBlockLengthPrefixCode=[new n(1,2),new n(5,2),new n(9,2),new n(13,2),new n(17,3),new n(25,3),new n(33,3),new n(41,3),new n(49,4),new n(65,4),new n(81,4),new n(97,4),new n(113,5),new n(145,5),new n(177,5),new n(209,5),new n(241,6),new n(305,6),new n(369,7),new n(497,8),new n(753,9),new n(1265,10),new n(2289,11),new n(4337,12),new n(8433,13),new n(16625,24)],r.kInsertLengthPrefixCode=[new n(0,0),new n(1,0),new n(2,0),new n(3,0),new n(4,0),new n(5,0),new n(6,1),new n(8,1),new n(10,2),new n(14,2),new n(18,3),new n(26,3),new n(34,4),new n(50,4),new n(66,5),new n(98,5),new n(130,6),new n(194,7),new n(322,8),new n(578,9),new n(1090,10),new n(2114,12),new n(6210,14),new n(22594,24)],r.kCopyLengthPrefixCode=[new n(2,0),new n(3,0),new n(4,0),new n(5,0),new n(6,0),new n(7,0),new n(8,0),new n(9,0),new n(10,1),new n(12,1),new n(14,2),new n(18,2),new n(22,3),new n(30,3),new n(38,4),new n(54,4),new n(70,5),new n(102,5),new n(134,6),new n(198,7),new n(326,8),new n(582,9),new n(1094,10),new n(2118,24)],r.kInsertRangeLut=[0,0,8,8,0,16,8,16,16],r.kCopyRangeLut=[0,8,0,8,16,0,16,8,16]},"dec/streams.js":function(e,t,r){function n(e){this.buffer=e,this.pos=0}function o(e){this.buffer=e,this.pos=0}n.prototype.read=function(e,t,r){this.pos+r>this.buffer.length&&(r=this.buffer.length-this.pos);for(var n=0;nthis.buffer.length)throw new Error("Output buffer is not large enough");return this.buffer.set(e.subarray(0,t),this.pos),this.pos+=t,t},r.BrotliOutput=o},"dec/transform.js":function(e,t,r){function n(e,t,r){this.prefix=new Uint8Array(e.length),this.transform=t,this.suffix=new Uint8Array(r.length);for(var n=0;n=97&&e[t]<=122&&(e[t]^=32),1):e[t]<224?(e[t+1]^=32,2):(e[t+2]^=5,3)}var a=e("./dictionary");const i=0,s=1,d=2,l=3,u=4,c=5,f=6,h=7,p=8,w=9,m=10,b=11,y=12,g=13,v=14,A=15,U=16,x=17,E=18,k=20;var B=[new n("",i,""),new n("",i," "),new n(" ",i," "),new n("",y,""),new n("",m," "),new n("",i," the "),new n(" ",i,""),new n("s ",i," "),new n("",i," of "),new n("",m,""),new n("",i," and "),new n("",g,""),new n("",s,""),new n(", ",i," "),new n("",i,", "),new n(" ",m," "),new n("",i," in "),new n("",i," to "),new n("e ",i," "),new n("",i,'"'),new n("",i,"."),new n("",i,'">'),new n("",i,"\n"),new n("",l,""),new n("",i,"]"),new n("",i," for "),new n("",v,""),new n("",d,""),new n("",i," a "),new n("",i," that "),new n(" ",m,""),new n("",i,". "),new n(".",i,""),new n(" ",i,", "),new n("",A,""),new n("",i," with "),new n("",i,"'"),new n("",i," from "),new n("",i," by "),new n("",U,""),new n("",x,""),new n(" the ",i,""),new n("",u,""),new n("",i,". The "),new n("",b,""),new n("",i," on "),new n("",i," as "),new n("",i," is "),new n("",h,""),new n("",s,"ing "),new n("",i,"\n\t"),new n("",i,":"),new n(" ",i,". "),new n("",i,"ed "),new n("",k,""),new n("",E,""),new n("",f,""),new n("",i,"("),new n("",m,", "),new n("",p,""),new n("",i," at "),new n("",i,"ly "),new n(" the ",i," of "),new n("",c,""),new n("",w,""),new n(" ",m,", "),new n("",m,'"'),new n(".",i,"("),new n("",b," "),new n("",m,'">'),new n("",i,'="'),new n(" ",i,"."),new n(".com/",i,""),new n(" the ",i," of the "),new n("",m,"'"),new n("",i,". This "),new n("",i,","),new n(".",i," "),new n("",m,"("),new n("",m,"."),new n("",i," not "),new n(" ",i,'="'),new n("",i,"er "),new n(" ",b," "),new n("",i,"al "),new n(" ",b,""),new n("",i,"='"),new n("",b,'"'),new n("",m,". "),new n(" ",i,"("),new n("",i,"ful "),new n(" ",m,". "),new n("",i,"ive "),new n("",i,"less "),new n("",b,"'"),new n("",i,"est "),new n(" ",m,"."),new n("",b,'">'),new n(" ",i,"='"),new n("",m,","),new n("",i,"ize "),new n("",b,"."),new n("\xc2\xa0",i,""),new n(" ",i,","),new n("",m,'="'),new n("",b,'="'),new n("",i,"ous "),new n("",b,", "),new n("",m,"='"),new n(" ",m,","),new n(" ",b,'="'),new n(" ",b,", "),new n("",b,","),new n("",b,"("),new n("",b,". "),new n(" ",b,"."),new n("",b,"='"),new n(" ",b,". "),new n(" ",m,'="'),new n(" ",b,"='"),new n(" ",m,"='")];r.kTransforms=B,r.kNumTransforms=B.length,r.transformDictionaryWord=function(e,t,r,n,i){var s,d=B[i].prefix,l=B[i].suffix,u=B[i].transform,c=un&&(c=n);for(var p=0;p0;){var g=o(e,s);s+=g,n-=g}for(var v=0;v0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===e[t-2]?2:"="===e[t-1]?1:0}function o(e){return 3*e.length/4-n(e)}function a(e){var t,r,o,a,i,s,d=e.length;i=n(e),s=new c(3*d/4-i),o=i>0?d-4:d;var l=0;for(t=0,r=0;t>16&255,s[l++]=a>>8&255,s[l++]=255&a;return 2===i?(a=u[e.charCodeAt(t)]<<2|u[e.charCodeAt(t+1)]>>4,s[l++]=255&a):1===i&&(a=u[e.charCodeAt(t)]<<10|u[e.charCodeAt(t+1)]<<4|u[e.charCodeAt(t+2)]>>2,s[l++]=a>>8&255,s[l++]=255&a),s}function i(e){return l[e>>18&63]+l[e>>12&63]+l[e>>6&63]+l[63&e]}function s(e,t,r){for(var n,o=[],a=t;au?u:d+i));return 1===n?(t=e[r-1],o+=l[t>>2],o+=l[t<<4&63],o+="=="):2===n&&(t=(e[r-2]<<8)+e[r-1],o+=l[t>>10],o+=l[t>>4&63],o+=l[t<<2&63],o+="="),a.push(o),a.join("")}r.byteLength=o,r.toByteArray=a,r.fromByteArray=d;for(var l=[],u=[],c="undefined"!=typeof Uint8Array?Uint8Array:Array,f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",h=0,p=f.length;h>3);if(commentOffset=r+1+2+1+2+(o<<3)+7>>3,17==n||commentOffset>e.length)return!1;for(var a=n+(6+(o<<4)+(t.length-1<<6)<>>=8)if(e[i]!=(255&a))return!1;return String.fromCharCode.apply(null,e.subarray(commentOffset,commentOffset+t.length))==t}},decompress:function(e,t){var r=this.gzip.hasUnityMarker(e)?this.gzip:this.brotli.hasUnityMarker(e)?this.brotli:this.identity;if(this.serverSetupWarningEnabled&&r!=this.identity&&(console.log("You can reduce your startup time if you configure your web server to host .unityweb files using "+(r==this.gzip?"gzip":"brotli")+" compression."),this.serverSetupWarningEnabled=!1),"function"!=typeof t)return r.decompress(e);if(!r.worker){var n=URL.createObjectURL(new Blob(["this.require = ",r.require.toString(),"; this.decompress = ",r.decompress.toString(),"; this.onmessage = ",function(e){var t={id:e.data.id,decompressed:this.decompress(e.data.compressed)};postMessage(t,t.decompressed?[t.decompressed.buffer]:[])}.toString(),"; postMessage({ ready: true });"],{type:"text/javascript"}));r.worker=new Worker(n),r.worker.onmessage=function(e){return e.data.ready?void URL.revokeObjectURL(n):(this.callbacks[e.data.id](e.data.decompressed),void delete this.callbacks[e.data.id])},r.worker.callbacks={},r.worker.nextCallbackId=0}var o=r.worker.nextCallbackId++;r.worker.callbacks[o]=t,r.worker.postMessage({id:o,compressed:e},[e.buffer])},serverSetupWarningEnabled:!0},Cryptography:{crc32:function(e){var t=UnityLoader.Cryptography.crc32.module;if(!t){var r=new ArrayBuffer(16777216),n=function(e,t,r){"use asm";var n=new e.Uint8Array(r);var o=new e.Uint32Array(r);function a(e,t){e=e|0;t=t|0;var r=0;for(r=o[1024>>2]|0;t;e=e+1|0,t=t-1|0)r=o[(r&255^n[e])<<2>>2]^r>>>8^4278190080;o[1024>>2]=r}return{process:a}}({Uint8Array:Uint8Array,Uint32Array:Uint32Array},null,r);t=UnityLoader.Cryptography.crc32.module={buffer:r,HEAPU8:new Uint8Array(r),HEAPU32:new Uint32Array(r),process:n.process,crc32:1024,data:1028};for(var o=0;o<256;o++){for(var a=255^o,i=0;i<8;i++)a=a>>>1^(1&a?3988292384:0);t.HEAPU32[o]=a}}t.HEAPU32[t.crc32>>2]=0;for(var s=0;s>2];return new Uint8Array([l>>24,l>>16,l>>8,l])},md5:function(e){var t=UnityLoader.Cryptography.md5.module;if(!t){var r=new ArrayBuffer(16777216),n=function(e,t,r){"use asm";var n=new e.Uint32Array(r);function o(e,t){e=e|0;t=t|0;var r=0,o=0,a=0,i=0,s=0,d=0,l=0,u=0,c=0,f=0,h=0,p=0;r=n[128]|0,o=n[129]|0,a=n[130]|0,i=n[131]|0;for(;t;e=e+64|0,t=t-1|0){s=r;d=o;l=a;u=i;for(f=0;(f|0)<512;f=f+8|0){p=n[f>>2]|0;r=r+(n[f+4>>2]|0)+(n[e+(p>>>14)>>2]|0)+((f|0)<128?i^o&(a^i):(f|0)<256?a^i&(o^a):(f|0)<384?o^a^i:a^(o|~i))|0;h=(r<<(p&31)|r>>>32-(p&31))+o|0;r=i;i=a;a=o;o=h}r=r+s|0;o=o+d|0;a=a+l|0;i=i+u|0}n[128]=r;n[129]=o;n[130]=a;n[131]=i}return{process:o}}({Uint32Array:Uint32Array},null,r);t=UnityLoader.Cryptography.md5.module={buffer:r,HEAPU8:new Uint8Array(r),HEAPU32:new Uint32Array(r),process:n.process,md5:512,data:576},t.HEAPU32.set(new Uint32Array([7,3614090360,65548,3905402710,131089,606105819,196630,3250441966,262151,4118548399,327692,1200080426,393233,2821735955,458774,4249261313,524295,1770035416,589836,2336552879,655377,4294925233,720918,2304563134,786439,1804603682,851980,4254626195,917521,2792965006,983062,1236535329,65541,4129170786,393225,3225465664,720910,643717713,20,3921069994,327685,3593408605,655369,38016083,983054,3634488961,262164,3889429448,589829,568446438,917513,3275163606,196622,4107603335,524308,1163531501,851973,2850285829,131081,4243563512,458766,1735328473,786452,2368359562,327684,4294588738,524299,2272392833,720912,1839030562,917527,4259657740,65540,2763975236,262155,1272893353,458768,4139469664,655383,3200236656,851972,681279174,11,3936430074,196624,3572445317,393239,76029189,589828,3654602809,786443,3873151461,983056,530742520,131095,3299628645,6,4096336452,458762,1126891415,917519,2878612391,327701,4237533241,786438,1700485571,196618,2399980690,655375,4293915773,65557,2240044497,524294,1873313359,983050,4264355552,393231,2734768916,851989,1309151649,262150,4149444226,720906,3174756917,131087,718787259,589845,3951481745]))}t.HEAPU32.set(new Uint32Array([1732584193,4023233417,2562383102,271733878]),t.md5>>2);for(var o=0;o>6),e.length-o<64){if(a=e.length-o,t.HEAPU8.set(e.subarray(e.length-a,e.length),t.data),o+=a,t.HEAPU8[t.data+a++]=128,a>56){for(var i=a;i<64;i++)t.HEAPU8[t.data+i]=0;t.process(t.data,1),a=0}for(var i=a;i<64;i++)t.HEAPU8[t.data+i]=0;for(var s=e.length,d=0,i=56;i<64;i++,d=(224&s)>>5,s/=256)t.HEAPU8[t.data+i]=((31&s)<<3)+d;t.process(t.data,1)}}return new Uint8Array(t.HEAPU8.subarray(t.md5,t.md5+16))},sha1:function(e){var t=UnityLoader.Cryptography.sha1.module;if(!t){var r=new ArrayBuffer(16777216),n=function(e,t,r){"use asm";var n=new e.Uint32Array(r);function o(e,t){e=e|0;t=t|0;var r=0,o=0,a=0,i=0,s=0,d=0,l=0,u=0,c=0,f=0,h=0,p=0;r=n[80]|0,o=n[81]|0,a=n[82]|0,i=n[83]|0,s=n[84]|0;for(;t;e=e+64|0,t=t-1|0){d=r;l=o;u=a;c=i;f=s;for(p=0;(p|0)<320;p=p+4|0,s=i,i=a,a=o<<30|o>>>2,o=r,r=h){if((p|0)<64){h=n[e+p>>2]|0;h=h<<24&4278190080|h<<8&16711680|h>>>8&65280|h>>>24&255}else{h=n[p-12>>2]^n[p-32>>2]^n[p-56>>2]^n[p-64>>2];h=h<<1|h>>>31}n[p>>2]=h;h=h+((r<<5|r>>>27)+s)+((p|0)<80?(o&a|~o&i|0)+1518500249|0:(p|0)<160?(o^a^i)+1859775393|0:(p|0)<240?(o&a|o&i|a&i)+2400959708|0:(o^a^i)+3395469782|0)|0}r=r+d|0;o=o+l|0;a=a+u|0;i=i+c|0;s=s+f|0}n[80]=r;n[81]=o;n[82]=a;n[83]=i;n[84]=s}return{process:o}}({Uint32Array:Uint32Array},null,r);t=UnityLoader.Cryptography.sha1.module={buffer:r,HEAPU8:new Uint8Array(r),HEAPU32:new Uint32Array(r),process:n.process,sha1:320,data:384}}t.HEAPU32.set(new Uint32Array([1732584193,4023233417,2562383102,271733878,3285377520]),t.sha1>>2);for(var o=0;o>6),e.length-o<64){if(a=e.length-o,t.HEAPU8.set(e.subarray(e.length-a,e.length),t.data),o+=a,t.HEAPU8[t.data+a++]=128,a>56){for(var i=a;i<64;i++)t.HEAPU8[t.data+i]=0;t.process(t.data,1),a=0}for(var i=a;i<64;i++)t.HEAPU8[t.data+i]=0;for(var s=e.length,d=0,i=63;i>=56;i--,d=(224&s)>>5,s/=256)t.HEAPU8[t.data+i]=((31&s)<<3)+d;t.process(t.data,1)}}for(var l=new Uint8Array(20),i=0;i\\[(\\d+)\\]\\+\\d+\\))()":"((\\s*)wasm-function\\[(\\d+)\\])@(blob:.*)",blobParseRegExp:new RegExp("^(blob:.*)(:\\d+:\\d+)$"),getModule:function(e){var t=e.message.match(new RegExp(this.stackTraceFormat,"g"));for(var r in t){var n=t[r].match(new RegExp("^"+this.stackTraceFormat+"$")),o=n[7].match(this.blobParseRegExp);if(o&&UnityLoader.Blobs[o[1]]&&UnityLoader.Blobs[o[1]].Module)return UnityLoader.Blobs[o[1]].Module}},demangle:function(e,t){var r=e.message;return t?(r=r.replace(new RegExp(this.stackTraceFormat,"g"),function(e){var r=e.match(new RegExp("^"+this.stackTraceFormat+"$")),n=r[7].match(this.blobParseRegExp),o=t.demangleSymbol?t.demangleSymbol(r[4]):r[4],a=n&&UnityLoader.Blobs[n[1]]&&UnityLoader.Blobs[n[1]].url?UnityLoader.Blobs[n[1]].url:"blob";return r[1]+o+(r[2]!=o?" ["+r[2]+"]":"")+" ("+(n?a.substr(a.lastIndexOf("/")+1)+n[2]:r[7])+")"}.bind(this)),t.useWasm&&(r=r.replace(new RegExp(this.stackTraceFormatWasm,"g"),function(e){var r=e.match(new RegExp("^"+this.stackTraceFormatWasm+"$")),n=t.demangleSymbol?t.demangleSymbol(r[3]):r[3],o=r[4].match(this.blobParseRegExp),a=o&&UnityLoader.Blobs[o[1]]&&UnityLoader.Blobs[o[1]].url?UnityLoader.Blobs[o[1]].url:"blob";return(n==r[3]?r[1]:r[2]+n+" [wasm:"+r[3]+"]")+(r[4]?" ("+(o?a.substr(a.lastIndexOf("/")+1)+o[2]:r[4])+")":"")}.bind(this))),r):r},handler:function(e,t){var r=t?this.demangle(e,t):e.message;if(!(t&&t.errorhandler&&t.errorhandler(r,e.filename,e.lineno)||(console.log("Invoking error handler due to\n"+r),"function"==typeof dump&&dump("Invoking error handler due to\n"+r),r.indexOf("UnknownError")!=-1||r.indexOf("Program terminated with exit(0)")!=-1||this.didShowErrorMessage))){var r="An error occurred running the Unity content on this page. See your browser JavaScript console for more info. The error was:\n"+r;r.indexOf("DISABLE_EXCEPTION_CATCHING")!=-1?r="An exception has occurred, but exception handling has been disabled in this build. If you are the developer of this content, enable exceptions in your project WebGL player settings to be able to catch the exception or see the stack trace.":r.indexOf("Cannot enlarge memory arrays")!=-1?r="Out of memory. If you are the developer of this content, try allocating more memory to your WebGL build in the WebGL player settings.":r.indexOf("Invalid array buffer length")==-1&&r.indexOf("Invalid typed array length")==-1&&r.indexOf("out of memory")==-1&&r.indexOf("could not allocate memory")==-1||(r="The browser could not allocate enough memory for the WebGL content. If you are the developer of this content, try allocating less memory to your WebGL build in the WebGL player settings."),alert(r),this.didShowErrorMessage=!0}},popup:function(e,t,r){r=r||[{text:"OK"}];var n=document.createElement("div");n.style.cssText="position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); text-align: center; border: 1px solid black; padding: 5px; background: #E8E8E8";var o=document.createElement("span");o.textContent=t,n.appendChild(o),n.appendChild(document.createElement("br"));for(var a=0;a=10.1)?1:0}(),hasThreads:"undefined"!=typeof SharedArrayBuffer,hasWasm:"object"==typeof WebAssembly&&"function"==typeof WebAssembly.validate&&"function"==typeof WebAssembly.compile}}(),compatibilityCheck:function(e,t,r){UnityLoader.SystemInfo.hasWebGL?UnityLoader.SystemInfo.mobile?e.popup("Please note that Unity WebGL is not currently supported on mobiles. Press OK if you wish to continue anyway.",[{text:"OK",callback:t}]):["Edge","Firefox","Chrome","Safari"].indexOf(UnityLoader.SystemInfo.browser)==-1?e.popup("Please note that your browser is not currently supported for this Unity WebGL content. Press OK if you wish to continue anyway.",[{text:"OK",callback:t}]):t():e.popup("Your browser does not support WebGL",[{text:"OK",callback:r}])},Blobs:{},loadCode:function(e,t,r){var n=[].slice.call(UnityLoader.Cryptography.md5(e)).map(function(e){return("0"+e.toString(16)).substr(-2)}).join(""),o=document.createElement("script"),a=URL.createObjectURL(new Blob(['UnityLoader["'+n+'"]=',e],{type:"text/javascript"}));UnityLoader.Blobs[a]=r,o.src=a,o.onload=function(){URL.revokeObjectURL(a),t(n),delete o.onload},document.body.appendChild(o)},setupIndexedDBJob:function(e,t){function r(n){r.called||(r.called=!0,e.indexedDB=n,t.complete())}try{var n=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB,o=n.open("/idbfs-test");o.onerror=function(e){e.preventDefault(),r()},o.onsuccess=function(){o.result.close(),r(n)},setTimeout(r,1e3)}catch(e){r()}},processWasmCodeJob:function(e,t){e.wasmBinary=UnityLoader.Job.result(e,"downloadWasmCode"),t.complete()},processWasmFrameworkJob:function(e,t){var r=UnityLoader.Job.result(e,"downloadWasmFramework");UnityLoader.loadCode(r,function(n){var o=new Blob([r],{type:"application/javascript"});e.mainScriptUrlOrBlob=o,UnityLoader[n](e),t.complete()},{Module:e,url:e.wasmFrameworkUrl})},processAsmCodeJob:function(e,t){var r=UnityLoader.Job.result(e,"downloadAsmCode");UnityLoader.loadCode(Math.fround?r:UnityLoader.Utils.optimizeMathFround(r),function(r){e.asm=UnityLoader[r],t.complete()},{Module:e,url:e.asmCodeUrl})},processAsmFrameworkJob:function(e,t){var r=UnityLoader.Job.result(e,"downloadAsmFramework");UnityLoader.loadCode(r,function(n){var o=new Blob([r],{type:"application/javascript"});e.mainScriptUrlOrBlob=o,UnityLoader[n](e),t.complete()},{Module:e,url:e.asmFrameworkUrl})},processMemoryInitializerJob:function(e,t){e.memoryInitializerRequest.status=200,e.memoryInitializerRequest.response=UnityLoader.Job.result(e,"downloadMemoryInitializer"),e.memoryInitializerRequest.callback&&e.memoryInitializerRequest.callback(),t.complete()},processDataJob:function(e,t){var r=UnityLoader.Job.result(e,"downloadData"),n=new DataView(r.buffer,r.byteOffset,r.byteLength),o=0,a="UnityWebData1.0\0";if(!String.fromCharCode.apply(null,r.subarray(o,o+a.length))==a)throw"unknown data format";o+=a.length;var i=n.getUint32(o,!0);for(o+=4;o0;c=f,f=u.indexOf("/",c)+1)e.FS_createPath(u.substring(0,c),u.substring(c,f-1),!0,!0);e.FS_createDataFile(u,null,r.subarray(s,s+d),!0,!0,!0)}e.removeRunDependency("processDataJob"),t.complete()},downloadJob:function(e,t){var r=t.parameters.objParameters?new UnityLoader.UnityCache.XMLHttpRequest(t.parameters.objParameters):new XMLHttpRequest;r.open("GET",t.parameters.url),r.responseType="arraybuffer",r.onload=function(){UnityLoader.Compression.decompress(new Uint8Array(r.response),function(e){t.complete(e)})},t.parameters.onprogress&&r.addEventListener("progress",t.parameters.onprogress),t.parameters.onload&&r.addEventListener("load",t.parameters.onload),r.send()},scheduleBuildDownloadJob:function(e,t,r){UnityLoader.Progress.update(e,t),UnityLoader.Job.schedule(e,t,[],UnityLoader.downloadJob,{url:e.resolveBuildUrl(e[r]),onprogress:function(r){UnityLoader.Progress.update(e,t,r)},onload:function(r){UnityLoader.Progress.update(e,t,r)},objParameters:e.companyName&&e.productName&&e.cacheControl&&(e.cacheControl[r]||e.cacheControl.default)?{companyName:e.companyName,productName:e.productName,cacheControl:e.cacheControl[r]||e.cacheControl.default}:null})},loadModule:function(e){if(e.useWasm=e.wasmCodeUrl&&UnityLoader.SystemInfo.hasWasm,e.useWasm)UnityLoader.scheduleBuildDownloadJob(e,"downloadWasmCode","wasmCodeUrl"),UnityLoader.Job.schedule(e,"processWasmCode",["downloadWasmCode"],UnityLoader.processWasmCodeJob),e.wasmMemoryUrl&&(UnityLoader.scheduleBuildDownloadJob(e,"downloadMemoryInitializer","wasmMemoryUrl"),UnityLoader.Job.schedule(e,"processMemoryInitializer",["downloadMemoryInitializer"],UnityLoader.processMemoryInitializerJob),e.memoryInitializerRequest={addEventListener:function(t,r){e.memoryInitializerRequest.callback=r}}),UnityLoader.scheduleBuildDownloadJob(e,"downloadWasmFramework","wasmFrameworkUrl"),UnityLoader.Job.schedule(e,"processWasmFramework",["downloadWasmFramework","processWasmCode","setupIndexedDB"],UnityLoader.processWasmFrameworkJob);else{if(!e.asmCodeUrl)throw"WebAssembly support is not detected in this browser.";UnityLoader.scheduleBuildDownloadJob(e,"downloadAsmCode","asmCodeUrl"),UnityLoader.Job.schedule(e,"processAsmCode",["downloadAsmCode"],UnityLoader.processAsmCodeJob),UnityLoader.scheduleBuildDownloadJob(e,"downloadMemoryInitializer","asmMemoryUrl"),UnityLoader.Job.schedule(e,"processMemoryInitializer",["downloadMemoryInitializer"],UnityLoader.processMemoryInitializerJob),e.memoryInitializerRequest={addEventListener:function(t,r){e.memoryInitializerRequest.callback=r}},e.asmLibraryUrl&&(e.dynamicLibraries=[e.asmLibraryUrl].map(e.resolveBuildUrl)),UnityLoader.scheduleBuildDownloadJob(e,"downloadAsmFramework","asmFrameworkUrl"),UnityLoader.Job.schedule(e,"processAsmFramework",["downloadAsmFramework","processAsmCode","setupIndexedDB"],UnityLoader.processAsmFrameworkJob)}UnityLoader.scheduleBuildDownloadJob(e,"downloadData","dataUrl"),UnityLoader.Job.schedule(e,"setupIndexedDB",[],UnityLoader.setupIndexedDBJob),e.preRun.push(function(){e.addRunDependency("processDataJob"),UnityLoader.Job.schedule(e,"processData",["downloadData"],UnityLoader.processDataJob)})},instantiate:function(e,t,r){function n(e,r){if("string"==typeof e&&!(e=document.getElementById(e)))return!1;e.innerHTML="",e.style.border=e.style.margin=e.style.padding=0,"static"==getComputedStyle(e).getPropertyValue("position")&&(e.style.position="relative"),e.style.width=r.width||e.style.width,e.style.height=r.height||e.style.height,r.container=e;var n=r.Module;return n.canvas=document.createElement("canvas"),n.canvas.style.width="100%",n.canvas.style.height="100%",n.canvas.addEventListener("contextmenu",function(e){e.preventDefault()}),n.canvas.id="#canvas",e.appendChild(n.canvas),r.compatibilityCheck(r,function(){var t=new XMLHttpRequest;t.open("GET",r.url,!0),t.responseType="text",t.onerror=function(){n.print("Could not download "+r.url),0==document.URL.indexOf("file:")&&alert("It seems your browser does not support running Unity WebGL content from file:// urls. Please upload it to an http server, or try a different browser.")},t.onload=function(){var o=JSON.parse(t.responseText);for(var a in o)"undefined"==typeof n[a]&&(n[a]=o[a]);for(var i=!1,s=0;s=1?i=!0:n.print("Warning: Unsupported graphics API "+d)}return i?(e.style.background=n.backgroundUrl?"center/cover url('"+n.resolveBuildUrl(n.backgroundUrl)+"')":n.backgroundColor?" "+n.backgroundColor:"",r.onProgress(r,0),void UnityLoader.loadModule(n)):void r.popup("Your browser does not support any of the required graphics API for this content: "+n.graphicsAPI,[{text:"OK"}])},t.send()},function(){n.printErr("Instantiation of the '"+t+"' terminated due to the failed compatibility check.")}),!0}function o(e){return o.link=o.link||document.createElement("a"),o.link.href=e,o.link.href}var a={url:t,onProgress:UnityLoader.Progress.handler,compatibilityCheck:UnityLoader.compatibilityCheck,Module:{graphicsAPI:["WebGL 2.0","WebGL 1.0"],onAbort:function(e){throw void 0!==e?(this.print(e),this.printErr(e),e=JSON.stringify(e)):e="","abort("+e+") at "+this.stackTrace()},preRun:[],postRun:[],print:function(e){console.log(e)},printErr:function(e){console.error(e)},Jobs:{},buildDownloadProgress:{},resolveBuildUrl:function(e){return e.match(/(http|https|ftp|file):\/\//)?e:t.substring(0,t.lastIndexOf("/")+1)+e},streamingAssetsUrl:function(){return o(this.resolveBuildUrl("../StreamingAssets"))},pthreadMainPrefixURL:"Build/"},SetFullscreen:function(){if(a.Module.SetFullscreen)return a.Module.SetFullscreen.apply(a.Module,arguments)},SendMessage:function(){if(a.Module.SendMessage)return a.Module.SendMessage.apply(a.Module,arguments)}};a.Module.gameInstance=a,a.popup=function(e,t){return UnityLoader.Error.popup(a,e,t)},a.Module.postRun.push(function(){a.onProgress(a,1)});for(var i in r)if("Module"==i)for(var s in r[i])a.Module[s]=r[i][s];else a[i]=r[i];return n(e,a)||document.addEventListener("DOMContentLoaded",function(){n(e,a)}),a},Utils:{assert:function(e,t){e||abort("Assertion failed: "+t)},optimizeMathFround:function(e,t){console.log("optimizing out Math.fround calls");for(var r={LOOKING_FOR_MODULE:0,SCANNING_MODULE_VARIABLES:1,SCANNING_MODULE_FUNCTIONS:2},n=["EMSCRIPTEN_START_ASM","EMSCRIPTEN_START_FUNCS","EMSCRIPTEN_END_FUNCS"],o="var",a="global.Math.fround;",i=0,s=t?r.LOOKING_FOR_MODULE:r.SCANNING_MODULE_VARIABLES,d=0,l=0;s<=r.SCANNING_MODULE_FUNCTIONS&&i 10 | 11 | [Demo](https://dom.ink/unity-webgl-responsive/) 12 | 13 | ## How to use 14 | 15 | Create a folder called `WebGLTemplates` in the `Assets` folder of your Unity project. 16 | 17 | For Unity 2018 and 2019, copy the `responsive-template` folder and all of its contents into `WebGLTemplates`. 18 | 19 | For Unity 2020.1 and newer, copy the `responsive-template-2020` folder instead, as changes to the WebGL loader and templates were introduced with 2020.1. 20 | 21 | Folder location 22 | 23 | Select the template in the Player settings (`Edit > Project Settings` then select the `Player` category) and set the default canvas resolution. 24 | 25 | Template settings 26 | 27 | Optionally, change the properties of `.webgl-wrapper` in `style.css` to set the application's maximum width: 28 | 29 | ``` 30 | .webgl-wrapper { 31 | width: 100%; 32 | max-width: 1280px; /* remove this line for full width */ 33 | } 34 | ``` 35 | 36 | For Gzip-compressed builds (see `Publishing Settings`), you should turn on `Decompression Fallback` or configure your web server to add `Content-Encoding: gzip` response header. 37 | 38 | ## Notes 39 | 40 | - Press F to toggle fullscreen. Customize this behavior in the script at the bottom of `index.html.` 41 | - The application canvas preserves the aspect ratio set in the `Player` settings in `Project Settings`. 42 | 43 | Resulting HTML includes credits and a link back to this page, which is appreciated, but feel free to remove all of that and modify the template as needed. Disney head in the example project courtesy of [David OReilly](http://www.davidoreilly.com/). 44 | -------------------------------------------------------------------------------- /assets/css/reset.css: -------------------------------------------------------------------------------- 1 | * { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} 2 | -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* demo */ 2 | 3 | * { 4 | font-family: monospace; 5 | } 6 | 7 | body { 8 | background: #000; 9 | color: #999; 10 | font-size: 17px; 11 | } 12 | 13 | a { 14 | color: #ccc; 15 | text-decoration: underline; 16 | } 17 | 18 | .info { 19 | width:100%; 20 | padding:12px; 21 | box-sizing: border-box; 22 | } 23 | 24 | /* webgl layout */ 25 | 26 | .webgl-wrapper { 27 | display: inline-block; 28 | width: 100%; 29 | max-width: 1280px; /* remove this line for full width */ 30 | position: relative; 31 | } 32 | 33 | .webgl-content { 34 | position:absolute; 35 | top: 0; 36 | bottom: 0; 37 | left: 0; 38 | right: 0; 39 | } 40 | 41 | #unityContainer { 42 | width: 100%; height: 100%; 43 | } 44 | 45 | .webgl-content * { 46 | border: 0; 47 | margin: 0; 48 | padding: 0; 49 | } 50 | 51 | #unityContainer canvas { 52 | width:100%; 53 | height:100%; 54 | top:0; 55 | left:0; 56 | } 57 | 58 | /* this element makes sure we preserve 16:9 aspect ratio */ 59 | 60 | .aspect { 61 | margin-top: 56.25%; 62 | } 63 | 64 | /* progress bar */ 65 | 66 | .webgl-content .logo, .progress {position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);} 67 | .webgl-content .logo {background: url('../images/progressLogo.Light.png') no-repeat center / contain; width: 154px; height: 130px;} 68 | .webgl-content .progress {height: 18px; width: 141px; margin-top: 90px;} 69 | .webgl-content .progress .empty {background: url('../images/progressEmpty.Light.png') no-repeat right / cover; float: right; width: 100%; height: 100%; display: inline-block;} 70 | .webgl-content .progress .full {background: url('../images/progressFull.Light.png') no-repeat left / cover; float: left; width: 0%; height: 100%; display: inline-block;} 71 | .webgl-content .logo.Dark {background-image: url('../images/progressLogo.Dark.png');} 72 | .webgl-content .progress.Dark .empty {background-image: url('../images/progressEmpty.Dark.png');} 73 | .webgl-content .progress.Dark .full {background-image: url('../images/progressFull.Dark.png');} 74 | .webgl-content .footer {margin-top: 5px; height: 38px; line-height: 38px; font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 18px;} 75 | .webgl-content .footer .webgl-logo, .title, .fullscreen {height: 100%; display: inline-block; background: transparent center no-repeat;} 76 | .webgl-content .footer .webgl-logo {background-image: url('../images/webgl-logo.png'); width: 204px; float: left;} 77 | .webgl-content .footer .title {margin-right: 10px; float: right;} 78 | .webgl-content .footer .fullscreen {background-image: url('../images/fullscreen.png'); width: 38px; float: right; cursor:pointer;} 79 | -------------------------------------------------------------------------------- /assets/images/readme-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sno/unity-webgl-responsive/0c4c7e2da74b532d30bea8d058212cef6e90e93b/assets/images/readme-demo.gif -------------------------------------------------------------------------------- /assets/images/readme-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sno/unity-webgl-responsive/0c4c7e2da74b532d30bea8d058212cef6e90e93b/assets/images/readme-folder.png -------------------------------------------------------------------------------- /assets/images/readme-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sno/unity-webgl-responsive/0c4c7e2da74b532d30bea8d058212cef6e90e93b/assets/images/readme-template.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | unity webgl responsive 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 |
34 |
35 |
36 |
37 |
38 |
39 | 40 |
41 |

unity webgl responsive

42 |

press F or click here to toggle fullscreen

43 |
44 | 45 | 46 |
47 |

source code on github

48 |

template by dom / @zerstoerer

49 |
50 | 51 | 52 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /responsive-template-2020/MyLoader.js: -------------------------------------------------------------------------------- 1 | var myGameInstance = null; 2 | 3 | function createUnityInstance(canvas, config, onProgress) { 4 | onProgress = onProgress || function () {}; 5 | 6 | function errorListener(e) { 7 | var error = e.type == "unhandledrejection" && typeof e.reason == "object" ? e.reason : typeof e.error == "object" ? e.error : null; 8 | var message = error ? error.toString() : typeof e.message == "string" ? e.message : typeof e.reason == "string" ? e.reason : ""; 9 | if (error && typeof error.stack == "string") 10 | message += "\n" + error.stack.substring(!error.stack.lastIndexOf(message, 0) ? message.length : 0).replace(/(^\n*|\n*$)/g, ""); 11 | if (!message || !Module.stackTraceRegExp || !Module.stackTraceRegExp.test(message)) 12 | return; 13 | var filename = 14 | e instanceof ErrorEvent ? e.filename : 15 | error && typeof error.fileName == "string" ? error.fileName : 16 | error && typeof error.sourceURL == "string" ? error.sourceURL : 17 | ""; 18 | var lineno = 19 | e instanceof ErrorEvent ? e.lineno : 20 | error && typeof error.lineNumber == "number" ? error.lineNumber : 21 | error && typeof error.line == "number" ? error.line : 22 | 0; 23 | #if SYMBOLS_FILENAME 24 | demanglingErrorHandler(message, filename, lineno); 25 | #else // SYMBOLS_FILENAME 26 | errorHandler(message, filename, lineno); 27 | #endif // SYMBOLS_FILENAME 28 | } 29 | 30 | var Module = { 31 | canvas: canvas, 32 | webglContextAttributes: { 33 | preserveDrawingBuffer: false, 34 | }, 35 | #if USE_DATA_CACHING 36 | cacheControl: function (url) { 37 | return url == Module.dataUrl ? "must-revalidate" : "no-store"; 38 | }, 39 | #endif // USE_DATA_CACHING 40 | #if !USE_WASM 41 | TOTAL_MEMORY: {{{ TOTAL_MEMORY }}}, 42 | #endif // !USE_WASM 43 | streamingAssetsUrl: "StreamingAssets", 44 | downloadProgress: {}, 45 | deinitializers: [], 46 | intervals: {}, 47 | setInterval: function (func, ms) { 48 | var id = window.setInterval(func, ms); 49 | this.intervals[id] = true; 50 | return id; 51 | }, 52 | clearInterval: function(id) { 53 | delete this.intervals[id]; 54 | window.clearInterval(id); 55 | }, 56 | preRun: [], 57 | postRun: [], 58 | print: function (message) { 59 | console.log(message); 60 | }, 61 | printErr: function (message) { 62 | console.error(message); 63 | }, 64 | locateFile: function (url) { 65 | return ( 66 | #if USE_WASM && !DECOMPRESSION_FALLBACK 67 | url == "build.wasm" ? this.codeUrl : 68 | #endif // USE_WASM && !DECOMPRESSION_FALLBACK 69 | #if USE_THREADS 70 | #if DECOMPRESSION_FALLBACK 71 | url == "pthread-main.js" ? this.frameworkBlobUrl : 72 | #else // DECOMPRESSION_FALLBACK 73 | url == "pthread-main.js" ? this.frameworkUrl : 74 | #endif // DECOMPRESSION_FALLBACK 75 | #endif // USE_THREADS 76 | url 77 | ); 78 | }, 79 | #if USE_THREADS 80 | // The contents of "pthread-main.js" is embedded in the framework, which is used as a worker source. 81 | // Therefore Module.mainScriptUrlOrBlob is no longer needed and is set to a dummy blob for compatibility reasons. 82 | mainScriptUrlOrBlob: new Blob([" "], { type: "application/javascript" }), 83 | #endif // USE_THREADS 84 | disabledCanvasEvents: [ 85 | "contextmenu", 86 | "dragstart", 87 | ], 88 | }; 89 | 90 | for (var parameter in config) 91 | Module[parameter] = config[parameter]; 92 | 93 | Module.streamingAssetsUrl = new URL(Module.streamingAssetsUrl, document.URL).href; 94 | 95 | // Operate on a clone of Module.disabledCanvasEvents field so that at Quit time 96 | // we will ensure we'll remove the events that we created (in case user has 97 | // modified/cleared Module.disabledCanvasEvents in between) 98 | var disabledCanvasEvents = Module.disabledCanvasEvents.slice(); 99 | 100 | function preventDefault(e) { 101 | e.preventDefault(); 102 | } 103 | 104 | disabledCanvasEvents.forEach(function (disabledCanvasEvent) { 105 | canvas.addEventListener(disabledCanvasEvent, preventDefault); 106 | }); 107 | 108 | window.addEventListener("error", errorListener); 109 | window.addEventListener("unhandledrejection", errorListener); 110 | 111 | var unityInstance = { 112 | Module: Module, 113 | SetFullscreen: function () { 114 | if (Module.SetFullscreen) 115 | return Module.SetFullscreen.apply(Module, arguments); 116 | Module.print("Failed to set Fullscreen mode: Player not loaded yet."); 117 | }, 118 | SendMessage: function () { 119 | if (Module.SendMessage) 120 | return Module.SendMessage.apply(Module, arguments); 121 | Module.print("Failed to execute SendMessage: Player not loaded yet."); 122 | }, 123 | Quit: function () { 124 | return new Promise(function (resolve, reject) { 125 | Module.shouldQuit = true; 126 | Module.onQuit = resolve; 127 | 128 | // Clear the event handlers we added above, so that the event handler 129 | // functions will not hold references to this JS function scope after 130 | // exit, to allow JS garbage collection to take place. 131 | disabledCanvasEvents.forEach(function (disabledCanvasEvent) { 132 | canvas.removeEventListener(disabledCanvasEvent, preventDefault); 133 | }); 134 | window.removeEventListener("error", errorListener); 135 | window.removeEventListener("unhandledrejection", errorListener); 136 | }); 137 | }, 138 | }; 139 | 140 | Module.SystemInfo = (function () { 141 | #if 0 142 | // Recognize and parse the following formats of user agents: 143 | 144 | // Opera 71 on Windows 10: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 OPR/71.0.3770.228 145 | // Edge 85 on Windows 10: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.70 146 | // Firefox 81 on Windows 10: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0 147 | // Chrome 85 on Windows 10: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 148 | // IE 11 on Windows 7: Mozilla/5.0 CK={} (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko 149 | // IE 10 on Windows 7: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0) 150 | 151 | // Chrome 80 on Android 8.0.0: Mozilla/5.0 (Linux; Android 8.0.0; VKY-L29) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Mobile Safari/537.36 152 | // Firefox 68 on Android 8.0.0: Mozilla/5.0 (Android 8.0.0; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0 153 | 154 | // Samsung Browser on Android 9: Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/10.2 Chrome/71.0.3578.99 Mobile Safari/537.36 155 | // Safari 13.0.5 on iPhone 13.3.1: Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1 156 | 157 | // Safari 12.1 on iPad OS 12.2 Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Mobile/15E148 Safari/604.1 158 | 159 | // Safari 14 on macOS 11.0: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1 160 | // Safari 14 on macOS 10.15.6: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15 161 | // Firefox 80 on macOS 10.15: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0 162 | // Chrome 65 on macOS 10.15.6: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36 163 | 164 | // Firefox 57 on FreeBSD: Mozilla/5.0 (X11; FreeBSD amd64; rv:57.0) Gecko/20100101 Firefox/57.0 165 | // Chrome 43 on OpenBSD: Mozilla/5.0 (X11; OpenBSD amd64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36 166 | #endif 167 | 168 | var browser, browserVersion, os, osVersion, canvas, gpu; 169 | 170 | var ua = navigator.userAgent + ' '; 171 | var browsers = [ 172 | ['Firefox', 'Firefox'], 173 | ['OPR', 'Opera'], 174 | ['Edg', 'Edge'], 175 | ['SamsungBrowser', 'Samsung Browser'], 176 | ['Trident', 'Internet Explorer'], 177 | ['MSIE', 'Internet Explorer'], 178 | ['Chrome', 'Chrome'], 179 | ['Safari', 'Safari'], 180 | ]; 181 | 182 | function extractRe(re, str, idx) { 183 | re = RegExp(re, 'i').exec(str); 184 | return re && re[idx]; 185 | } 186 | for(var b = 0; b < browsers.length; ++b) { 187 | browserVersion = extractRe(browsers[b][0] + '[\/ ](.*?)[ \\)]', ua, 1); 188 | if (browserVersion) { 189 | browser = browsers[b][1]; 190 | break; 191 | } 192 | } 193 | if (browser == 'Safari') browserVersion = extractRe('Version\/(.*?) ', ua, 1); 194 | if (browser == 'Internet Explorer') browserVersion = extractRe('rv:(.*?)\\)? ', ua, 1) || browserVersion; 195 | 196 | var oses = [ 197 | ['Windows (.*?)[;\)]', 'Windows'], 198 | ['Android ([0-9_\.]+)', 'Android'], 199 | ['iPhone OS ([0-9_\.]+)', 'iPhoneOS'], 200 | ['iPad.*? OS ([0-9_\.]+)', 'iPadOS'], 201 | ['FreeBSD( )', 'FreeBSD'], 202 | ['OpenBSD( )', 'OpenBSD'], 203 | ['Linux|X11()', 'Linux'], 204 | ['Mac OS X ([0-9_\.]+)', 'macOS'], 205 | ['bot|google|baidu|bing|msn|teoma|slurp|yandex', 'Search Bot'] 206 | ]; 207 | for(var o = 0; o < oses.length; ++o) { 208 | osVersion = extractRe(oses[o][0], ua, 1); 209 | if (osVersion) { 210 | os = oses[o][1]; 211 | osVersion = osVersion.replace(/_/g, '.'); 212 | break; 213 | } 214 | } 215 | var versionMappings = { 216 | 'NT 5.0': '2000', 217 | 'NT 5.1': 'XP', 218 | 'NT 5.2': 'Server 2003', 219 | 'NT 6.0': 'Vista', 220 | 'NT 6.1': '7', 221 | 'NT 6.2': '8', 222 | 'NT 6.3': '8.1', 223 | 'NT 10.0': '10' 224 | }; 225 | osVersion = versionMappings[osVersion] || osVersion; 226 | 227 | // TODO: Add mobile device identifier, e.g. SM-G960U 228 | 229 | canvas = document.createElement("canvas"); 230 | if (canvas) { 231 | gl = canvas.getContext("webgl2"); 232 | glVersion = gl ? 2 : 0; 233 | if (!gl) { 234 | if (gl = canvas && canvas.getContext("webgl")) glVersion = 1; 235 | } 236 | 237 | if (gl) { 238 | gpu = (gl.getExtension("WEBGL_debug_renderer_info") && gl.getParameter(0x9246 /*debugRendererInfo.UNMASKED_RENDERER_WEBGL*/)) || gl.getParameter(0x1F01 /*gl.RENDERER*/); 239 | } 240 | } 241 | 242 | var hasThreads = typeof SharedArrayBuffer !== 'undefined'; 243 | var hasWasm = typeof WebAssembly === "object" && typeof WebAssembly.compile === "function"; 244 | return { 245 | width: screen.width, 246 | height: screen.height, 247 | userAgent: ua.trim(), 248 | browser: browser, 249 | browserVersion: browserVersion, 250 | mobile: /Mobile|Android|iP(ad|hone)/.test(navigator.appVersion), 251 | os: os, 252 | osVersion: osVersion, 253 | gpu: gpu, 254 | language: navigator.userLanguage || navigator.language, 255 | hasWebGL: glVersion, 256 | hasCursorLock: !!document.body.requestPointerLock, 257 | hasFullscreen: !!document.body.requestFullscreen, 258 | hasThreads: hasThreads, 259 | hasWasm: hasWasm, 260 | hasWasmThreads: (function() { 261 | var wasmMemory = hasWasm && hasThreads && new WebAssembly.Memory({"initial": 1, "maximum": 1, "shared": true}); 262 | return wasmMemory && wasmMemory.buffer instanceof SharedArrayBuffer; 263 | })(), 264 | }; 265 | })(); 266 | 267 | function errorHandler(message, filename, lineno) { 268 | if (Module.startupErrorHandler) { 269 | Module.startupErrorHandler(message, filename, lineno); 270 | return; 271 | } 272 | if (Module.errorHandler && Module.errorHandler(message, filename, lineno)) 273 | return; 274 | console.log("Invoking error handler due to\n" + message); 275 | if (typeof dump == "function") 276 | dump("Invoking error handler due to\n" + message); 277 | // Firefox has a bug where it's IndexedDB implementation will throw UnknownErrors, which are harmless, and should not be shown. 278 | if (message.indexOf("UnknownError") != -1) 279 | return; 280 | // Ignore error when application terminated with return code 0 281 | if (message.indexOf("Program terminated with exit(0)") != -1) 282 | return; 283 | if (errorHandler.didShowErrorMessage) 284 | return; 285 | var message = "An error occurred running the Unity content on this page. See your browser JavaScript console for more info. The error was:\n" + message; 286 | if (message.indexOf("DISABLE_EXCEPTION_CATCHING") != -1) { 287 | message = "An exception has occurred, but exception handling has been disabled in this build. If you are the developer of this content, enable exceptions in your project WebGL player settings to be able to catch the exception or see the stack trace."; 288 | } else if (message.indexOf("Cannot enlarge memory arrays") != -1) { 289 | message = "Out of memory. If you are the developer of this content, try allocating more memory to your WebGL build in the WebGL player settings."; 290 | } else if (message.indexOf("Invalid array buffer length") != -1 || message.indexOf("Invalid typed array length") != -1 || message.indexOf("out of memory") != -1 || message.indexOf("could not allocate memory") != -1) { 291 | message = "The browser could not allocate enough memory for the WebGL content. If you are the developer of this content, try allocating less memory to your WebGL build in the WebGL player settings."; 292 | } 293 | alert(message); 294 | errorHandler.didShowErrorMessage = true; 295 | } 296 | 297 | #if SYMBOLS_FILENAME 298 | function demangleMessage(message, symbols) { 299 | #if USE_WASM 300 | var symbolExp = "(wasm-function\\[)(\\d+)(\\])"; 301 | #else // USE_WASM 302 | var symbolExp = "(\\n|\\n at |\\n at Array\\.)([a-zA-Z0-9_$]+)(@| \\()"; 303 | #endif // USE_WASM 304 | var symbolRegExp = new RegExp(symbolExp); 305 | return message.replace(new RegExp(symbolExp, "g"), function (symbol) { 306 | var match = symbol.match(symbolRegExp); 307 | #if USE_WASM 308 | return match[1] + (symbols[match[2]] ? symbols[match[2]] + "@" : "") + match[2] + match[3]; 309 | #else // USE_WASM 310 | return match[1] + match[2] + (symbols[match[2]] ? "[" + symbols[match[2]] + "]" : "") + match[3]; 311 | #endif // USE_WASM 312 | }); 313 | } 314 | 315 | function demanglingErrorHandler(message, filename, lineno) { 316 | if (Module.symbols) { 317 | errorHandler(demangleMessage(message, Module.symbols), filename, lineno); 318 | } else if (!Module.symbolsUrl) { 319 | errorHandler(message, filename, lineno); 320 | } else { 321 | downloadBinary("symbolsUrl").then(function (data) { 322 | var json = ""; 323 | for (var i = 0; i < data.length; i++) 324 | json += String.fromCharCode(data[i]); 325 | Module.symbols = JSON.parse(json); 326 | errorHandler(demangleMessage(message, Module.symbols), filename, lineno); 327 | }).catch(function (error) { 328 | errorHandler(message, filename, lineno); 329 | }); 330 | } 331 | } 332 | 333 | #endif // SYMBOLS_FILENAME 334 | 335 | Module.abortHandler = function (message) { 336 | #if SYMBOLS_FILENAME 337 | demanglingErrorHandler(message, "", 0); 338 | #else // SYMBOLS_FILENAME 339 | errorHandler(message, "", 0); 340 | #endif // SYMBOLS_FILENAME 341 | return true; 342 | }; 343 | 344 | Error.stackTraceLimit = Math.max(Error.stackTraceLimit || 0, 50); 345 | 346 | function progressUpdate(id, e) { 347 | if (id == "symbolsUrl") 348 | return; 349 | var progress = Module.downloadProgress[id]; 350 | if (!progress) 351 | progress = Module.downloadProgress[id] = { 352 | started: false, 353 | finished: false, 354 | lengthComputable: false, 355 | total: 0, 356 | loaded: 0, 357 | }; 358 | if (typeof e == "object" && (e.type == "progress" || e.type == "load")) { 359 | if (!progress.started) { 360 | progress.started = true; 361 | progress.lengthComputable = e.lengthComputable; 362 | progress.total = e.total; 363 | } 364 | progress.loaded = e.loaded; 365 | if (e.type == "load") 366 | progress.finished = true; 367 | } 368 | var loaded = 0, total = 0, started = 0, computable = 0, unfinishedNonComputable = 0; 369 | for (var id in Module.downloadProgress) { 370 | var progress = Module.downloadProgress[id]; 371 | if (!progress.started) 372 | return 0; 373 | started++; 374 | if (progress.lengthComputable) { 375 | loaded += progress.loaded; 376 | total += progress.total; 377 | computable++; 378 | } else if (!progress.finished) { 379 | unfinishedNonComputable++; 380 | } 381 | } 382 | var totalProgress = started ? (started - unfinishedNonComputable - (total ? computable * (total - loaded) / total : 0)) / started : 0; 383 | onProgress(0.9 * totalProgress); 384 | } 385 | 386 | #if USE_DATA_CACHING 387 | {{{ read("UnityLoader/XMLHttpRequest.js") }}} 388 | #endif // USE_DATA_CACHING 389 | 390 | #if DECOMPRESSION_FALLBACK 391 | var decompressors = { 392 | #if DECOMPRESSION_FALLBACK == "Gzip" 393 | gzip: { 394 | require: {{{ read("UnityLoader/Gzip.js") }}}, 395 | decompress: function (data) { 396 | if (!this.exports) 397 | this.exports = this.require("inflate.js"); 398 | try { return this.exports.inflate(data) } catch (e) {}; 399 | }, 400 | hasUnityMarker: function (data) { 401 | var commentOffset = 10, expectedComment = "UnityWeb Compressed Content (gzip)"; 402 | if (commentOffset > data.length || data[0] != 0x1F || data[1] != 0x8B) 403 | return false; 404 | var flags = data[3]; 405 | if (flags & 0x04) { 406 | if (commentOffset + 2 > data.length) 407 | return false; 408 | commentOffset += 2 + data[commentOffset] + (data[commentOffset + 1] << 8); 409 | if (commentOffset > data.length) 410 | return false; 411 | } 412 | if (flags & 0x08) { 413 | while (commentOffset < data.length && data[commentOffset]) 414 | commentOffset++; 415 | if (commentOffset + 1 > data.length) 416 | return false; 417 | commentOffset++; 418 | } 419 | return (flags & 0x10) && String.fromCharCode.apply(null, data.subarray(commentOffset, commentOffset + expectedComment.length + 1)) == expectedComment + "\0"; 420 | }, 421 | }, 422 | #endif // DECOMPRESSION_FALLBACK == "Gzip" 423 | #if DECOMPRESSION_FALLBACK == "Brotli" 424 | br: { 425 | require: {{{ read("UnityLoader/Brotli.js") }}}, 426 | decompress: function (data) { 427 | if (!this.exports) 428 | this.exports = this.require("decompress.js"); 429 | try { return this.exports(data) } catch (e) {}; 430 | }, 431 | hasUnityMarker: function (data) { 432 | var expectedComment = "UnityWeb Compressed Content (brotli)"; 433 | if (!data.length) 434 | return false; 435 | var WBITS_length = (data[0] & 0x01) ? (data[0] & 0x0E) ? 4 : 7 : 1, 436 | WBITS = data[0] & ((1 << WBITS_length) - 1), 437 | MSKIPBYTES = 1 + ((Math.log(expectedComment.length - 1) / Math.log(2)) >> 3); 438 | commentOffset = (WBITS_length + 1 + 2 + 1 + 2 + (MSKIPBYTES << 3) + 7) >> 3; 439 | if (WBITS == 0x11 || commentOffset > data.length) 440 | return false; 441 | var expectedCommentPrefix = WBITS + (((3 << 1) + (MSKIPBYTES << 4) + ((expectedComment.length - 1) << 6)) << WBITS_length); 442 | for (var i = 0; i < commentOffset; i++, expectedCommentPrefix >>>= 8) { 443 | if (data[i] != (expectedCommentPrefix & 0xFF)) 444 | return false; 445 | } 446 | return String.fromCharCode.apply(null, data.subarray(commentOffset, commentOffset + expectedComment.length)) == expectedComment; 447 | }, 448 | }, 449 | #endif // DECOMPRESSION_FALLBACK == "Brotli" 450 | }; 451 | 452 | function decompress(compressed, url, callback) { 453 | for (var contentEncoding in decompressors) { 454 | if (decompressors[contentEncoding].hasUnityMarker(compressed)) { 455 | if (url) 456 | console.log("You can reduce startup time if you configure your web server to add \"Content-Encoding: " + contentEncoding + "\" response header when serving \"" + url + "\" file."); 457 | var decompressor = decompressors[contentEncoding]; 458 | if (!decompressor.worker) { 459 | var workerUrl = URL.createObjectURL(new Blob(["this.require = ", decompressor.require.toString(), "; this.decompress = ", decompressor.decompress.toString(), "; this.onmessage = ", function (e) { 460 | var data = { id: e.data.id, decompressed: this.decompress(e.data.compressed) }; 461 | postMessage(data, data.decompressed ? [data.decompressed.buffer] : []); 462 | }.toString(), "; postMessage({ ready: true });"], { type: "application/javascript" })); 463 | decompressor.worker = new Worker(workerUrl); 464 | decompressor.worker.onmessage = function (e) { 465 | if (e.data.ready) { 466 | URL.revokeObjectURL(workerUrl); 467 | return; 468 | } 469 | this.callbacks[e.data.id](e.data.decompressed); 470 | delete this.callbacks[e.data.id]; 471 | }; 472 | decompressor.worker.callbacks = {}; 473 | decompressor.worker.nextCallbackId = 0; 474 | } 475 | var id = decompressor.worker.nextCallbackId++; 476 | decompressor.worker.callbacks[id] = callback; 477 | decompressor.worker.postMessage({id: id, compressed: compressed}, [compressed.buffer]); 478 | return; 479 | } 480 | } 481 | callback(compressed); 482 | } 483 | #endif // DECOMPRESSION_FALLBACK 484 | 485 | function downloadBinary(urlId) { 486 | return new Promise(function (resolve, reject) { 487 | progressUpdate(urlId); 488 | #if USE_DATA_CACHING 489 | var xhr = Module.companyName && Module.productName ? new Module.XMLHttpRequest({ 490 | companyName: Module.companyName, 491 | productName: Module.productName, 492 | cacheControl: Module.cacheControl(Module[urlId]), 493 | }) : new XMLHttpRequest(); 494 | #else // USE_DATA_CACHING 495 | var xhr = new XMLHttpRequest(); 496 | #endif // USE_DATA_CACHING 497 | xhr.open("GET", Module[urlId]); 498 | xhr.responseType = "arraybuffer"; 499 | xhr.addEventListener("progress", function (e) { 500 | progressUpdate(urlId, e); 501 | }); 502 | xhr.addEventListener("load", function(e) { 503 | progressUpdate(urlId, e); 504 | #if DECOMPRESSION_FALLBACK 505 | decompress(new Uint8Array(xhr.response), Module[urlId], resolve); 506 | #else // DECOMPRESSION_FALLBACK 507 | resolve(new Uint8Array(xhr.response)); 508 | #endif // DECOMPRESSION_FALLBACK 509 | }); 510 | xhr.send(); 511 | }); 512 | } 513 | 514 | function downloadFramework() { 515 | #if DECOMPRESSION_FALLBACK 516 | return downloadBinary("frameworkUrl").then(function (code) { 517 | var blobUrl = URL.createObjectURL(new Blob([code], { type: "application/javascript" })); 518 | #if USE_THREADS 519 | Module.frameworkBlobUrl = blobUrl; 520 | #endif // USE_THREADS 521 | #endif // DECOMPRESSION_FALLBACK 522 | return new Promise(function (resolve, reject) { 523 | var script = document.createElement("script"); 524 | #if DECOMPRESSION_FALLBACK 525 | script.src = blobUrl; 526 | #else // DECOMPRESSION_FALLBACK 527 | script.src = Module.frameworkUrl; 528 | #endif // DECOMPRESSION_FALLBACK 529 | script.onload = function () { 530 | // Adding the framework.js script to DOM created a global 531 | // 'unityFramework' variable that should be considered internal. 532 | // Capture the variable to local scope and clear it from global 533 | // scope so that JS garbage collection can take place on 534 | // application quit. 535 | var fw = unityFramework; 536 | unityFramework = null; 537 | // Also ensure this function will not hold any JS scope 538 | // references to prevent JS garbage collection. 539 | script.onload = null; 540 | #if DECOMPRESSION_FALLBACK && !USE_THREADS 541 | URL.revokeObjectURL(blobUrl); 542 | #endif // DECOMPRESSION_FALLBACK && !USE_THREADS 543 | resolve(fw); 544 | } 545 | document.body.appendChild(script); 546 | Module.deinitializers.push(function() { 547 | document.body.removeChild(script); 548 | }); 549 | }); 550 | #if DECOMPRESSION_FALLBACK 551 | }); 552 | #endif // DECOMPRESSION_FALLBACK 553 | } 554 | 555 | #if !USE_WASM 556 | function downloadAsm() { 557 | #if DECOMPRESSION_FALLBACK 558 | return downloadBinary("codeUrl").then(function (code) { 559 | var blobUrl = URL.createObjectURL(new Blob([code], { type: "application/javascript" })); 560 | #endif // DECOMPRESSION_FALLBACK 561 | return new Promise(function (resolve, reject) { 562 | var script = document.createElement("script"); 563 | #if DECOMPRESSION_FALLBACK 564 | script.src = blobUrl; 565 | #else // DECOMPRESSION_FALLBACK 566 | script.src = Module.codeUrl; 567 | #endif // DECOMPRESSION_FALLBACK 568 | #if USE_THREADS 569 | Module.asmJsUrlOrBlob = script.src; 570 | #endif // USE_THREADS 571 | script.onload = function () { 572 | delete script.onload; 573 | #if DECOMPRESSION_FALLBACK && !USE_THREADS 574 | URL.revokeObjectURL(blobUrl); 575 | #endif // DECOMPRESSION_FALLBACK && !USE_THREADS 576 | resolve(); 577 | } 578 | document.body.appendChild(script); 579 | Module.deinitializers.push(function() { 580 | document.body.removeChild(script); 581 | }); 582 | }); 583 | #if DECOMPRESSION_FALLBACK 584 | }); 585 | #endif // DECOMPRESSION_FALLBACK 586 | } 587 | 588 | #endif // !USE_WASM 589 | function loadBuild() { 590 | #if USE_WASM 591 | #if DECOMPRESSION_FALLBACK 592 | Promise.all([ 593 | downloadFramework(), 594 | downloadBinary("codeUrl"), 595 | ]).then(function (results) { 596 | Module.wasmBinary = results[1]; 597 | results[0](Module); 598 | }); 599 | 600 | #else // DECOMPRESSION_FALLBACK 601 | downloadFramework().then(function (unityFramework) { 602 | unityFramework(Module); 603 | }); 604 | 605 | #endif // DECOMPRESSION_FALLBACK 606 | #else // USE_WASM 607 | Promise.all([ 608 | downloadFramework(), 609 | downloadAsm(), 610 | ]).then(function (results) { 611 | results[0](Module); 612 | }); 613 | 614 | #endif // USE_WASM 615 | #if MEMORY_FILENAME 616 | Module.memoryInitializerRequest = { 617 | addEventListener: function (type, listener) { 618 | if (type == "load") 619 | Module.memoryInitializerRequest.useRequest = listener; 620 | }, 621 | }; 622 | downloadBinary("memoryUrl").then(function (data) { 623 | Module.memoryInitializerRequest.status = 200; 624 | Module.memoryInitializerRequest.response = data; 625 | if (Module.memoryInitializerRequest.useRequest) 626 | Module.memoryInitializerRequest.useRequest(); 627 | }); 628 | 629 | #endif // MEMORY_FILENAME 630 | var dataPromise = downloadBinary("dataUrl"); 631 | Module.preRun.push(function () { 632 | Module.addRunDependency("dataUrl"); 633 | dataPromise.then(function (data) { 634 | var view = new DataView(data.buffer, data.byteOffset, data.byteLength); 635 | var pos = 0; 636 | var prefix = "UnityWebData1.0\0"; 637 | if (!String.fromCharCode.apply(null, data.subarray(pos, pos + prefix.length)) == prefix) 638 | throw "unknown data format"; 639 | pos += prefix.length; 640 | var headerSize = view.getUint32(pos, true); pos += 4; 641 | while (pos < headerSize) { 642 | var offset = view.getUint32(pos, true); pos += 4; 643 | var size = view.getUint32(pos, true); pos += 4; 644 | var pathLength = view.getUint32(pos, true); pos += 4; 645 | var path = String.fromCharCode.apply(null, data.subarray(pos, pos + pathLength)); pos += pathLength; 646 | for (var folder = 0, folderNext = path.indexOf("/", folder) + 1 ; folderNext > 0; folder = folderNext, folderNext = path.indexOf("/", folder) + 1) 647 | Module.FS_createPath(path.substring(0, folder), path.substring(folder, folderNext - 1), true, true); 648 | Module.FS_createDataFile(path, null, data.subarray(offset, offset + size), true, true, true); 649 | } 650 | Module.removeRunDependency("dataUrl"); 651 | }); 652 | }); 653 | } 654 | 655 | return new Promise(function (resolve, reject) { 656 | if (!Module.SystemInfo.hasWebGL) { 657 | reject("Your browser does not support WebGL."); 658 | #if !USE_WEBGL_1_0 659 | } else if (Module.SystemInfo.hasWebGL == 1) { 660 | reject("Your browser does not support graphics API \"WebGL 2.0\" which is required for this content."); 661 | #endif // !USE_WEBGL_1_0 662 | #if USE_WASM 663 | } else if (!Module.SystemInfo.hasWasm) { 664 | reject("Your browser does not support WebAssembly."); 665 | #endif // USE_WASM 666 | #if USE_THREADS 667 | } else if (!Module.SystemInfo.hasThreads) { 668 | reject("Your browser does not support multithreading."); 669 | #endif // USE_THREADS 670 | } else { 671 | #if USE_WEBGL_2_0 672 | if (Module.SystemInfo.hasWebGL == 1) 673 | Module.print("Warning: Your browser does not support \"WebGL 2.0\" Graphics API, switching to \"WebGL 1.0\""); 674 | #endif // USE_WEBGL_2_0 675 | Module.startupErrorHandler = reject; 676 | onProgress(0); 677 | Module.postRun.push(function () { 678 | onProgress(1); 679 | delete Module.startupErrorHandler; 680 | resolve(unityInstance); 681 | }); 682 | loadBuild(); 683 | } 684 | }); 685 | } 686 | -------------------------------------------------------------------------------- /responsive-template-2020/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | * { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} 2 | -------------------------------------------------------------------------------- /responsive-template-2020/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* demo */ 2 | 3 | * { 4 | font-family: monospace; 5 | } 6 | 7 | body { 8 | background: #000; 9 | color: #999; 10 | font-size: 17px; 11 | } 12 | 13 | a { 14 | color: #ccc; 15 | text-decoration: underline; 16 | } 17 | 18 | .info { 19 | width:100%; 20 | padding:12px; 21 | box-sizing: border-box; 22 | } 23 | 24 | /* webgl layout */ 25 | 26 | .webgl-wrapper { 27 | display: inline-block; 28 | width: 100%; 29 | max-width: 1280px; /* remove this line for full width */ 30 | position: relative; 31 | } 32 | 33 | .webgl-content { 34 | position:absolute; 35 | top: 0; 36 | bottom: 0; 37 | left: 0; 38 | right: 0; 39 | } 40 | 41 | #unityContainer { 42 | width: 100%; height: 100%; 43 | } 44 | 45 | .webgl-content * { 46 | border: 0; 47 | margin: 0; 48 | padding: 0; 49 | } 50 | 51 | #unityContainer canvas { 52 | width:100%; 53 | height:100%; 54 | top:0; 55 | left:0; 56 | } 57 | 58 | /* this element makes sure we preserve 16:9 aspect ratio */ 59 | 60 | .aspect { 61 | margin-top: calc(100% / {{{ WIDTH }}} * {{{ HEIGHT }}}); 62 | } 63 | 64 | /* progress bar */ 65 | 66 | .webgl-content .logo, .progress {position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);} 67 | .webgl-content .logo {background: url('../images/progressLogo.Light.png') no-repeat center / contain; width: 154px; height: 130px;} 68 | .webgl-content .progress {height: 18px; width: 141px; margin-top: 90px;} 69 | .webgl-content .progress .empty {background: url('../images/progressEmpty.Light.png') no-repeat right / cover; float: right; width: 100%; height: 100%; display: inline-block;} 70 | .webgl-content .progress .full {background: url('../images/progressFull.Light.png') no-repeat left / cover; float: left; width: 0%; height: 100%; display: inline-block;} 71 | .webgl-content .logo.Dark {background-image: url('../images/progressLogo.Dark.png');} 72 | .webgl-content .progress.Dark .empty {background-image: url('../images/progressEmpty.Dark.png');} 73 | .webgl-content .progress.Dark .full {background-image: url('../images/progressFull.Dark.png');} 74 | .webgl-content .footer {margin-top: 5px; height: 38px; line-height: 38px; font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 18px;} 75 | .webgl-content .footer .webgl-logo, .title, .fullscreen {height: 100%; display: inline-block; background: transparent center no-repeat;} 76 | .webgl-content .footer .webgl-logo {background-image: url('../images/webgl-logo.png'); width: 204px; float: left;} 77 | .webgl-content .footer .title {margin-right: 10px; float: right;} 78 | .webgl-content .footer .fullscreen {background-image: url('../images/fullscreen.png'); width: 38px; float: right; cursor:pointer;} 79 | -------------------------------------------------------------------------------- /responsive-template-2020/index.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {{{ PRODUCT_NAME }}} 23 | 24 | 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 | 34 |
35 |

unity webgl responsive

36 |

press F or click here to toggle fullscreen

37 |
38 | 39 | 40 |
41 |

source code on github

42 |

template by dom / @zerstoerer

43 |
44 | 45 | 46 | 65 | 66 | 67 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /responsive-template-2020/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sno/unity-webgl-responsive/0c4c7e2da74b532d30bea8d058212cef6e90e93b/responsive-template-2020/thumbnail.png -------------------------------------------------------------------------------- /responsive-template/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | * { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} 2 | -------------------------------------------------------------------------------- /responsive-template/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* demo */ 2 | 3 | * { 4 | font-family: monospace; 5 | } 6 | 7 | body { 8 | background: #000; 9 | color: #999; 10 | font-size: 17px; 11 | } 12 | 13 | a { 14 | color: #ccc; 15 | text-decoration: underline; 16 | } 17 | 18 | .info { 19 | width:100%; 20 | padding:12px; 21 | box-sizing: border-box; 22 | } 23 | 24 | /* webgl layout */ 25 | 26 | .webgl-wrapper { 27 | display: inline-block; 28 | width: 100%; 29 | max-width: 1280px; /* remove this line for full width */ 30 | position: relative; 31 | } 32 | 33 | .webgl-content { 34 | position:absolute; 35 | top: 0; 36 | bottom: 0; 37 | left: 0; 38 | right: 0; 39 | } 40 | 41 | #unityContainer { 42 | width: 100%; height: 100%; 43 | } 44 | 45 | .webgl-content * { 46 | border: 0; 47 | margin: 0; 48 | padding: 0; 49 | } 50 | 51 | #unityContainer canvas { 52 | width:100%; 53 | height:100%; 54 | top:0; 55 | left:0; 56 | } 57 | 58 | /* this element makes sure we preserve 16:9 aspect ratio */ 59 | /* for unity versions older than 2020, this is set in-line in index.html */ 60 | 61 | .aspect { } 62 | 63 | /* progress bar */ 64 | 65 | .webgl-content .logo, .progress {position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);} 66 | .webgl-content .logo {background: url('../images/progressLogo.Light.png') no-repeat center / contain; width: 154px; height: 130px;} 67 | .webgl-content .progress {height: 18px; width: 141px; margin-top: 90px;} 68 | .webgl-content .progress .empty {background: url('../images/progressEmpty.Light.png') no-repeat right / cover; float: right; width: 100%; height: 100%; display: inline-block;} 69 | .webgl-content .progress .full {background: url('../images/progressFull.Light.png') no-repeat left / cover; float: left; width: 0%; height: 100%; display: inline-block;} 70 | .webgl-content .logo.Dark {background-image: url('../images/progressLogo.Dark.png');} 71 | .webgl-content .progress.Dark .empty {background-image: url('../images/progressEmpty.Dark.png');} 72 | .webgl-content .progress.Dark .full {background-image: url('../images/progressFull.Dark.png');} 73 | .webgl-content .footer {margin-top: 5px; height: 38px; line-height: 38px; font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 18px;} 74 | .webgl-content .footer .webgl-logo, .title, .fullscreen {height: 100%; display: inline-block; background: transparent center no-repeat;} 75 | .webgl-content .footer .webgl-logo {background-image: url('../images/webgl-logo.png'); width: 204px; float: left;} 76 | .webgl-content .footer .title {margin-right: 10px; float: right;} 77 | .webgl-content .footer .fullscreen {background-image: url('../images/fullscreen.png'); width: 38px; float: right; cursor:pointer;} 78 | -------------------------------------------------------------------------------- /responsive-template/index.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | %UNITY_WEB_NAME% 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 37 | 38 | 39 | 40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |

unity webgl responsive

49 |

press F or click here to toggle fullscreen

50 |
51 | 52 | 53 |
54 |

source code on github

55 |

template by dom / @zerstoerer

56 |
57 | 58 | 59 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /responsive-template/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sno/unity-webgl-responsive/0c4c7e2da74b532d30bea8d058212cef6e90e93b/responsive-template/thumbnail.png --------------------------------------------------------------------------------