public void SpawnParticle(string message, Color color, Vector3 position, float?startSize = null)
        {
            var texCords      = new Vector2[24]; // An array of 24 elements - 23 symbols + the length of the mesage
            var messageLenght = Mathf.Min(23, message.Length);

            texCords[texCords.Length - 1] = new Vector2(0, messageLenght);
            for (int i = 0; i < texCords.Length; i++)
            {
                if (i >= messageLenght)
                {
                    break;
                }
                // Calling the method GetTextureCoordinates() from SymbolsTextureData to obtain the symbol's position
                texCords[i] = textureData.GetTextureCoordinates(message[i]);
            }

            var custom1Data = CreateCustomData(texCords);
            var custom2Data = CreateCustomData(texCords, 12);

            // Caching link to ParticleSystem
            if (ps == null)
            {
                ps = GetComponent <ParticleSystem>();
            }

            if (particleSystemRenderer == null)
            {
                // If the link is to ParticleSystemRenderer, cash it and make sure we have right streams
                particleSystemRenderer = ps.GetComponent <ParticleSystemRenderer>();
                var streams = new List <ParticleSystemVertexStream>();
                particleSystemRenderer.GetActiveVertexStreams(streams);
                // Adding additional stream to Vector2(UV2, SizeXY, etc.), so that the coordinates in the script match the coordinates in the shader
                if (!streams.Contains(ParticleSystemVertexStream.UV2))
                {
                    streams.Add(ParticleSystemVertexStream.UV2);
                }
                if (!streams.Contains(ParticleSystemVertexStream.Custom1XYZW))
                {
                    streams.Add(ParticleSystemVertexStream.Custom1XYZW);
                }
                if (!streams.Contains(ParticleSystemVertexStream.Custom2XYZW))
                {
                    streams.Add(ParticleSystemVertexStream.Custom2XYZW);
                }
                particleSystemRenderer.SetActiveVertexStreams(streams);
            }

            // Initializing emission parameters
            // The color and position are obtained from the method parameters
            // Set startSize3D to X so that the characters are not stretched or compressed
            // when changing the length of the message
            var emitParams = new ParticleSystem.EmitParams
            {
                startColor           = color,
                position             = position,
                applyShapeToPosition = true,
                startSize3D          = new Vector3(messageLenght, 1, 1)
            };

            // If we want to create particles of different sizes, then in the parameters of SpawnParticle it is necessary
            // to transfer the desired startSize value
            if (startSize.HasValue)
            {
                emitParams.startSize3D *= startSize.Value * ps.main.startSizeMultiplier;
            }
            // Directly the spawn of the particles
            ps.Emit(emitParams, 1);

            // Transferring the custom data to the needed streams
            var customData = new List <Vector4>();

            // Getting the stream ParticleSystemCustomData.Custom1 from ParticleSystem
            ps.GetCustomParticleData(customData, ParticleSystemCustomData.Custom1);
            // Changing the data of the last element, i.e. the particle, that we have just created
            customData[customData.Count - 1] = custom1Data;
            // Returning the data to ParticleSystem
            ps.SetCustomParticleData(customData, ParticleSystemCustomData.Custom1);

            // The same for ParticleSystemCustomData.Custom2
            ps.GetCustomParticleData(customData, ParticleSystemCustomData.Custom2);
            customData[customData.Count - 1] = custom2Data;
            ps.SetCustomParticleData(customData, ParticleSystemCustomData.Custom2);
        }
        public void SpawnParticle(Vector3 position, string message, Color color, float?startSize = null)
        {
            var texCords      = new Vector2[24]; //массив из 24 элемент - 23 символа + длина сообщения
            var messageLenght = Mathf.Min(23, message.Length);

            texCords[texCords.Length - 1] = new Vector2(0, messageLenght);
            for (int i = 0; i < texCords.Length; i++)
            {
                if (i >= messageLenght)
                {
                    break;
                }
                //Вызываем метод GetTextureCoordinates() из SymbolsTextureData для получения позиции символа
                texCords[i] = textureData.GetTextureCoordinates(message[i]);
            }

            var custom1Data = CreateCustomData(texCords);
            var custom2Data = CreateCustomData(texCords, 12);

            //Кэшируем ссылку на ParticleSystem
            if (particleSystem == null)
            {
                particleSystem = GetComponent <ParticleSystem>();
            }

            if (particleSystemRenderer == null)
            {
                //Если ссылка на ParticleSystemRenderer, кэшируем и убеждаемся в наличии нужных потоков
                particleSystemRenderer = particleSystem.GetComponent <ParticleSystemRenderer>();
                var streams = new List <ParticleSystemVertexStream>();
                particleSystemRenderer.GetActiveVertexStreams(streams);
                //Добавляем лишний поток Vector2(UV2, SizeXY, etc.), чтобы координаты в скрипте соответствовали координатам в шейдере
                if (!streams.Contains(ParticleSystemVertexStream.UV2))
                {
                    streams.Add(ParticleSystemVertexStream.UV2);
                }
                if (!streams.Contains(ParticleSystemVertexStream.Custom1XYZW))
                {
                    streams.Add(ParticleSystemVertexStream.Custom1XYZW);
                }
                if (!streams.Contains(ParticleSystemVertexStream.Custom2XYZW))
                {
                    streams.Add(ParticleSystemVertexStream.Custom2XYZW);
                }
                particleSystemRenderer.SetActiveVertexStreams(streams);
            }

            //Инициализируем параметры эммишена
            //Цвет и позицию получаем из параметров метода
            //Устанавливаем startSize3D по X, чтобы символы не растягивались и не сжимались
            //при изменении длины сообщения
            var emitParams = new ParticleSystem.EmitParams
            {
                startColor           = color,
                position             = position,
                applyShapeToPosition = true,
                startSize3D          = new Vector3(messageLenght, 1, 1)
            };

            //Если мы хотим создавать частицы разного размера, то в параметрах SpawnParticle неоходимо
            //передать нужное значение startSize
            if (startSize.HasValue)
            {
                emitParams.startSize3D *= startSize.Value * particleSystem.main.startSizeMultiplier;
            }
            //Непосредственно спаун частицы
            particleSystem.Emit(emitParams, 1);

            //Передаем кастомные данные в нужные потоки
            var customData = new List <Vector4>();

            //Получаем поток ParticleSystemCustomData.Custom1 из ParticleSystem
            particleSystem.GetCustomParticleData(customData, ParticleSystemCustomData.Custom1);
            //Меняем данные последнего элемент, т.е. той частицы, которую мы только что создали
            customData[customData.Count - 1] = custom1Data;
            //Возвращаем данные в ParticleSystem
            particleSystem.SetCustomParticleData(customData, ParticleSystemCustomData.Custom1);

            //Аналогично для ParticleSystemCustomData.Custom2
            particleSystem.GetCustomParticleData(customData, ParticleSystemCustomData.Custom2);
            customData[customData.Count - 1] = custom2Data;
            particleSystem.SetCustomParticleData(customData, ParticleSystemCustomData.Custom2);
        }
    void DrawMainSettings()
    {
        Particle_Render = FindProperty("Particle_Render", _props);
        _MinRange       = FindProperty("_MinRange", _props);
        _MaxRange       = FindProperty("_MaxRange", _props);

        _materialEditor.ShaderProperty(Particle_Render, "Setup for Particle System");

        GameObject go = Selection.activeObject as GameObject;

        if (go != null)
        {
            ParticleSystemRenderer particles = go.GetComponent <ParticleSystemRenderer>();
            bool setupForParticles           = Particle_Render.floatValue != 0.0f;
            if (setupForParticles)
            {
                if (particles != null)
                {
                    List <ParticleSystemVertexStream> streams = new List <ParticleSystemVertexStream>();
                    particles.GetActiveVertexStreams(streams);
                    bool correctSetup = particles.activeVertexStreamsCount >= 2 && streams.Contains(ParticleSystemVertexStream.Position) && streams.Contains(ParticleSystemVertexStream.Center);
                    if (!correctSetup)
                    {
                        EditorGUILayout.HelpBox("Particle System Renderer is using this material with incorrect Vertex Streams. Use Apply to System button to fix this", MessageType.Warning);
                        if (GUILayout.Button("Apply to System"))
                        {
                            if (!streams.Contains(ParticleSystemVertexStream.Position))
                            {
                                streams.Add(ParticleSystemVertexStream.Position);
                            }
                            if (!streams.Contains(ParticleSystemVertexStream.Center))
                            {
                                streams.Add(ParticleSystemVertexStream.Center);
                            }
                            particles.SetActiveVertexStreams(streams);
                        }
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("Shader rendered by Mesh Renderer, but using setup for particles. Shader will be appearing incorrectly!", MessageType.Warning);
                    if (GUILayout.Button("Fix now"))
                    {
                        Particle_Render.floatValue = 0.0f;
                    }
                }
            }
            else
            {
                if (particles != null)
                {
                    EditorGUILayout.HelpBox("Shader rendered by Particle System, but using setup for meshes. Shader will be appearing incorrectly!", MessageType.Warning);
                    if (GUILayout.Button("Fix now"))
                    {
                        Particle_Render.floatValue = 1.0f;
                    }
                }
            }
        }

        GUILayout.Label("Fade settings", EditorStyles.boldLabel);
        _materialEditor.ShaderProperty(_MinRange, "Start fading");
        _materialEditor.ShaderProperty(_MaxRange, "End fading");
        GUILayout.Label("Editor settings", EditorStyles.boldLabel);
        useSliders = EditorGUILayout.Toggle("More SLIDERS!!!", useSliders);
        if (GUILayout.Button("[Experimental] Setup random effects"))
        {
            Glitch.floatValue                = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Magnification.floatValue         = Mathf.RoundToInt(UnityEngine.Random.Range(0, 5));
            _SizeGirls.floatValue            = UnityEngine.Random.value * 0.6f;
            ScreenRotation.floatValue        = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            _ScreenHorizontalFlip.floatValue = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            _ScreenVerticalFlip.floatValue   = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Shake.floatValue        = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Pixelization.floatValue = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Distorsion.floatValue   = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Blur.floatValue         = Mathf.RoundToInt(UnityEngine.Random.Range(0, 4));
            if (Blur.floatValue == 0)
            {
                Chromatic_Aberration.floatValue = Mathf.RoundToInt(UnityEngine.Random.Range(0, 2));
            }
            Neon.floatValue            = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            HSV_Selection.floatValue   = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            HSV_Transform.floatValue   = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Color_Tint.floatValue      = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Posterization.floatValue   = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Dithering.floatValue       = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Overlay_Texture.floatValue = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Static_Noise.floatValue    = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Vignette.floatValue        = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
            Mask_Texture.floatValue    = Mathf.RoundToInt(UnityEngine.Random.value * 0.6f);
        }
    }