babylonjs 动画

1,046 阅读3分钟

动画

创建动画对象

const myAnim = new BABYLON.Animation("tutoAnimation", //动画名称
"rotation.y", //动画涉及属性
30,//每秒帧数
BABYLON.Animation.ANIMATIONTYPE_FLOAT,//动画涉及属性的数据类型,用于插值
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);//动画循环模式

动画涉及的数据属性可以设置为以下几种:
BABYLON.Animation.ANIMATIONTYPE_COLOR3 颜色
BABYLON.Animation.ANIMATIONTYPE_FLOAT 数字
BABYLON.Animation.ANIMATIONTYPE_MATRIX 矩阵(矩阵默认不插值,但可以手动设置BABYLON.Animation.AllowMatricesInterpolation = true来激活插值,并可通过设置 BABYLON.Animation.AllowMatrixDecomposeForInterpolation = true 来使用Matrix.DecomposeLerp代替默认的Matrix.Lerp进行插值,这样会让插值过程变得更慢但更精确。)
BABYLON.Animation.ANIMATIONTYPE_QUATERNION 四元数
BABYLON.Animation.ANIMATIONTYPE_VECTOR2 二维矢量
BABYLON.Animation.ANIMATIONTYPE_VECTOR3 三维矢量\

动画循环模式可设置为以下几种:
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE 在动画结束后回到初始值进行循环 BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT 在动画结束后不进行循环
BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE 在动画结束后以当前值为基础继续进行运算\

为动画添加关键帧

    keys = [];
    keys.push({
        frame: 0,//当前关键帧
        value: 0//当前关键帧时属性的值
    });

    keys.push({
        frame: 40,
        value: Math.PI
    });

    keys.push({
        frame: 80,
        value: 0
    });

    myAnim.setKeys(keys);

设置动画并播放

    mesh.animations.push(myAnim)
    const animatable = scene.beginAnimation(mesh, //目标模型
    from,//起始帧
    to,//结束帧
    true);//是否循环播放
    
    //也可以这样设置动画并播放
    const animatable = scene.beginDirectAnimation(mesh, [myAnim], from, to, true)
    //或者更简单
    const animatable = BABYLON.Animation.CreateAndStartAnimation(名称,目标,属性,帧率,总帧数,起始值,终值);
    
    //之后可以通过animatable对象a中的方法来控制动画
    animatable.pause()//暂停
    animatable.restart()//继续
    animatable.stop()//停止
    animatable.reset()//从初始状态重新开始
    
    //通过promise等待动画结束
    await animatable.waitAsync();

动画组

创建动画组

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

//向组内添加动画
animationGroup1.addTargetedAnimation(animation1, mesh1);
animationGroup1.addTargetedAnimation(animation2, mesh2);

//把已有的animatable中的动画添加到动画组
for (anim of animatable.getAnimations()) {
    animationGroup1.addTargetedAnimation(anim.animation, anim.target);
}

//设置统一起始和结束帧
animationGroup2.normalize(0, 100);

动画组参数设置

//动画播放速率
animationGroup1.speedRatio = 0.25;
animationGroup2.speedRatio = 3;

//添加结束事件
animationGroup1.onAnimationEndObservable.add(function() {
  mesh2.material = redMaterial;
});

//添加动画循环事件
animationGroup1.onAnimationLoopObservable.add(function(targetAnimation) {
  console.log(targetAnimation.animation.name);
});

//添加动画组循环事件
animationGroup1.onAnimationGroupLoopObservable.add(function(group) {
  console.log("Group looped!");
});

高级设置

混合动画

按照设置的权重对同一目标上的动画进行混合。

// 混合权重为1
var idleAnim = scene.beginWeightedAnimation(skeleton, 0, 89, 1.0, true);
// 混合权重为0
var walkAnim = scene.beginWeightedAnimation(skeleton, 90, 124, 0, true);
// 混合权重为0
var runAnim = scene.beginWeightedAnimation(skeleton, 125, 146, 0, true);

idleAnim.weight = 0.5;
runAnim.weight = 0.5

混合参数

名称类型描述是否可选
targetany当前的动画的目标对象
fromnumberfps起始帧
tonumberfps结束帧
weightnumber当前动画的权重,默认为1
loopboolean是否循环播放
speedRationumber动画播放速率,默认为1
onAnimationEnd() => void在动画结束时触发的事件,手动停止动画也会触发
animatableAnimatable可选的特定动画

设置子动画覆盖属性

//可以同时为所有子动画指定一些常规属性,这些属性将覆盖默认的动画属性。
var overrides = new BABYLON.AnimationPropertiesOverride();

overrides.enableBlending = true;
overrides.blendingSpeed = 0.1;

skeleton.animationPropertiesOverride = overrides;

可覆盖属性:

  • enableBlending
  • blendingSpeed
  • loopMode

缓动补间函数设置

可以对缓动补间函数进行设置 以下是可用的缓动函数:

  • BABYLON.CircleEase()
  • BABYLON.BackEase(amplitude)
  • BABYLON.BounceEase(bounces, bounciness)
  • BABYLON.CubicEase()
  • BABYLON.ElasticEase(oscillations, springiness)
  • BABYLON.ExponentialEase(exponent)
  • BABYLON.PowerEase(power)
  • BABYLON.QuadraticEase()
  • BABYLON.QuarticEase()
  • BABYLON.QuinticEase()
  • BABYLON.SineEase()
  • BABYLON.BezierCurveEase() 并可以通过EasingMode设置缓动函数的运行方式:
  • BABYLON.EasingFunction.EASINGMODE_EASEIN :插值遵循与缓动函数关联的数学公式。
  • BABYLON.EasingFunction.EASINGMODE_EASEOUT :插值遵循100%插值减去与缓动函数关联的公式的输出。
  • BABYLON.EasingFunction.EASINGMODE_EASEINOUT :Interpolation在动画的前半部分使用EaseIn,在下半部分使用EaseOut。
// 设置缓动函数
var easingFunction = new BABYLON.CircleEase();


// 设置函数的运行方式
easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);


// 将缓动函数运用到动画中
animationTorus.setEasingFunction(easingFunction);

触发事件设置

//可以为动画添加触发事件
var event1 = new BABYLON.AnimationEvent(
  50,//在哪帧触发
  function () {
    console.log("Yeah!");
  },//事件函数
  true,//是否只触发一次,默认为false
);
// 添加事件到动画
animation.addEvent(event1);

确定性锁步

让在同一环境中的所有的动画,物理和游戏逻辑都都按照统一的帧率精确同步(通常用于实现多客户端间场景的同步或是历史场景的精确回放)

//删除默认引擎
delete engine;
//引擎设置
this.engine = new BABYLON.Engine(theCanvas, true, {
  deterministicLockstep: true,
  lockstepMaxSteps: 4,
});
//为场景使用新引擎设置
var scene = new BABYLON.Scene(engine);
//设置物理引擎的重力与帧间隔
var physEngine = new BABYLON.CannonJSPlugin(false);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), physEngine);
physEngine.setTimeStep(1/60);

完整例子:playground.babylonjs.com/#DU4FPJ#3