将Unity WebGL项目导入到Angular2组件中

8

我是一名有帮助的助手,可以为您进行文本翻译。

我想要将一个Unity WebGL项目集成到Angular2应用程序中。如何将所有此脚本移动到Angular2组件中?

首先,Unity WebGL会像这样导出一个index.html文件:

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | Espoo web manager (Prefab preview)</title>
    <link rel="shortcut icon" href="TemplateData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
    <script src="TemplateData/UnityProgress.js"></script>  
    <script src="Build/UnityLoader.js"></script>
    <script>
      var gameInstance = UnityLoader.instantiate("gameContainer", "Build/builds.json", {onProgress: UnityProgress});
    </script>
  </head>
  <body>
    <div class="webgl-content">
      <div id="gameContainer" style="width: 960px; height: 600px"></div>
      <div class="footer">
        <div class="webgl-logo"></div>
        <div class="fullscreen" onclick="gameInstance.SetFullscreen(1)"></div>
        <div class="title">Espoo web manager (Prefab preview)</div>
      </div>
    </div>
  </body>
</html>

我开始将这个内容进行拆分,首先我将样式表移动到模板的 .css 文件中:

@import './webgl-app/TemplateData/style.css';

然后我将JavaScript代码移到了组件的.ts文件中:

import { Component, AfterViewInit } from '@angular/core';
import './webgl-app/TemplateData/UnityProgress.js';
import './webgl-app/Build/UnityLoader.js';

declare var UnityLoader: any;
declare var UnityProgress: any;

@Component({
  selector: 'app-unity-prefab-preview',
  templateUrl: './unity-prefab-preview.component.html',
  styleUrls: ['./unity-prefab-preview.component.css']
})
export class UnityPrefabPreviewComponent implements AfterViewInit {
  constructor() {}

  gameInstance: any;

  ngAfterViewInit() {
    this.gameInstance = UnityLoader.instantiate("gameContainer", "./webgl-app/Build/builds.json", { onProgress: UnityProgress });
  }

}

然后对于 .html 模板,我保留了以下内容:

<div class="webgl-content">
  <div id="gameContainer" style="width: 960px; height: 600px"></div>
</div>

然而,无论我尝试什么方法(比如在JS文件上使用“require”),ngAfterViewInit中的那行代码总是会报错:“引用错误:UnityLoader未定义”。

应该如何正确地解决这个问题?


'./webgl-app/Build/UnityLoader.js' 被导入了,但是它不应该被声明为变量吗? 例如 import { UnityLoader } from './webgl-app/Build/UnityLoader.js'; - jervtub
_TemplateData/UnityProgress.js_文件中是否有任何已声明的export函数?据我所知,只有被export的函数/变量才能被导入。 - jervtub
2
通过将导出添加到相应的 .json 文件中,我成功使导入工作。 将一些 webgl 应用程序移动到公共资产文件夹后,我使其几乎可以运行,但是页面在模态对话框中显示: “在此页面上运行 Unity 内容时发生错误。 查看浏览器 JavaScript 控制台以获取更多信息。 错误是: ReferenceError:UnityLoader 未定义。” 似乎这个对话框是由 Unity 而不是 Angular 启动的,所以我猜它几乎可以运行,因为加载时间很长。 但是仍然没有成功,需要在某个地方声明 UnityLoader。 - Juhana Pietari Lehtiniemi
1
@JuhanaPietariLehtiniemi 你应该将你的解决方案发布为答案,这样这个问题才能被标记为已解决。 - Zze
最终我从未使其正常工作,放弃了。 - Juhana Pietari Lehtiniemi
显示剩余2条评论
4个回答

5
为了向您的项目添加Unity WebGL:
1)将WebGL项目导出到Angular项目根目录下的/unity文件夹中(与src处于同一级别)。从构建文件夹中复制以下文件到/src/assets/unity 中:
  • unity.json
  • unity.data.unityweb
  • unity.wasm.code.unityweb
  • unity.wasm.framework.unityweb

unity build files

2)将UnityProgress.jsUnityLoader.js添加到您的angular.json脚本中:
"scripts": [
  "unity/TemplateData/UnityProgress.js",
  "unity/Build/UnityLoader.js"
],

3) (可选)将style.css添加到您的angular.json样式中。

"styles": [
  "node_modules/font-awesome/css/font-awesome.css",
  "src/assets/theme.scss",
  "src/styles.scss",
  "unity/TemplateData/style.css"
],

