Skip to content

Instantly share code, notes, and snippets.

@tsubaki
Last active March 29, 2020 16:33
Show Gist options
  • Save tsubaki/9f5841aae552965b9e90c72475001dc0 to your computer and use it in GitHub Desktop.
Save tsubaki/9f5841aae552965b9e90c72475001dc0 to your computer and use it in GitHub Desktop.
UnityPhysics 0.3.1と Entities 0.8.0 の組み合わせ
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;
using static Unity.Entities.ComponentType;
namespace BallSystems
{
// ボール
[GenerateAuthoringComponent]
public struct Ball : IComponentData
{
public float Lifetime; // 接触時にLifeTimeに渡す値
}
// ボールの生存時間
// 本system郡でのみ使用する
struct Lifetime : IComponentData
{
public float Value; // 生存時間、0になったら死ぬ
}
// ボールが接触したら1秒後に破棄するシステム
public class BallHitSystem : SystemBase
{
EntityCommandBufferSystem _commandSystem;
BuildPhysicsWorld _buildPhysicsWorldSystem;
StepPhysicsWorld _stepPhysicsWorldSystem;
protected override void OnCreate()
{
_commandSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
_buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
_stepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
}
protected override void OnUpdate()
{
// 当たり判定からLifetimeを追加するジョブを実行
// 普通にITriggerEventsJobのジョブを実行。依存関係はthis.Dependencyで取得
Dependency = new HitEventJob
{
balls = GetComponentDataFromEntity<Ball>(true),
lifetimes = GetComponentDataFromEntity<Lifetime>(true),
commands = _commandSystem.CreateCommandBuffer()
}.Schedule(_stepPhysicsWorldSystem.Simulation, ref _buildPhysicsWorldSystem.PhysicsWorld, Dependency);
_commandSystem.AddJobHandleForProducer(Dependency);
}
// 接触判定
[Unity.Burst.BurstCompile]
struct HitEventJob : ITriggerEventsJob
{
[ReadOnly] public ComponentDataFromEntity<Ball> balls;
[ReadOnly] public ComponentDataFromEntity<Lifetime> lifetimes;
public EntityCommandBuffer commands;
public void Execute(TriggerEvent triggerEvent)
{
if (HasBallTagWithoutInterval(triggerEvent.Entities.EntityA))
DoProcess(triggerEvent.Entities.EntityA);
if (HasBallTagWithoutInterval(triggerEvent.Entities.EntityB))
DoProcess(triggerEvent.Entities.EntityB);
}
// Ballを持ちlieftimeを持っていない場合にTrueを返す
private bool HasBallTagWithoutInterval(Entity entity)
{
return balls.Exists(entity) && !lifetimes.Exists(entity);
}
// 接触時の処理を実行
public void DoProcess(Entity entity)
{
commands.AddComponent(entity, new Lifetime { Value = balls[entity].Lifetime });
}
}
}
public class BallLifetimeSystem : SystemBase
{
EntityCommandBufferSystem _commandSystem;
protected override void OnCreate()
{
_commandSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
protected override void OnUpdate()
{
// Entities.ForEach的に、システムで使用するデータは全てローカル変数として書き出しておく
var commands = _commandSystem.CreateCommandBuffer();
var dt = Time.DeltaTime;
// LifetimeをチェックしてEntityを破棄するジョブを実行
Entities
.ForEach((Entity entity, ref Lifetime interval) =>
{
interval.Value -= dt;
if (interval.Value < 0)
{
commands.DestroyEntity(entity);
}
}).Schedule();
_commandSystem.AddJobHandleForProducer(Dependency);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment