栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 游戏开发 > Unity3D

Babylon.js 深入 - 第 1 章 - 动画(2)

Unity3D 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Babylon.js 深入 - 第 1 章 - 动画(2)

Babylon.js 深入 - 第 1 章 - 动画(2) 动画

动画可以让您的游戏或应用程序栩栩如生。在 Babylon.js 中制作动画有两种主要方式。您可以在渲染周期期间更改场景中对象的属性,我们将在之后看一看 Animation 方法的描述。

排序动画

组合多个剪辑以形成动画的一种直接方法是为每个动画剪辑指定开始时间。

设计 概述

摄像机显示一栋带门的建筑物。摄像机靠近门并停了下来。门打开,摄像机进入房间。当摄像机进入房间时,房间里的灯亮了。门关上,摄像机环顾四周。

由于目的是展示如何制作剪辑,房间和门将简单地使用没有纹理的网格制作。

表演者

Camera - 相机 - 通用
Door - 门 - 铰链在右侧,向内打开
Spot Lights - 聚光灯 - 用球体显示位置

序列时间表

为每个表演者创建一个动画,其中包含每个定时事件的关键点。

动画 对于相机

移动相机会改变相机的位置(vector3)。相机环顾四周是围绕 y 轴(float)的旋转。

由于动画只能更改一个属性,因此相机需要两个动画。

移动摄像机的关键点将在时间 0 开始,摄像机将开始远离建筑物并上下移动,直到它在 3 秒的时间刚好在门外。
当门打开时,摄像机将保持其位置 2 秒,然后在 5 秒时将向前移动到与门成一定角度的房间,在 8 秒时停止。

相机在 9 秒时不旋转,然后相机将在 14 秒时旋转 180 度以面对门。

相机的关键点的值将是它在 0、 3、 5 和 8 秒处的帧中的位置以及它在 0、 9 和 14 秒处的帧中的旋转。

