using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Stride.Core; using Stride.Engine; namespace MyTrailEffect { /// /// A script which spawns a timed instance from a source prefab. /// public class SpawnTrail : AsyncScript { private float timeIntervalCountdown = 0f; public AnimationComponent Animation { get; set; } private TimeSpan lastTime = TimeSpan.FromMinutes(60); /// /// Source to the prefab, selectable by the user /// [DataMember(10)] [Display("Source")] public Prefab SourcePrefab; /// /// Should the prefab follow the entity's transform component on change or not /// [DataMember(20)] [Display("Following")] public bool Following { get; set; } = true; /// /// How long before the prefab instance is deleted, selectable by the user /// [DataMember(30)] [Display("Timeout")] public float InstanceTimeout = 3f; /// /// Set the time interval (in seconds) at which to spawn new instances. Set it to 0 to deactivate. /// [DataMember(50)] [Display("Start time")] public float TimeInterval { get; set; } = 0f; public override async Task Execute() { var canTrigger = lastTime > Animation.PlayingAnimations[0].CurrentTime; lastTime = Animation.PlayingAnimations[0].CurrentTime; while (Game.IsRunning) { await Script.NextFrame(); canTrigger |= lastTime > Animation.PlayingAnimations[0].CurrentTime; lastTime = Animation.PlayingAnimations[0].CurrentTime; if (canTrigger && Animation.PlayingAnimations[0].CurrentTime.TotalSeconds >= TimeInterval) { canTrigger = false; SpawnInstance(); } } } /// /// Will add a cloned entity from the prefab to the scene, wait for the specified time and delete it /// protected void SpawnInstance() { if (SourcePrefab == null) return; Func spawnTask = async () => { // Clone var spawnedEntities = SourcePrefab.Instantiate(); // Add foreach (var prefabEntity in spawnedEntities) { if (Following) { Entity.AddChild(prefabEntity); } else { prefabEntity.Transform.UpdateLocalMatrix(); var worldMatrix = prefabEntity.Transform.LocalMatrix * Entity.Transform.WorldMatrix; worldMatrix.Decompose(out prefabEntity.Transform.Scale, out prefabEntity.Transform.Rotation, out prefabEntity.Transform.Position); SceneSystem.SceneInstance.RootScene.Entities.Add(prefabEntity); } } // Countdown var secondsCountdown = InstanceTimeout; while (secondsCountdown > 0f) { await Script.NextFrame(); secondsCountdown -= (float)Game.UpdateTime.Elapsed.TotalSeconds; } // Remove foreach (var clonedEntity in spawnedEntities) { if (Following) { Entity.RemoveChild(clonedEntity); } else { SceneSystem.SceneInstance.RootScene.Entities.Remove(clonedEntity); } } // Cleanup spawnedEntities.Clear(); }; Script.AddTask(spawnTask); } } }