This commit is contained in:
2026-07-14 11:44:07 +08:00
commit 4409c7b031
5906 changed files with 6959792 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
import { _decorator, Collider, Component, Material, Node, PhysicsGroup, PhysicsSystem, RigidBody, SkinnedMeshRenderer, SphereCollider } from 'cc';
import { RagdollBone } from './RagdollBone';
import { RagdollConstraint } from './RagdollConstraint';
import { GameController } from '../scripts/GameController';
import { AudioMgr } from '../scripts/framework/audio/AudioMgr';
import { AssetController } from '../scripts/AssetController';
const { ccclass, property } = _decorator;
@ccclass('Ragdoll')
export class Ragdoll extends Component {
@property(Node)
rootNode: Node = null;
@property(Node)
centerNode: Node = null;
@property(SkinnedMeshRenderer)
renderer: SkinnedMeshRenderer = null;
@property(Material)
siwang: Material; // 新的材质
private realBones: Array<Node> = [];
private simuBones: Array<Node> = [];
private simuBoneJointArr: Array<CANNON.ConeTwistConstraint> = [];
private world: any;
private isEnabled: boolean = false;
start() {
this.world = PhysicsSystem.instance.physicsWorld.impl;
this.initRagdoll()
}
private initRagdoll() {
// 压入真实骨骼
this.getAllRealBones(this.rootNode)
// 创建模拟骨骼
this.createSimuBones();
// 创建模拟骨骼的关节
this.createSimuBoneJoints();
}
createSimuBones() {
for (let boneNode of this.realBones) {
let node = new Node
node.addComponent(SphereCollider).radius = 0.2 * node.worldScale.x
node.addComponent(RigidBody)
this.node.addChild(node)
this.simuBones.push(node)
this.syncPositionAndRotation(node, boneNode)
// 同步之后将位置赋给初始位置
let ragdollBone = boneNode.getComponent(RagdollBone)
ragdollBone.simuNode = node
ragdollBone.initPos = boneNode.getPosition();
ragdollBone.initRot = boneNode.getRotation();
}
this.scheduleOnce(() => {
for (let bone of this.simuBones) {
let body = bone.getComponent(RigidBody)
body.sleep()
}
}, 0)
}
createSimuBoneJoints() {
for (let boneNode of this.realBones) {
const joint = boneNode.getComponent(RagdollConstraint)
if (joint) {
const simuNodeA = boneNode.getComponent(RagdollBone).simuNode
const simuNodeB = joint.connectedBone.getComponent(RagdollBone).simuNode
const bodyA = simuNodeA.getComponent(RigidBody).body.impl
const bodyB = simuNodeB.getComponent(RigidBody).body.impl
let spineJoint = new CANNON.ConeTwistConstraint(bodyA, bodyB, {
pivotA: new CANNON.Vec3(joint.pivotA.x, joint.pivotA.y, joint.pivotA.z),
pivotB: new CANNON.Vec3(joint.pivotB.x, joint.pivotB.y, joint.pivotB.z),
axisA: new CANNON.Vec3(joint.axisA.x, joint.axisA.y, joint.axisA.z),
axisB: new CANNON.Vec3(joint.axisB.x, joint.axisB.y, joint.axisB.z),
angle: joint.angle,
twistAngle: joint.twistAngle
})
this.world.addConstraint(spineJoint)
this.simuBoneJointArr.push(spineJoint)
}
}
}
getAllRealBones(node: Node) {
let bones = node.children;
for (let boneNode of bones) {
const bone = boneNode.getComponent(RagdollBone)
if (bone) {
this.realBones.push(boneNode)
bone.ragdoll = this
}
this.getAllRealBones(boneNode)
}
}
lateUpdate(deltaTime: number) {
if (this.isEnabled) {
this.updateBones()
}
}
syncPositionAndRotation(nodeA: Node, nodeB: Node) {
nodeA.setWorldPosition(nodeB.worldPosition)
nodeA.setWorldRotation(nodeB.worldRotation)
}
// 将模拟骨骼的位置和转角同步到真实骨骼
private updateBones() {
for (let i = 0; i < this.realBones.length; i++) {
this.syncPositionAndRotation(this.realBones[i], this.simuBones[i])
}
}
getEnabled() {
return this.isEnabled;
}
setEnabled(isEnabled: boolean) {
if (isEnabled && this.isDie) return
isEnabled ? this.enableRagdoll() : this.disableRagdoll();
AudioMgr.inst.playOneShot(AssetController.instance.die)
}
isDie: boolean = false
enableRagdoll() {
this.isDie = true
GameController.getInstance().curLevel.onEnemyDie(this)
// this.renderer.setMaterialInstance(this.siwang, 0)
this.renderer.material = this.siwang
// 将模拟骨骼的位置和真实骨骼同步
for (let bone of this.realBones) {
let ragdollBone = bone.getComponent(RagdollBone)
this.syncPositionAndRotation(ragdollBone.simuNode, bone)
let collider = ragdollBone.getComponent(Collider)
if (collider)
collider.enabled = false
}
for (let bone of this.simuBones) {
let body = bone.getComponent(RigidBody)
body.wakeUp();
}
// 将关节添加至物理世界
for (let joint of this.simuBoneJointArr) {
this.world.addConstraint(joint);
}
this.isEnabled = true;
}
disableRagdoll() {
// 将真实骨骼移动至初始位置
for (let bone of this.realBones) {
let ragdollBone = bone.getComponent(RagdollBone);
bone.setPosition(ragdollBone.initPos);
bone.setRotation(ragdollBone.initRot);
}
for (let bone of this.simuBones) {
let body = bone.getComponent(RigidBody)
body.sleep();
}
// 从物理世界中移除关节
for (let joint of this.simuBoneJointArr) {
this.world.removeConstraint(joint);
}
this.isEnabled = false;
}
}