// 让相机向前移动
var movein = new BABYLON.Animation(
    "movein",
    "position",
    frameRate,
    BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
    BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
var movein_keys = [];
movein_keys.push({
    frame: 0,
    value: new BABYLON.Vector3(0, 5, -30)
});
movein_keys.push({
    frame: 3 * frameRate,
    value: new BABYLON.Vector3(0, 2, -10)
});
movein_keys.push({
    frame: 5 * frameRate,
    value: new BABYLON.Vector3(0, 2, -10)
});
movein_keys.push({
    frame: 8 * frameRate,
    value: new BABYLON.Vector3(-2, 2, 3)
});
movein.setKeys(movein_keys);
// 让相机扫一圈
var rotate = new BABYLON.Animation(
    "rotate",
    "rotation.y",
    frameRate,
    BABYLON.Animation.ANIMATIONTYPE_FLOAT,
    BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
var rotate_keys = [];
rotate_keys.push({
    frame: 0,
    value: 0
});
rotate_keys.push({
    frame: 9 * frameRate,
    value: 0
});
rotate_keys.push({
    frame: 14 * frameRate,
    value: Math.PI
});
rotate.setKeys(rotate_keys);
对于门

门以 y 轴为轴围绕铰链进行旋转。打开和关闭门的旋转将分别需要 2 秒。

关键点是 0、 3、 5、 13 和 15 秒。

关键点的值将是它在关键点处的帧中围绕 y 轴的旋转。

// 用于打开和关闭门
var sweep = new BABYLON.Animation(
    "sweep",
    "rotation.y",
    frameRate,
    BABYLON.Animation.ANIMATIONTYPE_FLOAT,
    BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
var sweep_keys = [];
sweep_keys.push({
    frame: 0,
    value: 0
});
sweep_keys.push({
    frame: 3 * frameRate,
    value: 0
});
sweep_keys.push({
    frame: 5 * frameRate,
    value: Math.PI / 3
});
sweep_keys.push({
    frame: 13 * frameRate,
    value: Math.PI / 3
});
sweep_keys.push({
    frame: 15 * frameRate,
    value: 0
});
sweep.setKeys(sweep_keys);
对于灯光

灯光的强度会有所不同。这需要一系列聚光灯的数组。

灯的关键点是保持关闭到 7 秒,在 10 秒达到全强度,直到 14 秒熄灭。

// 让光线变亮变暗
var lightDimmer = new BABYLON.Animation(
    "dimmer",
    "intensity",
    frameRate,
    BABYLON.Animation.ANIMATIONTYPE_FLOAT,
    BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
var light_keys = [];
light_keys.push({
    frame: 0,
    value: 0
});
light_keys.push({
    frame: 7 * frameRate,
    value: 0
});
light_keys.push({
    frame: 10 * frameRate,
    value: 1
});
light_keys.push({
    frame: 14 * frameRate,
    value: 1
});
light_keys.push({
    frame: 15 * frameRate,
    value: 0
});
lightDimmer.setKeys(light_keys);
卡通片

现在只需同时运行所有剪辑:

scene.beginDirectAnimation(camera, [movein, rotate], 0, 25 * frameRate, false);
scene.beginDirectAnimation(hinge, [sweep], 0, 25 * frameRate, false);
scene.beginDirectAnimation(
    spotLights[0],
    [lightDimmer],
    0,
    25 * frameRate,
    false
);
scene.beginDirectAnimation(
    spotLights[1],
    [lightDimmer.clone()],
    0,
    25 * frameRate,
    false
);

完成的动画序列示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



分组动画

AnimationGroup 允许您将动画和网格链接在一起并作为一个动画组播放、暂停和停止它们。

组成一个动画组

例如创建了animation1、 animation2 和 animation3 以及网格 mesh1、 mesh2、 mesh3 和 mesh4,您可以形成以下动画组:

var animationGroup1 = new BABYLON.AnimationGroup("Group1");
var animationGroup2 = new BABYLON.AnimationGroup("Group2");

然后使用 addTargetedAnimation 方法将动画与网格链接起来,并将它们添加到组中:

animationGroup1.addTargetedAnimation(animation1, mesh1);
animationGroup1.addTargetedAnimation(animation3, mesh1);
animationGroup1.addTargetedAnimation(animation2, mesh2);
animationGroup2.addTargetedAnimation(animation2, mesh3);
animationGroup2.addTargetedAnimation(animation1, mesh4);
animationGroup2.addTargetedAnimation(animation2, mesh4);
animationGroup2.addTargetedAnimation(animation3, mesh4);

由于动画可能是使用不同的时间线创建的,因此必须使用 normalize 规范这些动画。

规范化动画组

可能 animation1、 animation2 和 animation3 都是使用不同帧数创建的。例如,animation1 可能从第 0 帧到第 80 帧,animation2 从第 0 帧到第 75 帧,animation3 从第 0 帧到第 100 帧。您可以使用 normalize 方法使所有动画的帧数相同,如:

animationGroup2.normalize(0, 100);

一般来说,规范化的参数是数字 beginFrame 和 endFrame。

beginFrame - 开始帧编号 - 必须小于或等于所有动画的最小开始帧,以上示例不大于 0。
endFrame - 结束帧编号 - 必须大于或等于所有动画的最大结束帧,以上示例不小于 100。

动画组 1 的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



动画组 2 的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



动画组 3 的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



动画组的速率比

可以设置组中所有动画的 speedRatio 来加快或减慢动画播放,例如:

animationGroup1.speedRatio = 0.25;
animationGroup2.speedRatio = 3;

动画组速率比的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



从现有动画创建动画组

您可以通过枚举动画表中包含的动画来从动画表中创建新的 AnimationGroup:

var animationGroup = new BABYLON.AnimationGroup("my-animation-group");
for (anim of idleAnim.getAnimations()) {
    animationGroup.addTargetedAnimation(anim.animation, anim.target);
}

从 Animatable 创建 AnimationGroup 的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



在动画组结束时

onAnimationEndObservable 可以用来在动画组结束时触发一个函数:

animationGroup1.onAnimationEndObservable.add(function () {
    mesh2.material = redMaterial;
});

动画组结束的示例:

示例链接

示例代码:





    
    Babylon.js sample code
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    



    
    



在动画组循环时

onAnimationLoopObservable 可用于在动画组循环时触发一个函数:

animationGroup1.onAnimationLoopObservable.add(function (targetAnimation) {
    console.log(targetAnimation.animation.name);
});

onAnimationGroupLoopObservable 可用于在动画组的所有动画循环播放时触发一个函数:

animationGroup1.onAnimationGroupLoopObservable.add(function (group) {
    console.log("Group looped!");
});
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/899667.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号