public override bool Start()
        {
            m_Target = GetTarget();
            if (HasTarget() && m_Target == null)
            {
                // target has disappeared! Abort.
                return(false);
            }

            if (Description.Projectiles.Length < 1 || Description.Projectiles[0].ProjectilePrefab == null)
            {
                throw new System.Exception($"Action {Description.ActionTypeEnum} has no valid ProjectileInfo!");
            }

            // figure out how long the pretend-projectile will be flying to the target
            Vector3 targetPos       = HasTarget() ? m_Target.transform.position : m_Data.Position;
            float   initialDistance = Vector3.Distance(targetPos, m_Parent.transform.position);

            m_ProjectileDuration = initialDistance / Description.Projectiles[0].Speed_m_s;

            // create the projectile. It will control itself from here on out
            m_Projectile = SpawnAndInitializeProjectile();

            // animate shooting the projectile
            m_Parent.OurAnimator.SetTrigger(Description.Anim);
            return(true);
        }
        private FXProjectile SpawnAndInitializeProjectile()
        {
            GameObject projectileGO = Object.Instantiate(Description.Projectiles[0].ProjectilePrefab, m_Parent.transform.position, m_Parent.transform.rotation, null);

            FXProjectile projectile = projectileGO.GetComponent <FXProjectile>();

            if (!projectile)
            {
                throw new System.Exception($"FXProjectileTargetedAction tried to spawn projectile {projectileGO.name}, as dictated for action type {Data.ActionTypeEnum}, but the object doesn't have a FXProjectile component!");
            }

            // now that we have our projectile, initialize it so it'll fly at the target appropriately
            projectile.Initialize(m_Parent.transform.position, m_Target?.transform, m_Data.Position, Description.ExecTimeSeconds, m_ProjectileDuration);
            return(projectile);
        }