Spark AR —— Scripting 基础【脚本】

1,470 阅读5分钟

这是我参与8月更文挑战的第20天,活动详情查看: 8月更文挑战

Spark AR 是 Facebook 免费创作 AR 作品的平台,使用户能够为 Facebook 和 Instagram 创建交互式增强现实体验,超过 40 万名创作者,190个国家/地区,使用 Spark AR 来创作自己的AR作品

由于该软件无需任何编码知识即可使用,因此任何人现在都可以在 AR 世界中几乎没有经验地制作下一个疯狂式传播的 Instagram AR 特效,引领世界潮流。

专门的 AR 滤镜设计师单价甚至可达到 1000 美元到 3 万美元不等。

image.png

Spark AR Studio 支持 JavaScript 为你的效果添加逻辑和交互性。本文将涵盖帮助您开始编写脚本的基础知识。

Spark AR studio 将使用分配给 macOS 或 Windows 操作系统中的 JavaScript/TypeScript 文件的默认编辑器打开你的脚本。如果你还没有安装,你可以下载一个编辑器,比如 Visual Studio Code ,并将其设置为打开 JavaScript/TypeScript 文件的默认应用程序。

开始之前

以下是在 Spark AR Studio 中编写脚本时需要考虑的一些要点:

  • 支持 JavaScript ES6 和 TypeScript。
  • 可以在多个文件中分割脚本。

创建脚本

要创建一个新的脚本,单击资产面板中的 + Add Asset 按钮,然后选择 script 。你可以选择创建一个新的 JavaScript 或 TypeScript 文件。

image.png

一个新的脚本文件将出现在 Asset 面板中。

打开脚本

要打开脚本,双击 Assets 面板中的脚本文件。

67672570_2330354303843661_8615742526495653888_n.gif

脚本文件将在与计算机上的JavaScript文件相关联的默认编辑器中打开。

编辑脚本

要编辑脚本,请在脚本编辑器中进行修改,并在返回 Spark AR Studio 之前保存它们。

67672570_2330354303843661_8615742526495653888_n.gif

脚本中的更改将反映在 Spark AR Studio 中。

脚本基础

新的脚本预置了 Spark AR Studio 中一些基本的脚本代码。

下面的示例来自一个预填充的 JavaScript 文件。新创建的 TypeScript 文件的内容会略有不同。

//==============================================================================
  // Welcome to scripting in Spark AR Studio! Helpful links:
  //
  // Scripting Basics - https://fb.me/spark-scripting-basics
  // Reactive Programming - https://fb.me/spark-reactive-programming
  // Scripting Object Reference - https://fb.me/spark-scripting-reference
  // Changelogs - https://fb.me/spark-changelog
  //
  // For projects created with v87 onwards, JavaScript is always executed in strict mode.
  //==============================================================================
  
  // How to load in modules
  const Scene = require('Scene');
  
  // Use export keyword to make a symbol available in scripting debug console
  export const Diagnostics = require('Diagnostics');
  
  // Enables async/await in JS [part 1]
  (async function() {
  
  // To use variables and functions across files, use export/import keyword
  // export const animationDuration = 10;
  
  // Use import keyword to import a symbol from another file
  // import { animationDuration } from './script.js'
  
  // To access scene objects
  // const [directionalLight] = await Promise.all([
  //   Scene.root.findFirst('directionalLight0')
  // ]);
  
  // To access class properties
  // const directionalLightIntensity = directionalLight.intensity;
  
  // To log messages to the console
  // Diagnostics.log('Console message logged from the script.');
  
  // Enables async/await in JS [part 2]
  })();

加载模块

脚本被分解成多个模块,每个模块实现一个特定的功能。

要将模块的 API 加载到 JavaScript 文件中,可以使用 require 方法。

// How to load in modules
  const Diagnostics = require('Diagnostics');
  const Scene = require('Scene');

在上面的示例中,我们加载了 Diagnostics 和 Scene 模块,并将它们存储在变量中,以便稍后在代码中使用。

在 TypeScript 文件中,语法略有变化:

  // How to load in modules in a TypeScript file
  import Scene from 'Scene';
  import Diagnostics from 'Diagnostics';

访问场景对象

要访问场景中的对象,可以使用 scene 模块提供的根属性的 findFirst 方法。

image.png

  // Store a reference to a single scene object
  const focalDistance = await Scene.root.findFirst('Focal Distance');
  
            
  // Store references to multiple scene objects 
  const [directionalLight, plane] = await Promise.all([
      Scene.root.findFirst('directionalLight0'),
      Scene.root.findFirst('plane0'),
  ]);

在上面的例子中,我们访问场景中的对象是通过名称引用它们并将它们存储在变量中。

如果没有找到对象,findFirst 方法将返回 None 。如果有更多的重名对象,那么任意一个将被使用。请使用 findAll 查找给定对象的所有出现情况。

或者,您可以使用根属性的 findByPath 方法来使用对象的相对路径访问它们。

  Scene.root.findByPath('Device/Camera/Focal Distance/plane0').then((results) => {
      const plane = results[0];
  });
          

findypath 方法允许使用通配符 * 来匹配任何子名称,并使用双通配符 ** 来匹配任何一组子名称。

  Scene.root.findByPath('*/*/*/plane0').then((results) => {
      // If there are multiple scene objects matching the given path, multiple results may be returned
      const plane = results[0];
  });
          

注意,如果像前面的例子一样使用 findByPath 方法将引用存储为 const 变量,则必须在作用域内修改对象。

试图在范围之外修改它将会抛出一个错误,如下面的示例所示。

  Scene.root.findByPath('Device/Camera/Focal Distance/plane0').then((results) => {
      const plane = results[0];
  });
  
  // Will throw an error, as we are trying to modify the plane const outside of the scope it is defined in
  plane.width = 0.3;

您可以在 findypath 方法范围内修改对象,如下所示,也可以使用前面所示的 findFirst 方法创建全局可访问的引用。

  Scene.root.findByPath('Device/Camera/Focal Distance/plane0').then((results) => {
      const plane = results[0];
  
      // Since the plane const is modified within scope, no error is thrown
      plane.width = 0.3;
  });

从场景中访问的对象,例如 scene.root.findfirst ('directionalLight0') ,目前不支持自动完成。

编辑场景对象属性

一旦你可以访问一个场景对象,你就可以访问它的属性和方法。

   // How to access class properties
   const directionalLightIntensity = directionalLight.intensity; 

在上面的例子中,我们使用之前创建的 directionalLight 变量来访问光的强度属性。

  • 登录到控制台

可以使用 Diagnostics 模块将消息从脚本记录到 Spark AR Studio 中的控制台。

// How to log messages to the console (uncomment line below to activate)
   Diagnostics.log('I am a console message logged from the script');

image.png

在预置的脚本中,Diagnostics.log 行需要取消注释才能运行。

代码自动完成

脚本可以在你选择的编辑器中编辑,比如 Atom 或 Sublime ,但是 VS Code 通过智能感知支持自动完成功能。

代码建议

方法和属性将在您键入时被建议。

67672570_2330354303843661_8615742526495653888_n.gif

内联文档

您可以查看突出显示的方法或属性的文档。

67672570_2330354303843661_8615742526495653888_n.gif

类型检查

如果你传递了错误的类型或数量的参数给一个方法,你会收到警告。

67672570_2330354303843661_8615742526495653888_n.gif

从场景中访问的对象,例如 scene .root.find('directionalLight0') ,目前不支持自动完成。

下个阶段

现在,您已经掌握了基础知识,是时候学习响应式编程了,这是在 Spark AR Studio 中用于创建对象、资产和值之间关系的脚本模型。