前言
该文章主要讲元宇宙虚拟空间的角色初始化,基本核心技术点,不多说,直接引入正题。
角色初始化
在调用渲染前,打印一下更新的列表
console.log(this.updatables);
this.render(this);;
这里看到有很多要更新的
这里我们来看一下角色Character的更新,首先是在CharacterSpawnPoint载入人物的模型,通过Character类对角色模型进行一个初始化
public spawn(loadingManager: LoadingManager, world: World): void { loadingManager.loadGLTF('build/assets/boxman.glb', (model) => { let player = new Character(model); let worldPos = new THREE.Vector3();this.object.getWorldPosition(worldPos);player.setPosition(worldPos.x, worldPos.y, worldPos.z); let forward = Utils.getForward(this.object);player.setOrientation(forward, true); world.add(player); player.takeControl(); }); }
Character初始化的内容,
constructor(gltf: any){//继承了THREE.Object3Dsuper();//根据模型动画数据设置动画this.readCharacterData(gltf);this.setAnimations(gltf.animations);//创建一个组方便管理和控制角色,THREE.Object3D是可以加入一个组的this.tiltContainer = new THREE.Group();this.add(this.tiltContainer);//在嵌套一层模型容器,更好控制动画和角色行为,最后把gltf的模型数据导入进来this.modelContainer = new THREE.Group();this.modelContainer.position.y = -0.57;this.tiltContainer.add(this.modelContainer);this.modelContainer.add(gltf.scene);//创建动画混合器this.mixer = new THREE.AnimationMixer(gltf.scene);//速度模拟器,选择模拟器this.velocitySimulator = new VectorSpringSimulator(60, this.defaultVelocitySimulatorMass, this.defaultVelocitySimulatorDamping);this.rotationSimulator = new RelativeSpringSimulator(60, this.defaultRotationSimulatorMass, this.defaultRotationSimulatorDamping);//视图向量(人物看哪里)this.viewVector = new THREE.Vector3();//人物的动作this.actions = {'up': new KeyBinding('KeyW'),'down': new KeyBinding('KeyS'),'left': new KeyBinding('KeyA'),'right': new KeyBinding('KeyD'),'run': new KeyBinding('ShiftLeft'),'jump': new KeyBinding('Space'),'use': new KeyBinding('KeyE'),'enter': new KeyBinding('KeyF'),'enter_passenger': new KeyBinding('KeyG'),'seat_switch': new KeyBinding('KeyX'),'primary': new KeyBinding('Mouse0'),'secondary': new KeyBinding('Mouse1'),};// 使用CapsuleCollider类,创建物理碰撞的角色胶囊this.characterCapsule = new CapsuleCollider({mass: 1,position: new CANNON.Vec3(),height: 0.5,radius: 0.25,segments: 8,friction: 0.0});// capsulePhysics.physical.collisionFilterMask = ~CollisionGroups.Trimesh;//设置能够碰撞的碰撞组(匹配)this.characterCapsule.body.shapes.forEach((shape) => {// tslint:disable-next-line: no-bitwiseshape.collisionFilterMask = ~CollisionGroups.TrimeshColliders;});//允许休眠this.characterCapsule.body.allowSleep = false;// 设置碰撞组this.characterCapsule.body.collisionFilterGroup = 2;// 是否禁止角色碰撞旋转this.characterCapsule.body.fixedRotation = true;//固定旋转this.characterCapsule.body.updateMassProperties();// debugconst boxGeo = new THREE.BoxGeometry(0.1, 0.1, 0.1);const boxMat = new THREE.MeshLambertMaterial({color: 0xff0000});this.raycastBox = new THREE.Mesh(boxGeo, boxMat);this.raycastBox.visible = false;//物理前/后步骤回调绑定this.characterCapsule.body.preStep = (body: CANNON.Body) => { this.physicsPreStep(body, this); };this.characterCapsule.body.postStep = (body: CANNON.Body) => { this.physicsPostStep(body, this); };// 更新角色状态(如待机)this.setState(new Idle(this));}
物体胶囊的形状,在CapsuleCollider类定义了3个球体胶囊叠加
constructor(options: any){let defaults = {mass: 0,position: new CANNON.Vec3(),height: 0.5,radius: 0.3,segments: 8,friction: 0.3};options = Utils.setDefaults(options, defaults);this.options = options;//创建物理材质,名字是自己取的let mat = new CANNON.Material('capsuleMat');mat.friction = options.friction;//创建胶囊的物理bodylet capsuleBody = new CANNON.Body({mass: options.mass,position: options.position});// 创建物理的球形let sphereShape = new CANNON.Sphere(options.radius);capsuleBody.material = mat;// sphereShape.material = mat;//给body设置形状,形状为3个球体叠加capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, 0, 0));capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, options.height / 2, 0));capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, -options.height / 2, 0));this.body = capsuleBody;}