动画
创建动画对象
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
混合参数
| 名称 | 类型 | 描述 | 是否可选 |
|---|---|---|---|
| target | any | 当前的动画的目标对象 | 否 |
| from | number | fps起始帧 | 否 |
| to | number | fps结束帧 | 否 |
| weight | number | 当前动画的权重,默认为1 | 是 |
| loop | boolean | 是否循环播放 | 是 |
| speedRatio | number | 动画播放速率,默认为1 | 是 |
| onAnimationEnd | () => void | 在动画结束时触发的事件,手动停止动画也会触发 | 是 |
| animatable | Animatable | 可选的特定动画 | 是 |
设置子动画覆盖属性
//可以同时为所有子动画指定一些常规属性,这些属性将覆盖默认的动画属性。
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);