4) 将基本的Unity HTML添加到您的component.html中:

<div class="webgl-content">
  <div id="unityContainer" style="width: 960px; height: 600px"></div>
  <div class="footer">
    <div class="webgl-logo"></div>
    <div class="fullscreen" (click)="unityInstance.SetFullscreen(1)"></div>
    <div class="title">UnityProject</div>
  </div>
</div>

5) 最后,在您的 component.ts 中实例化您的 unityContainer:

import { Component, OnInit, AfterViewInit } from '@angular/core';
declare var UnityLoader: any;

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit, AfterViewInit {
  unityInstance: any;

  constructor() { }

  ngOnInit() { }

  ngAfterViewInit() {
    this.unityInstance = UnityLoader.instantiate("unityContainer", "assets/unity/unity.json");
  }

}

3

我很久以前就开始尝试这个了...

我使用的是最新的angular/cli@1.6.5版本,现在已经运行起来了。

这是我的app.component.ts文件:

import { Component, NgZone, OnInit } from '@angular/core';
import * as $ from 'jquery';
declare const UnityLoader;
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
public gameObject: any;

constructor(private ngZone: NgZone) {
  window.unity = window.unity || {};
  window.unity.GetUnityNumber = this.randomNumberFromUnity.bind(this);
}

public ngOnInit(): void {
 this.init();
}
public helloUnity() {
 console.log(this.gameObject); // <-- always undefined ?
 this.gameObject.SendMessage('SetText', 'HELLO?');
 }

private init() {
 $.getScript('assets/UnityLoader.js').done(function ( bla , text) {
   this.gameObject = 
   UnityLoader.instantiate('gameContainer','assets/test.json');
   //gameObject not undefined at this stage..
  });
}
private randomNumberFromUnity(input: string) {
  this.ngZone.run(() => {
      console.log('call from unity', input);
 });
}

在 typings.d.ts 文件中,我扩展了 window 元素。

interface Window {
  unity: any;
}

所以当我从Unity进行调用时,我像这样调用它
Application.ExternalCall("unity.GetUnityNumber", rnd);

目前我所缺少的就是调用Unity... 也许你有什么想法?

我将Unity构建为私有npm包。在构建时,所有内容都会被复制到资产文件夹中。


1
我将Unity WebGL输出简化为:

unity-game.html

<body style="margin: 0px">
    <script src="TemplateData/UnityProgress.js"></script>
    <script src="Build/UnityLoader.js"></script>
    <script>
      var gameInstance = UnityLoader.instantiate("gameContainer", "Build/Browser.json", {onProgress: UnityProgress});
    </script>
    <div class="webgl-content">
      <div id="gameContainer" style="width: 800px; height: 600px;"></div>
    </div>
 </body>

将其加载到一个iframe中。这将为您提供一个HTML框架。
unsafe value used in a resource URL context

错误。这可以通过使用特殊的iframe Angular组件来解决。

unity-game.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-unity-game',
  templateUrl: './unity-game.component.html',
  styleUrls: ['./unity-game.component.css']
})
export class UnityGameComponent implements OnInit {
  @Input()
  url: string;
  urlSafe: SafeResourceUrl;

  constructor(public sanitizer: DomSanitizer) { }

  ngOnInit() {
    this.urlSafe= this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
  }

}

unity-game.component.html

<iframe width="800" height="600" frameBorder="0" [src]="urlSafe"></iframe>

感谢Lrodriguez84提供的帮助: https://dev59.com/bloT5IYBdhLWcg3w6iwA#50863439

然后只需添加特殊的iframe组件,将HTML文件传递给它,您可以在任何您想要Unity项目出现的地方添加它!

<app-unity-game url="assets/unity-game.html"></app-unity-game>

1

我也遇到了同样的问题。

似乎你的上下文未设置。

$.getScript('assets/UnityLoader.js').done(function ( bla , text) {
   this.gameObject = 
   UnityLoader.instantiate('gameContainer','assets/test.json');
   //gameObject not undefined at this stage..
   // this does not point towards your container
});

解决方案:
$.getScript('assets/UnityLoader.js').done(function ( bla , text) {
    this.gameObject = 
    UnityLoader.instantiate('gameContainer','assets/test.json');
    //gameObject not undefined at this stage and this points to container
}.bind(this));

更多信息:https://docs.unity3d.com/2018.3/Documentation/Manual/webgl-interactingwithbrowserscripting.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接