该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

157 行
6.2 KiB

using Unity.Animation;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics.Systems;
using Unity.Sample.Core;
using Unity.Transforms;
using UnityEngine.Profiling;
public class RigAttacher
{
public struct AttachEntity : IComponentData
{
public Entity Value;
}
public struct AttachBone : IComponentData
{
public RuntimeBoneReference Value;
}
public struct State : IComponentData
{
public static State Default => new State { LastMappedBoneRef = RuntimeBoneReference.Default, boneIndex = -1,};
public Entity rigEntity;
public RuntimeBoneReference LastMappedBoneRef;
public int boneIndex;
}
public static void AddRigAttacher(Entity entity, EntityManager dstManager, RuntimeBoneReference boneRef)
{
var attachBone = new AttachBone
{
Value = boneRef,
};
dstManager.AddComponentData(entity, attachBone);
dstManager.AddComponentData(entity, State.Default);
if(dstManager.HasComponent<Static>(entity))
dstManager.AddComponentData(entity,new Static());
if(dstManager.HasComponent<Static>(entity))
dstManager.AddComponentData(entity,new Static());
if(dstManager.HasComponent<Parent>(entity))
dstManager.RemoveComponent<Parent>(entity);
}
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(AnimationSystemGroup))]
[UpdateBefore(typeof(TransformSystemGroup))]
[UpdateBefore(typeof(BuildPhysicsWorld))]
[AlwaysSynchronizeSystem]
public class Update : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
// TODO (mogensh) When all rig remapping happens we animstream, we no longer need to handle rig change
Profiler.BeginSample("RigAttach.HandleChange");
Entities
.WithoutBurst() // EntityManager.Exists() and EntityManager.GetSharedComponentData() are not Burst-compatible
.ForEach((Entity entity, ref AttachEntity attachEntity, ref AttachBone attachBone, ref State state) =>
{
if (!EntityManager.Exists(attachEntity.Value))
{
GameDebug.LogWarning(World,"Attach entity:{0}" + attachEntity.Value + " does no longer exist");
return;
}
// TODO (mogensh) dont check this every frame. Instead
// Find bone index
if (!attachBone.Value.Equals(state.LastMappedBoneRef) ||
attachEntity.Value != state.rigEntity)
{
if (attachEntity.Value != Entity.Null)
{
Profiler.BeginSample("GetSharedRigDef");
var sharedRigDef = EntityManager.GetSharedComponentData<SharedRigDefinition>(attachEntity.Value);
Profiler.EndSample();
if (attachBone.Value.ReferenceRig.Value.GetHashCode() == sharedRigDef.Value.Value.GetHashCode())
{
state.boneIndex = attachBone.Value.BoneIndex;
}
else
{
Profiler.BeginSample("GetOrCreateRigMapping");
BlobAssetReference<AnimationAssetDatabase.RigMap> rigMap;
AnimationAssetDatabase.GetOrCreateRigMapping(World, attachBone.Value.ReferenceRig, sharedRigDef.Value, out rigMap);
Profiler.EndSample();
state.boneIndex = rigMap.Value.BoneMap[attachBone.Value.BoneIndex];
}
}
else
{
state.boneIndex = -1;
}
state.LastMappedBoneRef = attachBone.Value; // new RuntimeBoneReference(attachBone.Value);
state.rigEntity = attachEntity.Value;
}
}).Run();
Profiler.EndSample();
var AnimatedLocalToWorldFromEntity = GetBufferFromEntity<AnimatedLocalToWorld>(true);
var LocalToParentFromEntity = GetComponentDataFromEntity<LocalToParent>(true);
Profiler.BeginSample("RigAttach.Move");
Entities
.WithReadOnly(AnimatedLocalToWorldFromEntity)
.WithReadOnly(LocalToParentFromEntity)
.ForEach((Entity entity, ref LocalToWorld localToWorld, ref Translation translation, ref Rotation rotation,
in AttachEntity attachEntity, in AttachBone attachBone, in State state) =>
{
if (!AnimatedLocalToWorldFromEntity.Exists(attachEntity.Value))
{
//GameDebug.LogWarning(World, string.Format("RigAttacher:{0} attacheEntity:{1} has not AnimatedLocalToWorld", entity,attachEntity.Value));
return;
}
// Move
if (state.boneIndex != -1)
{
var localToWorldBuffer = AnimatedLocalToWorldFromEntity[attachEntity.Value];
var boneLocalToWorld = localToWorldBuffer[state.boneIndex].Value;
if (LocalToParentFromEntity.HasComponent(entity))
{
var attacherLocalToParent = LocalToParentFromEntity[entity];
boneLocalToWorld = math.mul(boneLocalToWorld, attacherLocalToParent.Value);
}
localToWorld = new LocalToWorld
{
Value = boneLocalToWorld
};
// TODO (mogensh) Unity.Physics uses translation+rotation as input so they also need to be set.
translation = new Translation
{
Value = boneLocalToWorld.c3.xyz,
};
rotation = new Rotation
{
Value = new quaternion(boneLocalToWorld),
};
}
}).Run();
Profiler.EndSample();
return default;
}
}
}