Instantly share code, notes, and snippets.
Created
January 11, 2020 08:19
-
Star
(2)
2
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save thelebaron/67ac2e81ffe947ee26ae5365dbbe3a84 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Game.Components; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Entities; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using Unity.Physics; | |
using Unity.Physics.Authoring; | |
using Unity.Physics.Systems; | |
using Unity.Transforms; | |
using UnityEngine; | |
using Material = Unity.Physics.Material; | |
public struct Door : IComponentData | |
{ | |
public Entity Trigger; | |
public Entity Collider; | |
public float3 OpenPosition; | |
public float3 ClosedPosition; | |
public float Speed; | |
public bool Use; | |
public float MovementDuraction; | |
public DoorState State; | |
public float CurrentMoveTime; | |
} | |
public struct DoorTrigger : IComponentData | |
{ | |
public Entity Door; | |
public bool Use; | |
} | |
public enum DoorState | |
{ | |
Closed, Opened, Opening, Closing | |
} | |
[RequiresEntityConversion] | |
[DisallowMultipleComponent] | |
[SelectionBase] | |
public class DoorAuthoring : MonoBehaviour, IConvertGameObjectToEntity | |
{ | |
[Header("Trigger")] | |
[SerializeField] private PhysicsCategoryTags triggerBelongsTo; | |
[SerializeField] private PhysicsCategoryTags triggerCollidesWith; | |
[SerializeField] private Vector3 triggerCenter; | |
[SerializeField] private Vector3 triggerDimensions = Vector3.one; | |
[Header("Door")] | |
[SerializeField] private bool3 rotationAxis; | |
[SerializeField] private float3 rotationAngle; | |
[SerializeField] private float3 rotationPivot; | |
[Header("Collider")] | |
[SerializeField] private Vector3 colliderShape = Vector3.one; | |
[SerializeField] private Vector3 colliderOffset = Vector3.zero; | |
[SerializeField] private PhysicsCategoryTags colliderBelongsTo; | |
[SerializeField] private PhysicsCategoryTags colliderCollidesWith; | |
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) | |
{ | |
///////////////////////////////////// | |
// Create the collider for the door | |
///////////////////////////////////// | |
var collider = conversionSystem.CreateAdditionalEntity(gameObject); | |
dstManager.AddComponentData(collider, new Translation {Value = float3.zero}); | |
dstManager.AddComponentData(collider, new Rotation{Value = quaternion.identity}); | |
dstManager.AddComponentData(collider, new LocalToWorld()); | |
#if UNITY_EDITOR | |
dstManager.SetName(collider, name + " Collider"); | |
#endif | |
var colliderFilter = CollisionFilter.Default; | |
colliderFilter.BelongsTo = colliderBelongsTo.Value; | |
colliderFilter.CollidesWith = colliderCollidesWith.Value; | |
var colliderMaterial = Unity.Physics.Material.Default; | |
var colliderBlob = Unity.Physics.BoxCollider.Create(new BoxGeometry | |
{ | |
BevelRadius = 0.001f, | |
Center = colliderOffset, | |
Orientation = quaternion.identity, | |
Size = colliderShape | |
}, colliderFilter, colliderMaterial); | |
var colliderMass = new Unity.Physics.MassProperties(); | |
dstManager.AddComponentData(collider, new PhysicsCollider { Value = colliderBlob }); | |
dstManager.AddComponentData(collider, PhysicsMass.CreateKinematic(colliderMass)); | |
///////////////////////////////////// | |
// Trigger for trigger queries | |
///////////////////////////////////// | |
var trigger = conversionSystem.CreateAdditionalEntity(gameObject); | |
#if UNITY_EDITOR | |
dstManager.SetName(trigger, name + " Trigger"); | |
#endif | |
var filter = CollisionFilter.Default; | |
filter.BelongsTo = triggerBelongsTo.Value; | |
filter.CollidesWith = triggerCollidesWith.Value; | |
var material = Unity.Physics.Material.Default; | |
material.Flags = Material.MaterialFlags.IsTrigger; | |
var blob = Unity.Physics.BoxCollider.Create(new BoxGeometry | |
{ | |
BevelRadius = 0.001f, | |
Center = triggerCenter, | |
Orientation = quaternion.identity, | |
Size = triggerDimensions | |
}, filter, material); | |
dstManager.AddComponentData(trigger, new PhysicsCollider { Value = blob }); | |
dstManager.AddComponentData(trigger, new PhysicsMass()); | |
dstManager.AddComponentData(trigger, new Translation {Value = transform.position}); | |
dstManager.AddComponentData(trigger, new Rotation{Value = transform.rotation}); | |
dstManager.AddComponentData(trigger, new LocalToWorld()); | |
// Link both entities together | |
dstManager.AddComponentData(trigger, new DoorTrigger {Door = entity}); | |
///////////////////////////////////// | |
// Door | |
///////////////////////////////////// | |
dstManager.AddComponentData(entity, new Door | |
{ | |
Trigger = trigger, | |
Collider = collider, | |
OpenPosition = transform.position + Vector3.up, | |
ClosedPosition = transform.position, | |
Speed = 10, | |
MovementDuraction = 0.2f | |
}); | |
dstManager.AddComponentData(entity, new RotationEulerXYZ()); | |
dstManager.AddComponentData(entity, new CompositeRotation()); | |
dstManager.AddComponentData(entity, new RotationPivot {Value = rotationPivot}); | |
// ALso make a linkedentitygroup? | |
} | |
private void OnDrawGizmosSelected() | |
{ | |
Gizmos.color = Color.white; | |
Gizmos.DrawWireCube(triggerCenter + transform.position, triggerDimensions); | |
Gizmos.color = Color.blue; | |
Gizmos.DrawWireCube(transform.position + colliderOffset, colliderShape); | |
Gizmos.color = new Color(0f, 0f, 1f, 0.15f); | |
Gizmos.DrawCube(transform.position + colliderOffset, colliderShape); | |
} | |
public void FitColliderShape() | |
{ | |
var meshFilter = GetComponent<MeshFilter>(); | |
var mesh = meshFilter.sharedMesh; | |
var center = mesh.bounds.center; | |
var extents = new Vector3(mesh.bounds.size.x * transform.localScale.x,mesh.bounds.size.y * transform.localScale.y,mesh.bounds.size.z * transform.localScale.z); | |
colliderShape = extents; | |
colliderOffset = center; | |
} | |
} | |
[UpdateAfter(typeof(EndFramePhysicsSystem))] | |
public class DoorSystem : JobComponentSystem | |
{ | |
private BuildPhysicsWorld m_BuildPhysicsWorldSystem; | |
private StepPhysicsWorld m_StepPhysicsWorldSystem; | |
protected override void OnCreate() | |
{ | |
m_BuildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>(); | |
m_StepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>(); | |
} | |
[BurstCompile] | |
private struct TriggerJob: ITriggerEventsJob | |
{ | |
[ReadOnly] public ComponentDataFromEntity<PlayerTag> PlayerTag; | |
[ReadOnly] public ComponentDataFromEntity<GameplayInputs> PlayerInput; | |
[NativeDisableParallelForRestriction] public ComponentDataFromEntity<DoorTrigger> DoorTrigger; | |
public void Execute(TriggerEvent triggerEvent) | |
{ | |
var otherEntity = triggerEvent.Entities.EntityA; | |
var triggerEntity = triggerEvent.Entities.EntityB; | |
if(!DoorTrigger.Exists(triggerEntity)) | |
return; | |
var trigger = DoorTrigger[triggerEntity]; | |
var isBodyATrigger = PlayerTag.Exists(otherEntity); | |
if (isBodyATrigger && PlayerInput.Exists(otherEntity)) | |
{ | |
if (PlayerInput[otherEntity].Use) | |
{ | |
trigger.Use = true; | |
DoorTrigger[triggerEntity] = trigger; | |
} | |
} | |
} | |
} | |
[BurstCompile] | |
private struct DoorJob : IJobForEachWithEntity<Door, RotationEulerXYZ> | |
{ | |
public float FixedTime; | |
[NativeDisableParallelForRestriction] public ComponentDataFromEntity<DoorTrigger> DoorTrigger; | |
[NativeDisableParallelForRestriction] public ComponentDataFromEntity<Translation> Translation; | |
[NativeDisableParallelForRestriction] public ComponentDataFromEntity<Rotation> Rotation; | |
[NativeDisableParallelForRestriction] public ComponentDataFromEntity<LocalToWorld> LocalToWorld; | |
public void Execute(Entity entity, int index, ref Door door, ref RotationEulerXYZ rotationEulerXYZ) | |
{ | |
if(!DoorTrigger.Exists(door.Trigger)) | |
return; | |
var trigger = DoorTrigger[door.Trigger]; | |
// State behaviour setup | |
// If door is not moving and received use command | |
if (trigger.Use) | |
{ | |
//door.State = default; //?what | |
switch (door.State) | |
{ | |
case DoorState.Closed: | |
door.State = DoorState.Opening; | |
break; | |
case DoorState.Opened: | |
door.State = DoorState.Closing; | |
break; | |
case DoorState.Opening: | |
break; | |
case DoorState.Closing: | |
break; | |
default: | |
break; | |
} | |
// Clear use command | |
trigger.Use = false; | |
DoorTrigger[door.Trigger] = trigger; | |
} | |
// Movement behaviour | |
if (door.State == DoorState.Opening) | |
{ | |
// Tick the movement | |
if (door.CurrentMoveTime < door.MovementDuraction) | |
{ | |
door.CurrentMoveTime += FixedTime; | |
//translation.Value += maths.up * FixedTime * door.Speed; | |
rotationEulerXYZ.Value.y += FixedTime * door.Speed / 1; | |
} | |
// If finished, set state and reset timers | |
if (door.CurrentMoveTime > door.MovementDuraction) | |
{ | |
door.CurrentMoveTime = 0; | |
door.State = DoorState.Opened; | |
} | |
} | |
if (door.State == DoorState.Closing) | |
{ | |
// Tick the movement | |
if (door.CurrentMoveTime < door.MovementDuraction) | |
{ | |
door.CurrentMoveTime += FixedTime; | |
//translation.Value -= maths.up * FixedTime * door.Speed/3; | |
rotationEulerXYZ.Value.y -= FixedTime * door.Speed / 1; | |
} | |
// If finished, set state and reset timers | |
if (door.CurrentMoveTime > door.MovementDuraction) | |
{ | |
door.CurrentMoveTime = 0; | |
door.State = DoorState.Closed; | |
} | |
} | |
var translationCollider = Translation[door.Collider]; | |
translationCollider.Value = LocalToWorld[entity].Position; | |
Translation[door.Collider] = translationCollider; | |
var rotationCollider = Rotation[door.Collider]; | |
rotationCollider.Value = new quaternion(LocalToWorld[entity].Value); | |
Rotation[door.Collider] = rotationCollider; | |
} | |
} | |
protected override JobHandle OnUpdate(JobHandle inputDeps) | |
{ | |
var triggerjob = new TriggerJob | |
{ | |
PlayerTag = GetComponentDataFromEntity<PlayerTag>(true), | |
PlayerInput = GetComponentDataFromEntity<GameplayInputs>(true), | |
DoorTrigger = GetComponentDataFromEntity<DoorTrigger>(), | |
}; | |
var triggerHandle = triggerjob.Schedule( m_StepPhysicsWorldSystem.Simulation, ref m_BuildPhysicsWorldSystem.PhysicsWorld, inputDeps); | |
var doorJobHandle = new DoorJob | |
{ | |
FixedTime = Time.fixedDeltaTime, | |
DoorTrigger = GetComponentDataFromEntity<DoorTrigger>(), | |
Translation = GetComponentDataFromEntity<Translation>(), | |
LocalToWorld = GetComponentDataFromEntity<LocalToWorld>(), | |
Rotation = GetComponentDataFromEntity<Rotation>() | |
}.Schedule(this, triggerHandle); | |
return doorJobHandle; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment