/// ---------------------------------------------
/// Behavior Designer
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.Samples
{
using System;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
///
/// Specifies the entity agents.
///
public struct AgentTag : IComponentData { }
///
/// Marks the object for destruction.
///
public struct DestroyEntityTag : IComponentData { }
///
/// Destroys the tagged entities after the behavior tree simulation has run.
///
[DisableAutoCreation]
public partial class DestroyEntitySystem : SystemBase
{
public Action OnDestroyEntity;
///
/// Destroys the entities tagged with the DestroyTag.
///
protected override void OnUpdate()
{
var ecb = new EntityCommandBuffer(Unity.Collections.Allocator.Temp);
foreach (var (destroyTag, localTransform, entity) in SystemAPI.Query().WithEntityAccess()) {
ecb.DestroyEntity(entity);
OnDestroyEntity?.Invoke(localTransform.Position);
}
ecb.Playback(EntityManager);
ecb.Dispose();
}
}
///
/// Specifies the entity that is the rotating part of the turret.
///
public struct TurretTag : IComponentData { }
///
/// Specifies the entity that is the base of the turret. This entity should be destroyed at the same time as the turret's gun.
///
public struct TurretBaseTag : IComponentData { }
///
/// Component for pulling back the turret when it fires a bullet.
///
public struct TurretRecoil : IComponentData, IEnableableComponent
{
[UnityEngine.Tooltip("Is the recoil pulling back the turret?")]
public bool Pullback;
[UnityEngine.Tooltip("The speed of the recoil pullback.")]
public float PullbackPosition;
[UnityEngine.Tooltip("The target z position of the recoil pullback.")]
public float PullbackSpeed;
}
///
/// Destroys the tagged entities after the behavior tree simulation has run.
///
[DisableAutoCreation]
public partial struct TurretRecoilSystem : ISystem
{
///
/// Destroys the entities tagged with the DestroyTag.
///
[BurstCompile]
private void OnUpdate(ref SystemState state)
{
var ecb = new EntityCommandBuffer(Unity.Collections.Allocator.Temp);
var deltaTime = SystemAPI.Time.DeltaTime;
foreach (var (turretRecoil, localTransform, entity) in SystemAPI.Query, RefRW>().WithEntityAccess()) {
var position = localTransform.ValueRO.Position;
position.z = MoveTowards(localTransform.ValueRO.Position.z, turretRecoil.ValueRO.Pullback ? turretRecoil.ValueRO.PullbackPosition : 0, turretRecoil.ValueRO.PullbackSpeed * deltaTime);
localTransform.ValueRW.Position = position;
if (turretRecoil.ValueRO.Pullback && math.abs(position.z - turretRecoil.ValueRO.PullbackPosition) <= 0.01f) {
turretRecoil.ValueRW.Pullback = false;
ecb.SetComponentEnabled(entity, false);
} else if (!turretRecoil.ValueRO.Pullback && math.abs(position.z) <= 0.01f) {
turretRecoil.ValueRW.Pullback = true;
ecb.SetComponentEnabled(entity, false);
}
}
ecb.Playback(state.EntityManager);
ecb.Dispose();
}
///
/// Moves towards the target limited by the maximum distance.
///
/// The current value.
/// The target value.
/// The maximum distance that the delta value can move.
/// The move towards value.
[BurstCompile]
private static float MoveTowards(float current, float target, float maxDistanceDelta)
{
var delta = target - current;
if (math.abs(delta) <= maxDistanceDelta) {
return target;
}
return current + maxDistanceDelta * math.sign(delta);
}
}
}