Spark AR —— 使用脚本创建效果(三)【脚本】

355 阅读3分钟

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

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

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

录音机的扬声器动画

我们正在创建的第二个动画将应用于录音机的扬声器,以给他们播放音频的外观。

访问扬声器

与基础对象一样,我们需要访问脚本中的扬声器,这次我们需要场景面板中的speaker_left_jntspeaker_right_jnt 对象。

在基对象下面的一行中添加访问 speaker 对象的代码:

脚本代码

Scene.root.findFirst('base_jnt') // Existing code
  .then(function(base) { // Existing code
    Scene.root.findFirst('speaker_left_jnt')
    .then(function(speakerLeft) {
        Scene.root.findFirst('speaker_left_jnt')
        .then(function(speakerLeft) {
        

上面的代码,至少需要 3 帧来执行(由于 Promise 链),看起来相当混乱。我们可以通过 Promise.all API 调用大块的 find 请求来优化它,而不是一个一个地调用。这样的优化只需要 1 帧来执行:

 Promise.all([
    Scene.root.findFirst('base_jnt'),
    Scene.root.findFirst('speaker_left_jnt'),
    Scene.root.findFirst('speaker_right_jnt')
 ])
 .then(function(objects) {
    const base = objects[0];
    const speakerLeft = objects[1];
    const speakerRight = objects[2];

在访问场景中的三个对象时,我们调用 Scene.root 三次,这是一个提高脚本性能的机会。如果我们存储 Scene.root 在一个变量中,我们只需要调用它一次,并且可以任意使用这个变量。

添加以下代码将 root 存储在变量中,并更新访问对象的行:

const sceneRoot = Scene.root;

 // Existing code updated
 Promise.all([
    sceneRoot.findFirst('base_jnt'),
    sceneRoot.findFirst('speaker_left_jnt'),
    sceneRoot.findFirst('speaker_right_jnt')
 ])
 .then(function(objects) {
    const base = objects[0];
    const speakerLeft = objects[1];
    const speakerRight = objects[2];

sceneRoot 变量现在已经取代了单独的 Scene.root 属性调用。

完整脚本代码

const Animation = require('Animation');
 const Scene = require('Scene');
 
 const sceneRoot = Scene.root;
 
 // Existing code updated
 Promise.all([
     sceneRoot.findFirst('base_jnt'),
     sceneRoot.findFirst('speaker_left_jnt'),
     sceneRoot.findFirst('speaker_right_jnt')
 ])
 .then(function(objects) {
     const base = objects[0];
     const speakerLeft = objects[1];
     const speakerRight = objects[2];
     
     const baseDriverParameters = {
         durationMilliseconds: 400,
         loopCount: Infinity,
         mirror: true
     };
 
     const baseDriver = Animation.timeDriver(baseDriverParameters);
     baseDriver.start();
 
     const baseSampler = Animation.samplers.easeInQuint(0.9,1);
 
     const baseAnimation = Animation.animate(baseDriver,baseSampler);
 
     const baseTransform = base.transform;
 
     baseTransform.scaleX = baseAnimation;
     baseTransform.scaleY = baseAnimation;
     baseTransform.scaleZ = baseAnimation;
 });

创建扬声器动画

现在我们可以为扬声器创建驱动器、采样器和动画,就像我们为基对象所做的那样。

对于驱动器,我们将使用与基本对象驱动器类似的参数,但设置的持续时间为 0.2 秒。

脚本代码

const speakerDriverParameters = {
   durationMilliseconds: 200,
   loopCount: Infinity,
   mirror: true
 };

 const speakerDriver = Animation.timeDriver(speakerDriverParameters);
 speakerDriver.start();

对于采样器,我们将使用不同的缓动函数和值。

脚本代码

const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);

这些值比我们用于基础对象的值要小,因为扬声器本身是更小的物体。一个 ease out 函数意味着动画将快速开始但较慢结束。

随着驱动器和采样器的创建,我们现在可以创建动画。

脚本代码

const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);

完整代码如下

 const Animation = require('Animation');
 const Scene = require('Scene');
 
 const sceneRoot = Scene.root;
 
 // Existing code updated
 Promise.all([
     sceneRoot.findFirst('base_jnt'),
     sceneRoot.findFirst('speaker_left_jnt'),
     sceneRoot.findFirst('speaker_right_jnt')
 ])
 .then(function(objects) {
     const base = objects[0];
     const speakerLeft = objects[1];
     const speakerRight = objects[2];
     
     const baseDriverParameters = {
         durationMilliseconds: 400,
         loopCount: Infinity,
         mirror: true
     };
 
     const baseDriver = Animation.timeDriver(baseDriverParameters);
     baseDriver.start();
 
     const baseSampler = Animation.samplers.easeInQuint(0.9,1);
 
     const baseAnimation = Animation.animate(baseDriver,baseSampler);
 
     const baseTransform = base.transform;
 
     baseTransform.scaleX = baseAnimation;
     baseTransform.scaleY = baseAnimation;
     baseTransform.scaleZ = baseAnimation;
     
     const speakerDriverParameters = {
         durationMilliseconds: 200,
         loopCount: Infinity,
         mirror: true
     };
 
     const speakerDriver = Animation.timeDriver(speakerDriverParameters);
     speakerDriver.start();
 
     const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);
 
     const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);
 });

应用动画到扬声器

我们现在可以应用新的动画到两个扬声器对象,动画将用于改变他们的缩放比例。

脚本代码

 const speakerLeftTransform = speakerLeft.transform;
 speakerLeftTransform.scaleX = speakerAnimation;
 speakerLeftTransform.scaleY = speakerAnimation;
 speakerLeftTransform.scaleZ = speakerAnimation;

 const speakerRightTransform = speakerRight.transform;
 speakerRightTransform.scaleX = speakerAnimation;
 speakerRightTransform.scaleY = speakerAnimation;
 speakerRightTransform.scaleZ = speakerAnimation;

在使用缩放方法将 speakerAnimation 信号绑定到扬声器之前,要访问扬声器的变换。这意味着两个扬声器将以相同的方式进行动画。

脚本代码

const Animation = require('Animation');
 const Scene = require('Scene');
 
 const sceneRoot = Scene.root;
 
 // Existing code updated
 Promise.all([
     sceneRoot.findFirst('base_jnt'),
     sceneRoot.findFirst('speaker_left_jnt'),
     sceneRoot.findFirst('speaker_right_jnt')
 ])
 .then(function(objects) {
     const base = objects[0];
     const speakerLeft = objects[1];
     const speakerRight = objects[2];
     
     const baseDriverParameters = {
         durationMilliseconds: 400,
         loopCount: Infinity,
         mirror: true
     };
 
     const baseDriver = Animation.timeDriver(baseDriverParameters);
     baseDriver.start();
 
     const baseSampler = Animation.samplers.easeInQuint(0.9,1);
 
     const baseAnimation = Animation.animate(baseDriver,baseSampler);
 
     const baseTransform = base.transform;
 
     baseTransform.scaleX = baseAnimation;
     baseTransform.scaleY = baseAnimation;
     baseTransform.scaleZ = baseAnimation;
     
     const speakerDriverParameters = {
         durationMilliseconds: 200,
         loopCount: Infinity,
         mirror: true
     };
 
     const speakerDriver = Animation.timeDriver(speakerDriverParameters);
     speakerDriver.start();
 
     const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);
 
     const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);
     
     const speakerLeftTransform = speakerLeft.transform;
 
     speakerLeftTransform.scaleX = speakerAnimation;
     speakerLeftTransform.scaleY = speakerAnimation;
     speakerLeftTransform.scaleZ = speakerAnimation;
 
     const speakerRightTransform = speakerRight.transform;
 
     speakerRightTransform.scaleX = speakerAnimation;
     speakerRightTransform.scaleY = speakerAnimation;
     speakerRightTransform.scaleZ = speakerAnimation;
 });

保存你的脚本并返回 Spark AR Studio

现在,扬声器将在场景中动画起来。

69528694_1079588018903892_8484091505311481856_n.gif