/// <summary>
        /// Make a particle fit the setting.
        /// </summary>
        /// <param name="particle"> particle to change and fit the setting. </param>
        private void SetParticleBySetting(JCS_Particle particle)
        {
            // get this particle info.
            Vector3 newPos = particle.transform.position;

            if (mSetToSamePositionWhenActive)
            {
                // set position to the same position as particle
                // system's position.
                particle.transform.position = this.transform.position;
            }

            // after we have set the position to current
            // particle system's position. Next step is to
            // apply the random value to the newer position.
            newPos.x += JCS_Random.Range(-mRandPosX, mRandPosX);
            newPos.y += JCS_Random.Range(-mRandPosY, mRandPosY);
            newPos.z += JCS_Random.Range(-mRandPosZ, mRandPosZ);
            particle.transform.position = newPos;

            // set rotation depend on wind speed

            /**
             * NOTE(jenchieh):
             *                      ------- Set the scale from
             *                      ↓      the original particle,
             *                      ↓      so the euler angles won't
             *                  ↓-------↓  get stack up.              */
            Vector3 newRot = mParticle.transform.localEulerAngles;

            newRot.z = mWindSpeed;

            // apply wind speed.
            newRot.z += JCS_Random.Range(-mRandAngleX, mRandAngleX);

            // apply random rotation.
            newRot.x += JCS_Random.Range(-mRandAngleX, mRandAngleX);
            newRot.y += JCS_Random.Range(-mRandAngleY, mRandAngleY);
            newRot.z += JCS_Random.Range(-mRandAngleZ, mRandAngleZ);
            particle.transform.localEulerAngles = newRot;

            /**
             * NOTE(jenchieh):
             *                      ------- Set the scale from
             *                      ↓      the original particle,
             *                      ↓      so the scale won't
             *                  ↓-------↓  get stack up.              */
            Vector3 newScale = mParticle.transform.localScale;

            newScale.x += JCS_Random.Range(-mRandScaleX, mRandScaleX);
            newScale.y += JCS_Random.Range(-mRandScaleY, mRandScaleY);
            newScale.z += JCS_Random.Range(-mRandScaleZ, mRandScaleZ);
            if (mAlwaysTheSameScale)
            {
                // set the scale the same.
                newScale.y = newScale.x;
                newScale.z = newScale.x;
            }
            particle.transform.localScale = newScale;
        }
        /// <summary>
        /// Spawn all particle base on the count.
        /// </summary>
        public void SpawnParticles()
        {
            // check if particles already spawned?
            if (mParticleSpawned)
            {
                return;
            }

            if (mParticle == null)
            {
                JCS_Debug.Log(
                    "No particle assign!");
                return;
            }

            for (int index = 0;
                 index < mNumOfParticle;
                 ++index)
            {
                JCS_Particle trans = (JCS_Particle)JCS_Util.SpawnGameObject(mParticle);
                mParticles.push(trans);

                // disable the object
                trans.gameObject.SetActive(false);

                if (mSetChild)
                {
                    // set parent
                    trans.transform.SetParent(this.transform);
                }
            }

            mParticleSpawned = true;
        }
        /// <summary>
        /// Active some particle in certain number current frame.
        /// </summary>
        /// <param name="num"> number to spawn the particle. </param>
        public void PlayOneShot(int num)
        {
            if (mParticle == null)
            {
                return;
            }

            if (mDoShotImmediately)
            {
                for (int count = 0;
                     count < num;
                     ++count)
                {
                    JCS_Particle particle = SearchAvaliableParticles();

                    if (particle == null)
                    {
                        continue;
                    }

                    SetParticleBySetting(particle);
                }
            }
            else
            {
                for (int count = 0;
                     count < num;
                     ++count)
                {
                    DoSequenceParticle(mDensity);
                }
            }
        }
        /// <summary>
        /// Process the thread.
        /// </summary>
        /// <param name="processIndex"> thread id </param>
        private void Sequence(int processIndex)
        {
            // get the timer from the thread
            float newTimer = mTimers.at(processIndex);

            // add time to timer
            newTimer += Time.deltaTime;

            // check if we can do the particle or not
            if (mTimeAParticle < newTimer)
            {
                int totalParticleCount   = mParticleCount.at(processIndex);
                int currentParticleCount = mParticleCounter.at(processIndex);
                if (currentParticleCount == totalParticleCount)
                {
                    // Remove Thread.
                    EndProcessSequence(processIndex);
                    return;
                }

                // find a particle
                JCS_Particle particle = SearchAvaliableParticles();

                if (particle == null)
                {
                    // exit function.
                    return;
                }

                SetParticleBySetting(particle);

                ++currentParticleCount;

                // update new count, in order
                // to spawn next bullet
                mParticleCounter.set(processIndex, currentParticleCount);
                newTimer = 0;
            }

            // update timer
            mTimers.set(processIndex, newTimer);
        }
        /// <summary>
        /// Find the avaliable particle in the list.
        /// </summary>
        /// <returns> non-active paritcle. </returns>
        private JCS_Particle SearchAvaliableParticles(bool sec = false)
        {
            if (mNumOfParticle <= 0)
            {
                JCS_Debug.LogError(
                    "Number of particle cannot lower or equal to zero...");
                return(null);
            }

            for (int index = mLastAvaliableIndex;
                 index < mParticles.length;
                 ++index)
            {
                JCS_Particle particle = mParticles.at(index);
                bool         isActive = particle.gameObject.activeInHierarchy;
                if (isActive == false)
                {
                    particle.gameObject.SetActive(true);
                    mLastAvaliableIndex = index;
                    return(particle);
                }
            }

            // if we get here mean we cycle once but we
            // did not spawn a text!
            // so reset the spawn pos and
            // try to search agian until we find one!
            mLastAvaliableIndex = 0;

            // if second time still does not find, return null.
            // prevent stack overflow.
            if (sec)
            {
                return(null);
            }

            // dangerious, use carefully!
            // make sure u have enough number of handle
            // or else the program might crash? (too many delay?)
            return(SearchAvaliableParticles(true));
        }