您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
177 行
6.2 KiB
177 行
6.2 KiB
using System;
|
|
using Unity.Entities;
|
|
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(Skeleton))]
|
|
public class RagdollOwner : MonoBehaviour
|
|
{
|
|
public enum Phase
|
|
{
|
|
Inactive,
|
|
PoseSampled,
|
|
Active,
|
|
}
|
|
public Phase phase = Phase.Inactive;
|
|
|
|
[NonSerialized] public float timeUntilStart = 0.0f;
|
|
|
|
[Tooltip("The skeleton group of a Ragdoll Prefab")]
|
|
public GameObject m_RagdollPrefab;
|
|
public GameObject ragdollInstance;
|
|
|
|
public Skeleton ragdollSkeleton;
|
|
public Transform[] targeteBones;
|
|
public Vector3[] lastBonePositions;
|
|
public Quaternion[] lastBoneRotations;
|
|
}
|
|
|
|
|
|
[DisableAutoCreation]
|
|
public class HandleRagdollSpawn : InitializeComponentSystem<RagdollOwner>
|
|
{
|
|
public HandleRagdollSpawn(GameWorld gameWorld, GameObject systemRoot) : base(gameWorld)
|
|
{
|
|
m_SystemRoot = systemRoot;
|
|
}
|
|
|
|
protected override void Initialize(Entity entity, RagdollOwner ragdoll)
|
|
{
|
|
// Create ragdoll instance
|
|
ragdoll.ragdollInstance = GameObject.Instantiate(ragdoll.m_RagdollPrefab);
|
|
ragdoll.ragdollInstance.SetActive(false);
|
|
ragdoll.ragdollInstance.name = ragdoll.gameObject.name + "_Ragdoll";
|
|
|
|
if(m_SystemRoot != null)
|
|
ragdoll.ragdollInstance.transform.SetParent(m_SystemRoot.transform);
|
|
|
|
ragdoll.ragdollSkeleton = ragdoll.ragdollInstance.GetComponent<Skeleton>();
|
|
|
|
Skeleton targetSkeleton = ragdoll.GetComponent<Skeleton>();
|
|
|
|
int boneCount = ragdoll.ragdollSkeleton.bones.Length;
|
|
ragdoll.targeteBones = new Transform[boneCount];
|
|
ragdoll.lastBonePositions = new Vector3[boneCount];
|
|
ragdoll.lastBoneRotations = new Quaternion[boneCount];
|
|
|
|
for (var i = 0; i < ragdoll.ragdollSkeleton.bones.Length; i++)
|
|
{
|
|
var targetBoneIndex = targetSkeleton.GetBoneIndex(ragdoll.ragdollSkeleton.nameHashes[i]);
|
|
if (targetBoneIndex == -1)
|
|
{
|
|
// GameDebug.LogError("Ragdoll bone could not be mapped. Bone name:" + ragdoll.ragdollSkeleton.m_Bones[i].name);
|
|
continue;
|
|
}
|
|
|
|
ragdoll.targeteBones[i] = targetSkeleton.bones[targetBoneIndex];
|
|
}
|
|
}
|
|
|
|
readonly GameObject m_SystemRoot;
|
|
}
|
|
|
|
|
|
[DisableAutoCreation]
|
|
public class HandleRagdollDespawn : DeinitializeComponentSystem<RagdollOwner>
|
|
{
|
|
public HandleRagdollDespawn(GameWorld gameWorld) : base(gameWorld)
|
|
{}
|
|
|
|
protected override void Deinitialize(Entity entity, RagdollOwner ragdoll)
|
|
{
|
|
GameObject.Destroy(ragdoll.ragdollInstance);
|
|
}
|
|
}
|
|
|
|
|
|
[DisableAutoCreation]
|
|
public class UpdateRagdolls : BaseComponentSystem<RagdollOwner, RagdollState>
|
|
{
|
|
public UpdateRagdolls(GameWorld gameWorld) : base(gameWorld) {}
|
|
|
|
protected override void Update(Entity entity, RagdollOwner ragdollOwner, RagdollState ragdollState)
|
|
{
|
|
GameDebug.Assert(ragdollOwner.ragdollInstance != null, "Ragdoll instance is NULL for object: {0}", ragdollOwner.gameObject);
|
|
|
|
if (!ragdollState.ragdollActive)
|
|
return;
|
|
|
|
switch (ragdollOwner.phase)
|
|
{
|
|
case RagdollOwner.Phase.Inactive:
|
|
|
|
ragdollOwner.timeUntilStart -= m_world.frameDuration;
|
|
|
|
if(ragdollOwner.timeUntilStart <= m_world.worldTime.tickInterval)
|
|
{
|
|
// Store bone transforms so they can be used to calculate bone velocity next frame
|
|
for (int boneIndex = 0; boneIndex < ragdollOwner.targeteBones.Length; boneIndex++)
|
|
{
|
|
if (ragdollOwner.targeteBones[boneIndex] == null)
|
|
continue;
|
|
|
|
ragdollOwner.lastBonePositions[boneIndex] = ragdollOwner.targeteBones[boneIndex].position;
|
|
ragdollOwner.lastBoneRotations[boneIndex] = ragdollOwner.targeteBones[boneIndex].rotation;
|
|
}
|
|
|
|
ragdollOwner.phase = RagdollOwner.Phase.PoseSampled;
|
|
}
|
|
|
|
break;
|
|
case RagdollOwner.Phase.PoseSampled:
|
|
|
|
IntializeRagdoll(ragdollOwner, true, ragdollState.impulse);
|
|
ragdollOwner.phase = RagdollOwner.Phase.Active;
|
|
|
|
break;
|
|
case RagdollOwner.Phase.Active:
|
|
|
|
for (int boneIndex = 0; boneIndex < ragdollOwner.targeteBones.Length; boneIndex++)
|
|
{
|
|
if (ragdollOwner.targeteBones[boneIndex] == null)
|
|
continue;
|
|
|
|
ragdollOwner.targeteBones[boneIndex].position = ragdollOwner.ragdollSkeleton.bones[boneIndex].position;
|
|
ragdollOwner.targeteBones[boneIndex].rotation = ragdollOwner.ragdollSkeleton.bones[boneIndex].rotation;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void IntializeRagdoll(RagdollOwner ragdollOwner, bool useAnimSpeed, Vector3 impulse)
|
|
{
|
|
ragdollOwner.ragdollInstance.SetActive(true);
|
|
|
|
// Setup ragdoll
|
|
var invFrameTime = 1.0f / m_world.frameDuration;
|
|
for (int boneIndex = 0; boneIndex < ragdollOwner.targeteBones.Length; boneIndex++)
|
|
{
|
|
if (ragdollOwner.targeteBones[boneIndex] == null)
|
|
continue;
|
|
|
|
// Set start position
|
|
var position = ragdollOwner.targeteBones[boneIndex].position;
|
|
var rotation = ragdollOwner.targeteBones[boneIndex].rotation;
|
|
ragdollOwner.ragdollSkeleton.bones[boneIndex].position = position;
|
|
ragdollOwner.ragdollSkeleton.bones[boneIndex].rotation = rotation;
|
|
|
|
// Set bone velocity
|
|
var rigidBody = ragdollOwner.ragdollSkeleton.bones[boneIndex].GetComponent<Rigidbody>();
|
|
if (rigidBody == null)
|
|
continue;
|
|
|
|
if (useAnimSpeed)
|
|
{
|
|
var torque = (Quaternion.Inverse(ragdollOwner.lastBoneRotations[boneIndex]) * rotation).eulerAngles * invFrameTime;
|
|
rigidBody.AddTorque(torque, ForceMode.VelocityChange);
|
|
}
|
|
|
|
var velocity = Vector3.zero;
|
|
//velocity += (position - ragdollOwner.lastBonePositions[boneIndex]) * invFrameTime;
|
|
velocity += impulse;
|
|
rigidBody.AddForce(velocity, ForceMode.VelocityChange);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|