我试图创建一个游戏,其中有一个动画角色,有多个动画来自Mixamo。我希望动画能够根据用户在游戏中所做的事情而改变,比如Walking、Running或Idle。下面是我如何加载FBX模型(没有动画):
loader.load('Assets/Animations/Main.fbx', function(object){
object.traverse(function (child){
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.frustumCulled = false;
}
});
object.rotation.x = Math.PI / 2
object.position.x = 11;
scene.add(object);
});我也有以下文件,它们是没有皮肤的动画。
Idle.fbx
Walking.fbx
Running.fbx我的目标是尝试制作类似这或这的东西。这两个链接的唯一问题是,在第一个链接中,它们使用的是一个带有多个动画的模型(我有一个没有皮肤的普通模型,有3个动画),在第二个链接中,代码是用TypeScript编写的(我更喜欢JavaScript)。
我是一个新手三维造型,所以我不知道如何把所有的动画没有皮肤的主要fbx模型。如何在混合器中将动画组合成一个模型,或者有什么方法可以在three.js?中完成?
我很感谢您的帮助,谢谢!
编辑:
据GuyNachshon说,这是我应该怎么处理的吗?
因此,首先,我加载没有动画的模型(yourMesh),并创建一个AnimationMixer
var mixer;
loader.load('Assets/Animations/Main.fbx', function(object){
object.traverse(function (child){
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.frustumCulled = false;
}
});
mixer = new THREE.AnimationMixer(object);
object.rotation.x = Math.PI / 2
object.position.x = 11;
scene.add(object);
});然后,我必须加载没有皮肤的3个动画文件,并将它们添加到animationsArray中。(不确定是否正确加载动画.):
loader.load('Assets/Animations/Idle.fbx', function(object){
object.traverse(function (child){
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.frustumCulled = false;
}
});
object.rotation.x = Math.PI / 2
object.position.x = 11;
animationsArray.push(object);
scene.add(object);
});
loader.load('Assets/Animations/Walking.fbx', function(object){
object.traverse(function (child){
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.frustumCulled = false;
}
});
object.rotation.x = Math.PI / 2
object.position.x = 11;
animationsArray.push(object);
scene.add(object);
});
loader.load('Assets/Animations/Running.fbx', function(object){
object.traverse(function (child){
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.frustumCulled = false;
}
});
object.rotation.x = Math.PI / 2
object.position.x = 11;
animationsArray.push(object);
scene.add(object);
});在全部加载完之后,我创建了actions
let actions = mixer.clipAction(animationsArray).play();但是,在你说了之后:
actions.play();那句台词要放什么?它会在animationsArray中播放第一个动画吗?
发布于 2022-04-14 18:04:10
您需要创建一个AnimationMixer。
因此,假设您已经创建了一个场景,添加了一个网格等等,现在您可以在一个动画混合器中使用它。
let mixer = new THREE.AnimationMixer(yourMesh);然后使用clipActions添加动画,
let actions = mixer.clipAction(animationsArray).play();现在玩吧
actions.play();但是要真正知道如何使用它,您应该阅读文档(附在上面:)
编辑-响应您的编辑
为了控制动画的播放,您可以做几件事情,下面是来自文档 的一个例子
const mixer = new THREE.AnimationMixer( mesh );
const clips = mesh.animations;
// Update the mixer on each frame
function update () {
mixer.update( deltaSeconds );
}
// Play a specific animation
const clip = THREE.AnimationClip.findByName( clips, 'dance' );
const action = mixer.clipAction( clip );
action.play();
// Play all animations
clips.forEach( function ( clip ) {
mixer.clipAction( clip ).play();
} );现在,如果您在构造代码时遇到了问题,下面是一个关于如何将动画附加到fbx并控制它们的一般示例:
let mixer = THREE.AnimationMixer
let modelReady = false
const animationActions = THREE.AnimationAction
let activeAction = THREE.AnimationAction
let lastAction = THREE.AnimationAction
const fbxLoader = new FBXLoader()在我们启动所需的一切之后,让我们加载所有内容:
fbxLoader.load(
(object) => {
'path/to/your/model.fbx',
object.scale.set(0.01, 0.01, 0.01)
mixer = new THREE.AnimationMixer(object)
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'default')
activeAction = animationActions[0] // sets current animation
scene.add(object) // adds animated object to your scene
//add an animation from another file
fbxLoader.load(
'path/to/animation.fbx',
(object) => {
console.log('loaded animation')
const animationAction = mixer.clipAction(.animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
//add an animation from another file
fbxLoader.load(
'path/to/other/animation.fbx',
(object) => {
console.log('loaded second animation')
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
//add an animation from another file
fbxLoader.load(
'path/to/animation.fbx',
(object) => {
console.log('loaded third animation');
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
modelReady = true
},
(xhr) => {
console.log(
(xhr.loaded / xhr.total) * 100 + '% loaded'
)
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)现在我们应该确定我们的动画和动作是什么:
const animations = {
function default() {
setAction(animationActions[0])
},
function firstAnimation() {
setAction(animationActions[1])
},
function sceondAnimation() {
setAction(animationActions[2])
},
function thirdAnimation() {
setAction(animationActions[3])
}
}
const setAction = {
if (toAction != activeAction) {
lastAction = activeAction
activeAction = toAction
//lastAction.stop()
lastAction.fadeOut(1)
activeAction.reset()
activeAction.fadeIn(1)
activeAction.play()
}
}让我们动起来!
const clock = new THREE.Clock()
function animate() {
requestAnimationFrame(animate)
controls.update()
if (modelReady) {mixer.update(clock.getDelta())}
render()
}
function render() {
renderer.render(scene, camera)
}
animate()把所有东西放在一起:
import * as THREE from 'three'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
let mixer = THREE.AnimationMixer
let modelReady = false
const animationActions = THREE.AnimationAction
let activeAction = THREE.AnimationAction
let lastAction = THREE.AnimationAction
const fbxLoader = new FBXLoader()
fbxLoader.load(
(object) => {
'path/to/your/model.fbx',
object.scale.set(0.01, 0.01, 0.01)
mixer = new THREE.AnimationMixer(object)
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'default')
activeAction = animationActions[0] // sets current animation
scene.add(object) // adds animated object to your scene
//add an animation from another file
fbxLoader.load(
'path/to/animation.fbx',
(object) => {
console.log('loaded animation')
const animationAction = mixer.clipAction(.animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
//add an animation from another file
fbxLoader.load(
'path/to/other/animation.fbx',
(object) => {
console.log('loaded second animation')
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
//add an animation from another file
fbxLoader.load(
'path/to/animation.fbx',
(object) => {
console.log('loaded third animation');
const animationAction = mixer.clipAction(animations[0])
animationActions.push(animationAction)
animationsFolder.add(animations, 'animationName')
modelReady = true
},
(xhr) => {
console.log(
(xhr.loaded / xhr.total) * 100 + '% loaded'
)
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
(error) => {
console.log(error)
}
)
const animations = {
function default() {
setAction(animationActions[0])
},
function firstAnimation() {
setAction(animationActions[1])
},
function sceondAnimation() {
setAction(animationActions[2])
},
function thirdAnimation() {
setAction(animationActions[3])
}
}
const setAction = {
if (toAction != activeAction) {
lastAction = activeAction
activeAction = toAction
//lastAction.stop()
lastAction.fadeOut(1)
activeAction.reset()
activeAction.fadeIn(1)
activeAction.play()
}
}
const clock = new THREE.Clock()
function animate() {
requestAnimationFrame(animate)
controls.update()
if (modelReady) {mixer.update(clock.getDelta())}
render()
}
function render() {
renderer.render(scene, camera)
}
animate()
https://stackoverflow.com/questions/71810443
复制相似问题