<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Trshcan : MonoBehaviour
{
    MainParticleLifeCycle[] recycleObjectList;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        recycleObjectList = transform.GetComponentsInChildren<MainParticleLifeCycle>();
        foreach(MainParticleLifeCycle particle in recycleObjectList)
        {
            if(particle.m_stage == mainParticleStage.end)
            {
                
                Destroy(particle.transform.gameObject);
            }
        }
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[System.Serializable]
public class EmitterHunter : Hunter
{
    /*
     * public LayerManager m_Layer;
     * public LayerManager[] HuntingTargets;
     * public GameObject HuntingSensor;
     * [HideInInspector] public bool ifHasTarget;
     * [HideInInspector] public List<GameObject> HuntingList;
     */
     
    public EmitterHunter(EmitterParticleBehaiour _emitterParticle)
    {
        if(_emitterParticle != null)
            emitterParticle = _emitterParticle;

        
        
    }

    public float TracingSpeed;
    [HideInInspector]public EmitterParticleBehaiour emitterParticle;
    int eatingNumber;

    public GameObject currentTarget = null;
    public GameObject getCurrentTarget{ get { return currentTarget; } }

    public int getEatingNumber{get{return eatingNumber;}}
    public bool isTracing{get{ return (currentTarget != null);}}

    public void Hunting()
    {
        //Debug.Log("enter hunting");
        if (!isTracing && ifHasTarget)
        {
            SelectTracingTarget(emitterParticle.transform);
            //Debug.Log("select target");
            return;
        }
        else if (!ifHasTarget)
        {
            
            //Debug.Log("currentTarget = null");
            return;
        }

       
        //Debug.Log("ifHasTarget : " + ifHasTarget + " ; isTracing : " + isTracing);
        //TracingTarget();
    }

    public void SelectTracingTarget(Transform m_transform)
    {
       
        if (HuntingList.Count > 0)
        {
            //Debug.Log("select hunting target");
            float mostCloseDistance = 0;
            GameObject mostCloseTarget = null;
            if(mouse.HuntingTargets.Length == 0){
                mouse.setHunigTarget(HuntingTargets);
                Debug.Log("Hunting Targets" + mouse.HuntingTargets[0]);
            }
            for (int i = 0; i < HuntingList.Count; i++)
            {
                if(HuntingList[i] == null)continue;
                float distanceToTarget = Vector3.Distance(m_transform.position, HuntingList[i].transform.position);
                if(distanceToTarget > 10)
                {
                    HuntingList.Remove(HuntingList[i]);
                    return;
                }
                if (mostCloseTarget == null)
                {
                    currentTarget = HuntingList[i];
                    mostCloseDistance = Vector3.Distance(m_transform.position, currentTarget.transform.position);
                }
                else if (distanceToTarget < mostCloseDistance)
                {
                    currentTarget = HuntingList[i];
                    mostCloseDistance = distanceToTarget;
                }
            }

        }
        else if(HuntingList.Count == 0)
        {
            currentTarget = null;
            //Debug.Log("hunting List is empty");
        }

    }

    //public void TracingTarget(Transform m_transform)
    //{
    //    float sensorRadius = HuntingSensor.GetComponent<SphereCollider>().radius * HuntingSensor.transform.localScale.x;
    //    float distanceToTarget = Vector3.Distance(m_transform.position, currentTarget.transform.position);

    //    TracingMove(m_transform);

    //    if(distanceToTarget < sensorRadius)
    //    {
    //        EatingBehaviour();
    //    }
    //}

    //void TracingMove(Transform m_transform)
    //{
    //    float _distance = Vector3.Distance(currentTarget.transform.position, m_transform.position);
    //    Vector3 dir = (currentTarget.transform.position - m_transform.transform.position).normalized;
    //    float t = Time.deltaTime * _distance / 2 * TracingSpeed * 0.35f;
    //    if (t > 0.5) t = 0.5f;
    //    m_transform.GetComponent<Rigidbody>().MovePosition(
    //        Vector3.Slerp(m_transform.position, currentTarget.transform.position, t));
    //}
    //void EatingBehaviour()
    //{
    //    eatingNumber += 1;
    //    if(eatingNumber > emitterParticle.HowMuchNumberForEatingToGrowUp)
    //    {
    //        emitterParticle.GrowUp();
    //        eatingNumber = 0;
    //    }
    //    emitterParticle.motionStateNow = ParticleMotionState.Eating;
    //}
}

[RequireComponent(typeof(Rigidbody),typeof(SphereCollider))]
public class EmitterParticleBehaiour : ParticleBehaiour{
    /* 參考用
    //public ApearenceStructure apearence;
    //public PhysicMotionSetting physicMotion;
    //public Hunter hunter;
    //public ParticleLifeState stateNow;
    //public ParticleMotionState motionStateNow;
    //public int HowMuchNumberForEatingToGrowUp;
    //public bool canItGrowUp = false;
    //public bool isHunter = false;
    //public bool ifNeedRandomReborn;
    //int index;

    //ScreenSpaceBoundary m_Boundary;
    //Rigidbody m_rigidbody;
    //SphereCollider m_collider;
    */

    private static EmitterParticleBehaiour _instance ;
    public EmitterParticleBehaiour instance{
        get{
            if (_instance == null) _instance = this;
            return _instance;
        }
    }


    int index;
    int direction = 1;
    float timer;
    float timerAtEnd;
    float rebornDelayTime;

    public EmitterHunter m_hunter = new EmitterHunter(_instance);

    [Header("Motion Related Attribbute")]
    public Vector2 rebornDelay = new Vector2(2, 5);
    [Tooltip("How long will it reborn after leaving boundary")]
    public float endingDelay = 1.5f;

    [Tooltip("(min,max)")]
    public Vector2 stepRandomMoveDistance = new Vector2(1,2);
    public Vector2 maxMoveAngle = new Vector2(60,120);
    private Vector3 nextPosition;

    [Header("ParticleEffect")]
    public ParticleSystem TraceEffect;
    public ParticleSystem ExplosionEffect;
    
	// Use this for initialization
    void Awake()
    {
        if(instance == null){
            Debug.Log("initialize");
        }
    }
	void Start () {
        saveData();
        Initialize();


	}
	
	// Update is called once per frame
	void Update () 
    {
        LifeCycleStateSelector();
	}

    public override void Initialize()
    {
        InitializeComponent();
        m_hunter.emitterParticle = instance;
        if(isUseRandomReborn)
        {
            RandomReborn();
        }


    }

    public override void RandomReborn()
    {
        direction = UnityEngine.Random.Range(0, 100) > 50 ? 1 : -1;
        transform.position = RegenerateStartPosition(direction);
        PositionInitialize();
    }

    public override void LifeCycleStateSelector()
    {
        timer += Time.deltaTime;
        //switch
        switch (stateNow)
        {
            case ParticleLifeState.RebornDelay:
                RebornDelayBehaviour();
                break;

            case ParticleLifeState.Start:
                StartBehaviour();
                break;

            case ParticleLifeState.Update:
                UpdateBehaviour();
                break;

            case ParticleLifeState.End:
                EndBehaviour();
                break;
        }
    }

    void RebornDelayBehaviour()
    {
        if (timer > rebornDelayTime)
        {

            stateNow = ParticleLifeState.Start;

        }
    }

    void StartBehaviour()
    {
        timer = 0;
        m_hunter.mouse.isBeEaten = false;
        stateNow = ParticleLifeState.Update;

        direction = UnityEngine.Random.Range(0, 100) > 50 ? 1 : -1;
        transform.localPosition = RegenerateStartPosition(direction);
        PositionInitialize();
        m_hunter.HuntingList.Clear();
        m_hunter.currentTarget = null;
        transform.localScale = scale;
        ExplosionEffect.Stop();
        TraceEffect.Play();
        GetComponent<MeshRenderer>().material.SetFloat("_Alpha", 1);
    }

    void UpdateBehaviour()
    {
        UpdateCycleStateSelector();
    }
    void EndBehaviour()
    {
        StartCoroutine(fadeOut(0.5f));

    }

    Vector3 nextRandomPos;
    public override void UpdateCycleStateSelector() 
    {
        //Debug.Log(m_updateStage);
        EventManagement();
        switch (motionStateNow)
        {
            case ParticleMotionState.Idle:
                GerridaeMoveWay();
                break;
            case ParticleMotionState.Hunting:
                GerridaeMoveWay();
                //Hunter();
                break;
            case ParticleMotionState.Eating:
                if (!isgrowing)
                    StartCoroutine(growing(1f));
                motionStateNow = ParticleMotionState.Idle;

                break;
            case ParticleMotionState.BeEaten:
                StartCoroutine(scaleDown(ExplosionEffect.main.duration, ExplosionEffect));
                break;
        }

       
        //if particle leave boundary it will translate to end state
        //but here I do is for avoiding particle stuck on the boundary line
        if(!m_Boundary.isPointInside(transform) && timer > 5)
        {
            timerAtEnd += Time.deltaTime;
            //Debug.Log("isPointInside : " + m_Boundary.isPointInside(transform) + "; timer : " + timer + " ; timerAtEnd : " + timerAtEnd);

            if (timerAtEnd > endingDelay)
            {
                timer = 0;
                timerAtEnd = 0;
                nextPosition = Vector3.zero;
                stateNow = ParticleLifeState.End;
                //Debug.Log("enter end state");
            }
        }
    }


    public void EventManagement()
    {

        if(m_hunter.mouse.isBeEaten)
        {
            motionStateNow = ParticleMotionState.BeEaten;
        }
        else if(m_hunter.ifHasTarget && !m_hunter.getIsEating)
        {
            motionStateNow = ParticleMotionState.Hunting;

        }
        else if (m_hunter.getIsEating)
        {
            motionStateNow = ParticleMotionState.Eating;

            m_hunter.mouse.Reset();
        }
        else 
        {
            motionStateNow = ParticleMotionState.Idle;
        }


    }
    void HuntingTracingMove()
    {
        LerpMove(nextPosition, this.transform.position, moveDistance);
    }

    /// <summary>
    /// 水皿移動
    /// </summary>
    void GerridaeMoveWay()
    {
        float currentDistance = Vector3.Distance(transform.position, nextPosition);
        //Debug.Log("transform.position : " + transform.position + " ; nextPosition : " + nextPosition + "Vector3.Distance(transform.position, nextPosition) : " + Vector3.Distance(transform.position, nextPosition));
        if (currentDistance < 1.5f || currentDistance > 10f)
        {
            if(motionStateNow == ParticleMotionState.Idle)
                GeneratNextPosion();
            else if(motionStateNow == ParticleMotionState.Hunting)
            {
                //Debug.Log("GerridaeMoveWay hunting");
                m_hunter.Hunting();

                if(m_hunter.isTracing)
                {
                    if (Vector3.Distance(transform.position, m_hunter.currentTarget.transform.position) > 15)
                    {
                        m_hunter.currentTarget = null;
                        motionStateNow = ParticleMotionState.Idle;
                        //Debug.Log("tracing 2");
                        return;
                    }
                    nextPosition = this.transform.position + (m_hunter.getCurrentTarget.transform.position - transform.position).normalized * 5;
                    //Debug.Log("tracing 1");
                    //Debug.Log("reset next position in hunting : current distance " + currentDistance);
                }
                else
                {
                    motionStateNow = ParticleMotionState.Idle;
                    //Debug.Log("return to idle");
                    return;

                }
                //Debug.Log("nothing happen");
                    
            }
                
        }
        else if(currentDistance < 10f && currentDistance > 1.5f)
            LerpMove(nextPosition, this.transform.position, moveDistance);
        
        //LerpMove(nextPosition, this.transform.position, moveDistance);
    }

    float moveDistance;
    void GeneratNextPosion()
    {
        
        float mediumAngle = direction == 1 ? (maxMoveAngle.x + maxMoveAngle.y) * Mathf.Deg2Rad * 0.5f : (maxMoveAngle.x + maxMoveAngle.y ) * Mathf.Deg2Rad * 0.5f + 180f* Mathf.Deg2Rad;
        float moveAngle = UnityEngine.Random.Range(maxMoveAngle.x * Mathf.Deg2Rad - mediumAngle, maxMoveAngle.y * Mathf.Deg2Rad - mediumAngle);
        moveDistance = UnityEngine.Random.Range(stepRandomMoveDistance.x, stepRandomMoveDistance.y);

        float newX = (float)(moveDistance * Mathf.Cos(moveAngle));
        float newY = (float)(moveDistance * Mathf.Sin(moveAngle));

        //if(m_Boundary.isPointInside())
        nextPosition = this.transform.position + new Vector3(newX, newY,0);
        //Debug.Log("reset next position in idle");
    }

    void LerpMove(Vector3 forwardPosition, Vector3 currentPosition, float minCloseDistance)
    {
        float _distance = Vector3.Distance(forwardPosition, currentPosition);
        Vector3 dir = (forwardPosition - currentPosition).normalized;
        float t = Time.deltaTime * _distance / minCloseDistance * physicMotion.speed;
        if (t > 0.5) t = 0.5f;
            m_rigidbody.MovePosition(
            Vector3.Slerp(currentPosition, forwardPosition, t));
    }


    private void OnTriggerEnter(Collider other)
    {
        for (int i = 0; i < m_hunter.HuntingTargets.Length;i++)
        {
            if(other.gameObject.layer == (int)m_hunter.HuntingTargets[i])
            {
                if(!m_hunter.HuntingList.Contains(other.gameObject))
                    m_hunter.HuntingList.Add(other.gameObject);
                ForceSelector(100, other.gameObject, ForceType.attractive);
            }
        }

    }
    private void OnTriggerStay(Collider other)
    {
        for (int i = 0; i < m_hunter.HuntingTargets.Length; i++)
        {
            if (other.gameObject.layer == (int)m_hunter.HuntingTargets[i])
            {
                if (!m_hunter.HuntingList.Contains(other.gameObject))
                    m_hunter.HuntingList.Add(other.gameObject);
                ForceSelector(100, other.gameObject, ForceType.attractive);
            }
        }
    }
    private void OnTriggerExit(Collider other)
    {
        if(m_hunter.HuntingList.Contains(other.gameObject))
        {
            m_hunter.HuntingList.Remove(other.gameObject);

        }
    }

    public void ForceSelector(float forceMagnitude,GameObject _collisionObject, ForceType type)
    {
        Vector3 Force = Vector3.zero;
        Rigidbody pRigidbody = _collisionObject.GetComponent<Rigidbody>();
        float distance = Vector3.Distance(transform.position, _collisionObject.transform.position);
        switch (type)
        {
            case ForceType.attractive:
                Force = (this.transform.position - _collisionObject.transform.position).normalized *
                    Mathf.Lerp(forceMagnitude, forceMagnitude / 2, distance / GetComponent<SphereCollider>().radius * transform.localScale.x);
                break;

            case ForceType.explosition:
                Force = (_collisionObject.transform.position - this.transform.position).normalized *
                    Mathf.Lerp(0, forceMagnitude, distance / GetComponent<SphereCollider>().radius * transform.localScale.x);
                break;
        }

        pRigidbody.AddForce(Force);
    }
    Vector3 scale;
    void saveData()
    {
        scale = transform.localScale;
    }

    bool checkLossyScale(Vector3 _scale)
    {
        return _scale.x * _scale.y * _scale.z > 0;
    }


    IEnumerator scaleDown(float lerpTime,ParticleSystem explosionEffect)
    {
        float time = 0;
        explosionEffect.Play();
        while(checkLossyScale(transform.localScale))
        {
            time += Time.deltaTime;
            transform.localScale = Vector3.Slerp(scale, Vector3.zero, time / lerpTime);
            yield return new WaitForEndOfFrame();
        }
        stateNow = ParticleLifeState.End;
        TraceEffect.Stop();
    }

    IEnumerator fadeOut(float lerpTime)
    {
        float alpha = GetComponent<MeshRenderer>().material.GetFloat("_Alpha");
        float time = 0;
        TraceEffect.Stop();
        while(GetComponent<MeshRenderer>().material.GetFloat("_Alpha") > 0)
        {
            time += Time.deltaTime;
            float _a = Mathf.Lerp(alpha, 0, time / lerpTime);
            GetComponent<MeshRenderer>().material.SetFloat("_Alpha", _a);
            yield return new WaitForEndOfFrame();
        }
        stateNow = ParticleLifeState.RebornDelay;

    }
    bool isgrowing = false;
    IEnumerator growing(float _timer)
    {
        float time = 0;
        isgrowing = true;
        TraceEffect.emissionRate = 120;
        while(time/_timer < 1)
        {
            time += Time.deltaTime;
            transform.localScale = Vector3.Slerp(scale, scale + Vector3.one*0.2f , time / _timer);
            yield return new WaitForEndOfFrame();
        }

        TraceEffect.emissionRate = 8;
        time = 0;
        while (time / _timer < 1)
        {
            time += Time.deltaTime;
            transform.localScale = Vector3.Slerp(scale +Vector3.one * 0.2f,scale, time / _timer);
            yield return new WaitForEndOfFrame();
        }
        transform.localScale = scale;

        isgrowing = false;
    }
   
}
<file_sep>using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

namespace Klak.Hap
{
    [ExecuteInEditMode, AddComponentMenu("Klak/HAP/HAP Player")]
    public sealed class HapPlayer : MonoBehaviour, ITimeControl, IPropertyPreview
    {
        #region Editable attributes

        public enum PathMode { StreamingAssets, LocalFileSystem }

        [SerializeField] PathMode _pathMode = PathMode.StreamingAssets;
        [SerializeField] string _filePath = "";

        [SerializeField] float _time = 0;
        [SerializeField, Range(-10, 10)] float _speed = 1;
        [SerializeField] bool _loop = true;

        [SerializeField] RenderTexture _targetTexture = null;
        [SerializeField] Renderer _targetRenderer = null;
        [SerializeField] string _targetMaterialProperty = "_MainTex";

        #endregion

        #region Public properties

        public float time {
            get { return _time; }
            set { _time = value; }
        }

        public float speed {
            get { return _speed; }
            set { _speed = value; }
        }

        public bool loop {
            get { return _loop; }
            set { _loop = value; }
        }

        public RenderTexture targetTexture {
            get { return _targetTexture; }
            set { _targetTexture = value; }
        }

        public Renderer targetRenderer {
            get { return _targetRenderer; }
            set { _targetRenderer = value; }
        }

        public string targetMaterialProperty {
            get { return _targetMaterialProperty; }
            set { _targetMaterialProperty = value; }
        }

        #endregion

        #region Read-only properties

        public bool isValid { get { return _demuxer != null; } }
        public int frameWidth { get { return _demuxer?.Width ?? 0; } }
        public int frameHeight { get { return _demuxer?.Height ?? 0; } }
        public int frameCount { get { return _demuxer?.FrameCount ?? 0; } }
        public double streamDuration { get { return _demuxer?.Duration ?? 0; } }

        public CodecType codecType { get {
            return Utility.DetermineCodecType(_demuxer?.VideoType ?? 0);
        } }

        public string resolvedFilePath { get {
            if (_pathMode == PathMode.StreamingAssets)
                return System.IO.Path.Combine(Application.streamingAssetsPath, _filePath);
            else
                return _filePath;
        } }

        public Texture2D texture { get { return _texture; } }

        #endregion

        #region Public methods

        public void Open(string filePath, PathMode pathMode = PathMode.StreamingAssets)
        {
            if (_demuxer != null)
            {
                Debug.LogError("Stream has already been opened.");
                return;
            }

            _filePath = filePath;
            _pathMode = pathMode;

            OpenInternal();
        }

        #endregion

        #region Private members

        Demuxer _demuxer;
        StreamReader _stream;
        Decoder _decoder;

        Texture2D _texture;
        TextureUpdater _updater;

        float _storedTime;
        float _storedSpeed;

        void OpenInternal()
        {
            // Demuxer instantiation
            _demuxer = new Demuxer(resolvedFilePath);

            if (!_demuxer.IsValid)
            {
                if (Application.isPlaying)
                {
                    // In play mode, show an error message, then disable itself
                    // to prevent spamming the console.
                    Debug.LogError("Failed to open stream (" + resolvedFilePath + ").");
                    enabled = false;
                }
                _demuxer.Dispose();
                _demuxer = null;
                return;
            }

            // Stream reader instantiation
            _stream = new StreamReader(_demuxer, _time, _speed / 60);
            (_storedTime, _storedSpeed) = (_time, _speed);

            // Decoder instantiation
            _decoder = new Decoder(
                _stream, _demuxer.Width, _demuxer.Height, _demuxer.VideoType
            );

            // Texture initialization
            _texture = new Texture2D(
                _demuxer.Width, _demuxer.Height,
                Utility.DetermineTextureFormat(_demuxer.VideoType), false
            );
            _texture.wrapMode = TextureWrapMode.Clamp;
            _texture.hideFlags = HideFlags.DontSave;

            _updater = new TextureUpdater(_texture, _decoder);
        }

        #endregion

        #region External object updaters

        Material _blitMaterial;
        MaterialPropertyBlock _propertyBlock;

        void UpdateTargetTexture()
        {
            if (_targetTexture == null) return;

            // Material lazy initialization
            if (_blitMaterial == null)
            {
                _blitMaterial = new Material(Utility.DetermineBlitShader(_demuxer.VideoType));
                _blitMaterial.hideFlags = HideFlags.DontSave;
            }

            // Blit
            Graphics.Blit(_texture, _targetTexture, _blitMaterial, 0);
        }

        void UpdateTargetRenderer()
        {
            if (_targetRenderer == null) return;

            // Material property block lazy initialization
            if (_propertyBlock == null)
                _propertyBlock = new MaterialPropertyBlock();

            // Read-modify-write
            _targetRenderer.GetPropertyBlock(_propertyBlock);
            _propertyBlock.SetTexture(_targetMaterialProperty, _texture);
            _targetRenderer.SetPropertyBlock(_propertyBlock);
        }

        #endregion

        #region ITimeControl implementation

        bool _externalTime;

        public void OnControlTimeStart()
        {
            _externalTime = true;

            // In the external time mode, we can't know the actual playback
            // speed but sure that it's positive (Control Track doesn't support
            // reverse playback), so we assume that the speed is 1.0.
            // Cons: Resync could happen every frame for high speed play back.
            _speed = 1;
        }

        public void OnControlTimeStop()
        {
            _externalTime = false;
        }

        public void SetTime(double time)
        {
            _time = (float)time;
            _speed = 1;
        }

        #endregion

        #region IPropertyPreview implementation

        public void GatherProperties(PlayableDirector director, IPropertyCollector driver)
        {
            driver.AddFromName<HapPlayer>(gameObject, "_time");
        }

        #endregion

        #region MonoBehaviour implementation

        void OnDestroy()
        {
            if (_updater != null)
            {
                _updater.Dispose();
                _updater = null;
            }

            if (_decoder != null)
            {
                _decoder.Dispose();
                _decoder = null;
            }

            if (_stream != null)
            {
                _stream.Dispose();
                _stream = null;
            }

            if (_demuxer != null)
            {
                _demuxer.Dispose();
                _demuxer = null;
            }

            Utility.Destroy(_texture);
            Utility.Destroy(_blitMaterial);
        }

        void LateUpdate()
        {
            // Lazy initialization of demuxer
            if (_demuxer == null && !string.IsNullOrEmpty(_filePath))
                OpenInternal();

            // Do nothing if the demuxer hasn't been instantiated.
            if (_demuxer == null) return;

            var duration = (float)_demuxer.Duration;

            // Check if _time is still in the same frame of _storedTime.
            // Resync is needed when it went out of the frame.
            var dt = duration / _demuxer.FrameCount;
            var resync = _time < _storedTime || _time > _storedTime + dt;

            // Check if the speed was externally modified.
            if (_speed != _storedSpeed)
            {
                resync = true; // Resync to adapt to the new speed.
                _storedSpeed = _speed;
            }

            // Time clamping
            var t = _loop ? _time : Mathf.Clamp(_time, 0, duration);

            // Determine if background decoding is available.
            // Resync shouldn't happen. Not preferable in edit mode.
            var bgdec = !resync && Application.isPlaying;

            // Restart the stream reader on resync.
            if (resync) _stream.Restart(t, _speed / 60);

            if (TextureUpdater.AsyncSupport)
            {
                // Asynchronous texture update supported:
                // Decode a frame and request a texture update.
                if (bgdec) _decoder.UpdateAsync(t); else _decoder.UpdateSync(t);
                _updater.RequestAsyncUpdate();
            }
            else if (bgdec)
            {
                // Synchronous texture update with background decoding:
                // Update first, then start background decoding. This
                // introduces a single frame delay but makes it possible to
                // offload decoding load to a background thread.
                _updater.UpdateNow();
                _decoder.UpdateAsync(t);
            }
            else
            {
                // Synchronous decoding and texture update.
                _decoder.UpdateSync(t);
                _updater.UpdateNow();
            }

            // Update the stored time.
            if (Application.isPlaying && !_externalTime)
                _time += Time.deltaTime * _speed;
            _storedTime = _time;

            // External object updates
            UpdateTargetRenderer();
            UpdateTargetTexture();
        }

        #endregion
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StarCellMove : ParticleBase {

    [HideInInspector] public int index;
    [Range(0, 1000)] public float spinAroundSpeed = 100;
    [Range(0, 1000)] public float localMoveSpeed = 100;
    //public bool isUseSphereBoundary = false;
    public float distance;

    // Use this for initialization
    void Start () {
        Initialized();
        StartCoroutine(spinAround());
	}
	
	// Update is called once per frame
	void Update () {
        Run();
        OutputValue();
	}
    void RandomRotation()
    {
        
    }
    public float speed = 10f;
    IEnumerator spinAround()
    {
        while (true)
        {
            transform.Rotate(0, 0, ((spinAroundSpeed * Mathf.PerlinNoise(Time.time, Time.time)) * Time.deltaTime));
            Run();
            yield return new WaitForEndOfFrame();
        }

    }

    void Run()
    {
        direction += new Vector3(
            Mathf.Sin(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI)),
            Mathf.Cos(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI)), 0);
        direction = direction.normalized;
        direction.Set(direction.x, direction.y, 0);
        velocity = Mathf.PerlinNoise(Time.time + index, index) * direction * localMoveSpeed * Time.deltaTime;
        //distance = transform.parent.localScale.x * transform.parent.GetComponent<SphereCollider>().radius;
        //if(Vector3.Distance(this.transform.localPosition,transform.parent.position) > distance * 0.5f && isUseSphereBoundary)
        //{
        //    velocity = -velocity;
        //}
    }

    Rigidbody m_rigidbody;
    void OutputValue()
    {

        m_rigidbody.velocity = velocity;
        m_rigidbody.angularVelocity = angVelocity;

    }
    public void AttributeInitialze()
    {
        velocity = Vector3.zero;
        angVelocity = Vector3.zero;
        index = Random.Range(0, 823231);
    }
    public void Initialized()
    {
        m_rigidbody = GetComponent<Rigidbody>();
    }

}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CircleBoundary : MonoBehaviour {
    float radius;
    Vector3 center;
	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class SpingWormCornerBehaviour : MonoBehaviour {

    MovingMode state;
    public enum MovingMode
    {
        SinWave,
        ScaleUp,

    }

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StraightMove : ParticleBase {
    int index = 1;
    public float localMoveSpeed = 0.5f;
    Rigidbody m_rigidbody;
    private void Start()
    {
        m_rigidbody = GetComponent<Rigidbody>();
        PositionInitialize();
    }
    private void Update()
    {
        Run();
        OutputValue();
    }
    void PositionInitialize()
    {
        this.transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, 0);
    }
    void Run()
    {

        //direction = direction.normalized;
        //direction.Set(direction.x, direction.y, 0);
        direction = Vector3.right;
        velocity = Mathf.PerlinNoise(Time.time + index, index) * direction * localMoveSpeed * Time.deltaTime;

    }
    void OutputValue()
    {

        //m_rigidbody.velocity = velocity;
        m_rigidbody.MovePosition(transform.position + velocity);
        //m_rigidbody.AddForce(velocity);
        //m_rigidbody.angularVelocity = angVelocity;

    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpringJointWormHunter : Hunter
{
}
public class SpringJointWormBehaviour : ParticleBehaiour
{
    [Header("Move motion setting")]
    [Tooltip("multiply")] public float globalMoveSpeed = 1;
    public float moveSpeed = 1;
    public int direction = 1;

    private int index;
    private float timer;
    private float timerAtFirst;
    float nextTimeToEatOrBeEaten;
    private void Start()
    {
        InitializeComponent();

    }

    private void FixedUpdate()
    {
        LifeCycleStateSelector();
    }

    #region state setting function
    //state setting function

    //life state funtion region
    public override void LifeCycleStateSelector()
    {
        timer += Time.deltaTime;
        switch (stateNow)
        {
            case ParticleLifeState.RebornDelay:
                stateNow = ParticleLifeState.Start;
                break;
            case ParticleLifeState.Start:
                Initialize();
                break;
            case ParticleLifeState.Update:
                IdldeEventHandler();
                break;
            case ParticleLifeState.End:
                EndBehaviour();
                break;

        }
    }
    public override void Initialize()
    {

        direction = m_Boundary.worldCenter.x - transform.position.x > 0 ? 1 : -1;
        RegenerateStartPosition(direction);
        //GetComponent<SpriteRenderer>().color = firstColor;
        stateNow = ParticleLifeState.Update;
        timer = 0;
    }
    public void EndBehaviour()
    {
        stateNow = ParticleLifeState.RebornDelay;
    }
    void FirstUpdateEventHandler()
    {
        timerAtFirst += Time.deltaTime;
    }

    void IdldeEventHandler() { 
        if (!m_Boundary.isPointInside(transform) && timer > 5)
        {
            stateNow = ParticleLifeState.End;
        }
        Run(); 
    }
    void EndOfUpdateEventHandler(){}

    #endregion

    #region behaviour function

    //behaviour function
    void Run()
    {
        float velocity = Mathf.PerlinNoise(Time.time + index, index) * direction * moveSpeed * Time.deltaTime;
        m_rigidbody.MovePosition(transform.position + velocity * Vector3.right);

    }
    #endregion
        
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(ScreenSpaceBoundary))]
public class ParticleEmitter : MonoBehaviour {
    public int maxNumber = 100;
    public GameObject particle;
    //public MainParticleLifeCycleAttribbute allParticleAttribute = new MainParticleLifeCycleAttribbute();

    [HideInInspector]public List<GameObject> particleList;
    private void Initialized()
    {
        if(particleList.Count > 0)
        {
            particleList.Clear();
        }

    }
    private void Awake()
    {
        Initialized();
        Emitter();
    }
    void Emitter()
    {
        
        for (int i = 0; i < maxNumber;i++)
        {
            GameObject clone = Instantiate(particle);
            clone.transform.parent = this.transform;
            particleList.Add(clone);
        }

    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using System.Security.Cryptography.X509Certificates;
//using System.Runtime.Remoting;
//using System.Security.Policy;

public class SpringJointWormGenerator : MonoBehaviour {
    
    [Header("Single Shape Setting")]
    [Range(5,12)]public int frequency = 5;
    [Range(1, 10)] public float radius;
    public Material material;
    public Mesh mesh;

    public Color centerColor;
    public Color cornerColor;

    [Header("Single Worm Physic Attribute Setting")]
    public float mass = 50;
    public float drag = 1.5f;
    public float spring = 50f;
    public RigidbodyConstraints constraints = RigidbodyConstraints.FreezeRotation;

    [Header("Moving Attribute")]
    public float minSpeedOfSpinAround = 50;
    public float maxSpeedOfSpinArdoun = 150;

    [Header("Random Attribute range")]
    public bool isUseRandomAttribute = true;

    public Gradient randomCenterColor;
    public Gradient randomCornerColor;

    public Vector2 randomFrequencyBetweenTwoConstant = new Vector2(5,12);
    public Vector2 randomRadiusBetweenTwoConstant = new Vector2(1, 15);
    public Vector2 minSpinAroundBetweenTwoConstant = new Vector2(75, 100);
    public Vector2 maxSpinAroundBetweenTwoConstant = new Vector2(100, 200);
    #region private attribute
    bool alreadyBuild = false;
    float index;
    public GameObject center;
    public List<GameObject> cornerList;
    ScreenSpaceBoundary m_Boundary;
    #endregion

    //List<GameObject> particles;

    // Use this for initialization
    void Start () 
    {
        PositionInitialize();
        RandomBornSetting();
        StartCoroutine(checkEveryCorner());
        GameObjectGenerator();
	}
    IEnumerator checkEveryCorner()
    {
        while(true)
        {
            for (int i = 0; i < cornerList.Count;i++)
            {
                if(cornerList[i].GetComponent<ParticleBase>().isBeaten)
                {
                    
                    cornerList[i].GetComponent<ParticleBase>().FadeIn();
                }
            }
            yield return new WaitForSeconds(10f);
        }

    }
    void PositionInitialize()
    {
        this.transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, 0);
    }

    void RandomBornSetting()
    {
        if (!isUseRandomAttribute) return;
        m_Boundary = transform.parent.GetComponent<ScreenSpaceBoundary>();

        this.transform.localPosition = new Vector3(
            Random.Range(m_Boundary.minX, m_Boundary.maxX),
            Random.Range(m_Boundary.minY, m_Boundary.maxY), 0);
        
        index = Random.Range(12452, 59291241);
        frequency = (int)Random.Range(randomFrequencyBetweenTwoConstant.x, randomFrequencyBetweenTwoConstant.y);
        radius = (int)Random.Range(randomRadiusBetweenTwoConstant.x, randomRadiusBetweenTwoConstant.y);

        minSpeedOfSpinAround = Random.Range(minSpinAroundBetweenTwoConstant.x, minSpinAroundBetweenTwoConstant.y);
        maxSpeedOfSpinArdoun = Random.Range(maxSpinAroundBetweenTwoConstant.x, maxSpinAroundBetweenTwoConstant.y);
        //color setting 
        float randomSeed = Mathf.Sin(minSpeedOfSpinAround + maxSpeedOfSpinArdoun) *
                           Mathf.Cos(maxSpeedOfSpinArdoun - minSpeedOfSpinAround);
        
        centerColor = randomCenterColor.Evaluate(Mathf.PerlinNoise(index, randomSeed));
        cornerColor = randomCornerColor.Evaluate(Mathf.PerlinNoise(index * randomSeed, index));

        //Debug.Log(Mathf.PerlinNoise(index * Mathf.Sin(index), index * Mathf.Sin(index)));

        
    }

    void GeneratorCenter()
    {
        center = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        center.name = "Center";
        center.tag = "SpringJointWorm";
        center.layer = 12;

        center.GetComponent<MeshFilter>().mesh = mesh;
        center.GetComponent<MeshRenderer>().material = material;
        center.GetComponent<SphereCollider>().enabled = false;
        center.AddComponent<Rigidbody>();
        center.AddComponent<SpinAround>();
        center.AddComponent<ParticleBase>();

        Rigidbody rigidbody = center.GetComponent<Rigidbody>();
        rigidbody.constraints = RigidbodyConstraints.FreezePosition | RigidbodyConstraints.FreezeRotation;
        rigidbody.useGravity = false;

        center.transform.parent = this.transform;
        center.transform.localPosition = Vector3.zero;

        center.GetComponent<SpinAround>().minSpeed = minSpeedOfSpinAround;
        center.GetComponent<SpinAround>().maxSpeed = maxSpeedOfSpinArdoun;
        center.GetComponent<SpinAround>().direction = ((int)index % 2 == 0) ? 1:-1;
        center.GetComponent<Renderer>().material.SetColor("_Color", centerColor);

    }

    void GameObjectGenerator()
    {
        if (center == null) GeneratorCenter();
        for (int i = 0; i < frequency;i++)
        {
            float angle = (360 * i / (frequency)) * Mathf.Deg2Rad;
            float x = transform.position.x + radius * Mathf.Sin(angle);
            float y = transform.position.y + radius * Mathf.Cos(angle);

            GameObject corner = new GameObject();
            corner.name = "corner" + i;
            corner.layer = 12;
            corner.transform.parent = this.transform;
            corner.transform.localScale *= transform.localScale.x;
            corner.transform.position = new Vector3(x,y,transform.position.z);

            //add composnent
            corner.AddComponent<MeshFilter>();
            corner.AddComponent<MeshRenderer>();
            corner.AddComponent<Rigidbody>();
            corner.AddComponent<SphereCollider>();
            corner.AddComponent<SpringJoint>();
            corner.AddComponent<ParticleBase>();

            //setting stage
            material = Instantiate(material);
            material.SetColor("_Color", cornerColor);
            corner.GetComponent<MeshFilter>().mesh = mesh;
            corner.GetComponent<MeshRenderer>().material = material;

            Rigidbody rigidbody = corner.GetComponent<Rigidbody>();
            rigidbody.mass = mass;
            rigidbody.drag = drag;
            rigidbody.constraints = constraints;
            rigidbody.useGravity = false;

            SpringJoint joint = corner.GetComponent<SpringJoint>();
            joint.connectedBody = center.GetComponent<Rigidbody>();
            joint.autoConfigureConnectedAnchor = true;
            joint.spring = 50;
            joint.damper = 5;
            cornerList.Add(corner);
            //particles.Add(corner);
        }
        alreadyBuild = true;
    }

}
<file_sep># AIParticleSystem
an Ai Particle system 
[link](https://www.instagram.com/p/ByuZsNYA7yz/?utm_source=ig_web_copy_link)
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Security.Cryptography;
using System;
using UnityEngine.Experimental.UIElements;
/// <summary>
/// tip : need change the project setting collision let same tag object wont happen collision
/// </summary>
//[System.Serializable]
//public struct Snake
//{

//    public GameObject headPrefab;
//    public GameObject bodyPrefab;

//    public Color headColor;
//    public Color bodyColor;

//    public List<GameObject> bodyList;
//    public bool[] bodyStayBoundaryCheckList;
//}
//using UnityEditor.ShaderGraph;
public enum SnakeLifeStage
{
    RebornDelay,
    Start,
    Update,
    End
}
public enum SnakeMotionStage
{
    Idle,
    Hunting,
    Eating,
    BeEaten
}

public class SnakeParticleGenerator : MonoBehaviour
{

    [Header("Prefabs Attribute setting")]
    public GameObject headPrefab;
    public GameObject bodyPrefab;

    [Header("Apearence Attribbute")]
    public Color headColor;
    public Color bodyColor;

    [Tooltip("only affect at fisrt time(start)")] public int numberOfBody = 5;
    public int minBodyNunber = 3;
    [Tooltip("change by realtime")] public float bodyDistance;

    [Header("Motion Related Attribbute")]
    public Vector2 rebornDelay = new Vector2(2, 5);
    [Tooltip("How long will it reborn after leaving boundary")]
    public float endingDelay = 1.5f;
    [Tooltip("The moving speed")]
    public float speed = 1;
    public float maxMoveSpeed = 3.4f;


    [Header("Sensor Related Attribute")]
    [Tooltip("defalt value : o.5 so at least bigger than 0.5f")]
    public float SensorTriggerRadius = 1f;
    public SortingLayer HuntingTarget;
    public int HowMuchNumberForEatingToGrowUp = 5;
    [Tooltip("the max number that you can add to snake")]
    public int snakeAddingMaxNumber = 10;

    
    [Header("Snake body animation")]
    public bool isUseSnakeBodyAnimation = true;
    public Color color1 = Color.white;
    public Color color2 = Color.white;

    public Color beEatenColor = Color.red;
    public float animationClipTime = 1;
    public float animationFreshRate = 20f;
    
    public float AnimationSpeed = 1;
    bool isUseAntiOrder=false;
    public int maxIntervalNumber = 3;

    
    [Header("state visualizer")]
    public AnimationState animationState;
    public enum AnimationState
    {
        start,
        update,
        end
    }
    [HideInInspector] public bool ifAllStayInBoundary;
    [HideInInspector] public int direction = 1;

    int index;
    float timer;
    float timerAtEnd;
    float rebbornDelayTime;
    int eatNumber;

    //stage control
    public SnakeLifeStage m_stage = SnakeLifeStage.Update;
    public SnakeMotionStage m_updateStage = SnakeMotionStage.Idle;

    [HideInInspector] public List<GameObject> bodyList = new List<GameObject>();
    GameObject head;
    ScreenSpaceBoundary m_Boundary;

    public ParticleSystem deathParticleEffect;
    SnakeHead m_head
    {
        get
        {
            return bodyList[0].GetComponent<SnakeHead>();
        }
    }

    bool isBeEaten
    {
        get{
            foreach(GameObject body in bodyList)
            {
                bool _isBeEaten = body.GetComponent<ParticleBase>().isBeaten;
                if(_isBeEaten)return true;
            }
            return false;
        }
    }
    //[Header("setting Boundary Attribute ")]
    //public bool isUseBoundarySystem;
    //public bool isUseRandomAttributeToReborn;
    // Use this for initialization
    void Start()
    {
        PositionInitialize();
        SnakeGenerator();
        AttributeIniate();
        StartCoroutine(SnakeColorLerpAnimation());
    }

    // Update is called once per frame
    void Update()
    {
        LifeCycleStageSelector();
        //SnakeMove();
    }

    IEnumerator StageController()
    {
        while (true)
        {
            LifeCycleStageSelector();
            yield return new WaitForEndOfFrame();
        }
    }

    void LifeCycleStageSelector()
    {
        timer += Time.deltaTime;
        //switch
        switch (m_stage)
        {
            case SnakeLifeStage.RebornDelay:
                if (timer > rebbornDelayTime)
                {
                    m_stage = SnakeLifeStage.Start;
                    UpdateCycleStageSelector();
                }
                break;

            case SnakeLifeStage.Start:
                timer = 0;
                SnakeInitializer();
                m_stage = SnakeLifeStage.Update;
                break;

            case SnakeLifeStage.Update:
                UpdateCycleStageSelector();
                break;

            case SnakeLifeStage.End:
                m_stage = SnakeLifeStage.RebornDelay;
                break;
        }
    }
    bool isTimerEnd = true;
    IEnumerator animationSpeedUp(float _timeLength,float _speed)
    {
        if(!isTimerEnd)yield break;
        isTimerEnd = false;
        AnimationSpeed = _speed;
        speed *=2;
        yield return new WaitForSeconds(_timeLength);
        AnimationSpeed = 1;
        speed /= 2;
        isTimerEnd = true;
    }
    IEnumerator animationSpeedDown(float _timeLength,float _speed)
    {
        if(!isTimerEnd)yield break;
        Color temp = color2;
        color2 = beEatenColor;
        isTimerEnd = false;

        updownSpeed = 5;
        if(bodyList.Count > minBodyNunber )
            RemoveBody();
        animationState = AnimationState.start;
        AnimationSpeed = _speed;
        //speed *= 0.5f;
        yield return new WaitForSeconds(_timeLength);
        AnimationSpeed = 1;
        //speed *= 2;
        updownSpeed = 1;
        isTimerEnd = true;
        m_head.beEaten = false;
        color2 = temp;
    }
    void UpdateCycleStageSelector()
    {
        EventManagement();
        switch (m_updateStage)
        {
            case SnakeMotionStage.Idle:
                SnakeMove();
                break;
            case SnakeMotionStage.Hunting:
                Hunter();
                break;
            case SnakeMotionStage.Eating:
                GrowUp();
                m_updateStage = SnakeMotionStage.Idle;
                break;
            case SnakeMotionStage.BeEaten:
                SnakeMove();
                StartCoroutine(animationSpeedDown(1,0.5f));
                break;
        }
        if (timer > 5) CheckEachBodyIffStayInBoundary();
    }
    void GrowUp()
    {
        StartCoroutine(animationSpeedUp(1f,3));
        //StartCoroutine(animationSpeedDown(1,0.5f));
        eatNumber += 1;
        //Debug.Log("HowMuchNumberForEatingToGrowUp" + HowMuchNumberForEatingToGrowUp + "||Eat Number" + eatNumber);
        if (eatNumber > HowMuchNumberForEatingToGrowUp)
        {
            if (snakeAddingMaxNumber == 0)
            {
                m_updateStage = SnakeMotionStage.Idle;
                return;
            }
            snakeAddingMaxNumber -= 1;
            eatNumber = 0;
            //Debug.Log("grow");
            AddBody();
        }
        m_updateStage = SnakeMotionStage.Idle;
    }

    //define what stage should be 
    void EventManagement()
    {
        SnakeHead m_head = head.GetComponent<SnakeHead>();
        if (m_head.HuntingList.Count > 1 && !m_head.beEaten)
        {
            m_updateStage = SnakeMotionStage.Hunting;
        }
        else if (m_head.HuntingList.Count == 0 && !m_head.beEaten)
        {
            m_updateStage = SnakeMotionStage.Idle;
        }
        else if (m_head.beEaten)
        {
            m_updateStage = SnakeMotionStage.BeEaten;
        }
        else if (m_head.getIfEating)
        {
            m_updateStage = SnakeMotionStage.Eating;
        }

    }
    public bool ifHaveTarget = false;
    public GameObject mostCloseTarget = null;
    public GameObject currentTarget
    {
        get
        {
            return m_head._currentTarget;
        }
        set
        {
            m_head._currentTarget = value;
        }
    }
    void Hunter()
    {
        if (!ifHaveTarget)
        {
            ChooseTarget();
        }
        TracingTarget();
    }
    void ChooseTarget()
    {
        if (m_head.HuntingList.Count > 0)
        {
            float mostCloseDistance = 0;
            for (int i = 0; i < m_head.HuntingList.Count; i++)
            {
                float distanceToTarget = Vector3.Distance(m_head.transform.position, m_head.HuntingList[i].transform.position);
                if (mostCloseTarget == null)
                {
                    currentTarget = m_head.HuntingList[i];
                    mostCloseDistance = Vector3.Distance(m_head.transform.position, currentTarget.transform.position);
                }
                else if (distanceToTarget < mostCloseDistance)
                {
                    currentTarget = m_head.HuntingList[i];
                    mostCloseDistance = distanceToTarget;
                }
            }
        }
        else if (m_head.HuntingList.Count == 0)
        {
            //Debug.Log("lost target");
            m_updateStage = SnakeMotionStage.Idle;
        }
    }

    void TracingTarget()
    {
        float distanceToTarget = Vector3.Distance(m_head.transform.position, currentTarget.transform.position);
        for (int i = 0; i < bodyList.Count; i++)
        {

            if (i == 0)
                TracingMove(bodyList[i]);
            else
                CheckDistanceWithForward(bodyList[i - 1], bodyList[i]);

        }
        if (distanceToTarget < 1.39f)
        {
            m_updateStage = SnakeMotionStage.Eating;
            GrowUp();
        }

    }
    void TracingMove(GameObject _head)
    {
        //Vector3 velocity = (currentTarget.transform.position - _head.transform.position ).normalized* speed * 1.5f * Time.deltaTime;
        //_head.GetComponent<Rigidbody>().MovePosition(_head.transform.position + velocity);

        float _distance = Vector3.Distance(currentTarget.transform.position, _head.transform.position);
        Vector3 dir = (currentTarget.transform.position - _head.transform.position).normalized;
        float t = Time.deltaTime * _distance / 2 * speed * 0.35f;
        if (t > 0.5) t = 0.5f;
        _head.GetComponent<Rigidbody>().MovePosition(
            Vector3.Slerp(_head.transform.position, currentTarget.transform.position, t));
    }

    void PositionInitialize()
    {
        this.transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, 0);
    }

    void AttributeIniate()
    {
        index = UnityEngine.Random.Range(12345, 823231);

        //stage initialize
        m_stage = SnakeLifeStage.RebornDelay;
        m_updateStage = SnakeMotionStage.Idle;

        m_Boundary = transform.parent.GetComponent<ScreenSpaceBoundary>();
        rebbornDelayTime = UnityEngine.Random.Range(rebornDelay.x, rebornDelay.y);
        deathParticleEffect.Stop();
    }

    void SnakeInitializer()
    {
        //Head and body position random setting
        direction = UnityEngine.Random.Range(0, 100) > 50 ? 1 : -1;
        transform.localPosition = RegenerateStartPosition(direction);
        PositionInitialize();
        if (direction == 1)
        {

            for (int i = 0; i < bodyList.Count; i++)
            {
                if(i>=bodyList.Count)return;
                //head setting 
                if (i == 0)
                {
                    bodyList[0].transform.localPosition = Vector3.zero;
                    bodyList[0].GetComponent<Rigidbody>().Sleep();
                    bodyList[0].GetComponent<SnakeHead>().beEaten = false;

                }
                //body setting
                else
                {
                    bodyList[i].transform.localPosition = bodyList[0].transform.localPosition;
                    bodyList[i].GetComponent<Rigidbody>().Sleep();
                }

                //bodyList[i].GetComponent<ParticleBase>().isBeaten = false;
            }
        }
        else
        {

            for (int i = 0; i < bodyList.Count; i++)
            {
                if(i>=bodyList.Count)return;
                //head setting 
                if (i == 0)
                {
                    bodyList[0].transform.localPosition = Vector3.zero;
                }
                //body setting
                else
                {
                    bodyList[i].transform.localPosition = bodyList[0].transform.localPosition; ;
                }
            }
        }
    }


    void CheckEachBodyIffStayInBoundary()
    {
        //bool[] checklist = new bool[bodyList.Count];
        for (int i = 0; i < bodyList.Count; i++)
        {
            if(i>=bodyList.Count)return;
            if (m_Boundary.isPointInside(bodyList[i].transform))
            {
                //Debug.Log("stay");
                return;
            }
        }
        timerAtEnd += Time.deltaTime;
        if (timerAtEnd > endingDelay)
        {
            timer = 0;
            timerAtEnd = 0;
            m_stage = SnakeLifeStage.End;
            //Debug.Log("exit");
        }
        return;
    }

    Vector3 RegenerateStartPosition(int direction)
    {
        float newPositionX = (direction == 1 ? m_Boundary.minX : m_Boundary.maxX) - 5f * direction;
        float newPositionY = (m_Boundary.maxY + m_Boundary.minY) / 2 + ((m_Boundary.maxY - m_Boundary.minY) / 4) * Mathf.Sin(Time.time * 0.5f);
        Vector3 newPosition = new Vector3(newPositionX, newPositionY, 0);
        return newPosition;
    }

    void SnakeGenerator()
    {
        HeadGenerator();
        BodyGenerator();
    }

    void HeadGenerator()
    {
        GameObject Head = (Instantiate(headPrefab) as GameObject);
        Head.transform.parent = this.transform;
        Head.transform.localPosition = new Vector3(0, 0, 0);

        Head.GetComponent<Renderer>().material.SetColor("_TintColor", headColor);
        Head.GetComponent<ParticleBase>().maxMoveSpeed = maxMoveSpeed;
        Head.GetComponent<SphereCollider>().radius = SensorTriggerRadius;

        //Snake layer
        Head.layer = 13;
        bodyList.Add(Head);
        head = Head;
    }
    void BodyGenerator()
    {

        for (int i = 1; i <= numberOfBody; i++)
        {
            GameObject body = (Instantiate(bodyPrefab) as GameObject);
            body.transform.parent = this.transform;
            body.transform.position = bodyList[0].transform.position;
            body.GetComponent<Renderer>().material.SetColor("_TintColor", bodyColor);
            body.layer = 13;
            body.GetComponent<Rigidbody>().isKinematic = true;
            if (i % 3 == 0)
            {
                body.GetComponent<Rigidbody>().isKinematic = false;
            }

            if (bodyList[i - 1] == null)
            {
                HeadGenerator();
            }
            bodyList.Add(body);
        }
    }

    void SnakeMove()
    {
        //Debug.Log("StageControl");
        for (int i = 0; i < bodyList.Count; i++)
        {
            if (i == 0)
            {
                HeadMove(bodyList[i]);

            }
            else
            {
                CheckDistanceWithForward(bodyList[i - 1], bodyList[i]);
            }
        }
    }

    void CheckDistanceWithForward(GameObject forward, GameObject current)
    {
        current.GetComponent<Rigidbody>().Sleep();
        float _distance = Vector3.Distance(forward.transform.position, current.transform.position);
        Vector3 dir = (forward.transform.position - current.transform.position).normalized;
        float t = Time.deltaTime * _distance / bodyDistance * speed;
        if (t > 0.5) t = 0.5f;
        current.GetComponent<Rigidbody>().MovePosition(
                Vector3.Slerp(current.transform.position, forward.transform.position, t));

    }

    float updownSpeed = 1;
    void HeadMove(GameObject _head)
    {
        _head.GetComponent<Rigidbody>().Sleep();
        if (direction == 0) direction = 1;
        float moveX = (Mathf.PerlinNoise(Time.time + index, index) - 0.1f) * 2 * speed * Time.deltaTime * direction;
        float moveY = Mathf.Sin((Time.time)+ index) * 3 * Time.deltaTime *(1/updownSpeed);
        Vector3 velocity = new Vector3(moveX, moveY, 0);
        _head.GetComponent<Rigidbody>().MovePosition(_head.transform.position + velocity);
        //Debug.Log(velocity);
        //if(!m_Boundary.isPointInside(_head.transform) && timer > 5)
        //{
        //    _head.GetComponent<Rigidbody>().MovePosition(_head.transform.position - velocity * 2);
        //}

    }

    void AddBody()
    {
        GameObject body = (Instantiate(bodyPrefab) as GameObject);
        body.transform.parent = this.transform;
        body.transform.position = bodyList[bodyList.Count - 1].transform.position;
        body.layer = 13;
        body.GetComponent<Renderer>().material.SetColor("_TintColor", bodyColor);
        bodyList.Add(body);
    }
    void RemoveBody()
    {
        GameObject removeTarget = bodyList[bodyList.Count - 1];
        snakeAddingMaxNumber ++;
        bodyList.Remove(removeTarget);
        removeTarget.transform.parent = GameObject.Find("TrashLayer").transform ;
        removeTarget.tag = "LittleParticle";
        removeTarget.layer = 9;

        deathParticleEffect.transform.position = bodyList[bodyList.Count-1].transform.position;
        deathParticleEffect.Play();

        removeTarget.AddComponent<MainParticleLifeCycle>().fisrtColor = color1;
        removeTarget.GetComponent<MainParticleLifeCycle>().finalColor = color2;
        removeTarget.GetComponent<MainParticleLifeCycle>().localMoveSpeed = 0;
        removeTarget.GetComponent<MainParticleLifeCycle>().m_stage = mainParticleStage.update;
        removeTarget.GetComponent<MainParticleLifeCycle>().lifeTime = 60f;
    }
    #region  bodyAnimation
    bool isLoop = true;
    bool[] states;
    float animationTimer;

    IEnumerator SnakeColorLerpAnimation()
    {
        //if(!isUseSnakeBodyAnimation)isLoop = false;
        while (isLoop)
        {
            stateSelector();
            AnimationStateSelector();
            //Debug.Log("Refresh animation");
            yield return new WaitForSeconds(1/animationFreshRate);
        }
    }
    public bool isPlaying
    {
        get
        {
            if ((int)animationTimer / animationClipTime <= 0 || (int)animationTimer / animationClipTime >= 1)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
    void AnimationStateSelector()
    {
        switch(animationState)
        {
            case AnimationState.start:
                InitializeAnimation(ref states);
                break;
            case AnimationState.update:
                UpdateAnimation(ref states);
                break;
            case AnimationState.end:
                EndAnimation(ref states);
                break;
        }
    }
    public virtual void InitializeAnimation(ref bool[] _states)
    {
        states = new bool[bodyList.Count];
        animationTimer += Time.deltaTime * Mathf.Abs(AnimationSpeed);
    }
    public virtual void UpdateAnimation(ref bool[] _states) {
         animationTimer += Time.deltaTime * Mathf.Abs(AnimationSpeed); 
         AnimatiionLogic_1(isUseAntiOrder,maxIntervalNumber,ref states);
    }
    public virtual void EndAnimation(ref bool[] _states)
    {
        animationTimer = 0;
    }

    public void stateSelector(){
            if (animationTimer == 0)
                animationState = AnimationState.start;
            else if (animationTimer > 0 && animationTimer < animationClipTime)
                animationState = AnimationState.update;
            else if (animationTimer > animationClipTime)
                animationState = AnimationState.end;
        }
    void AnimatiionLogic_1(bool _isUseAntiOrder, int maxDarkNumber, ref bool[] _states)
    {
        int dir = _isUseAntiOrder ? -1 : 1;
        int timeIndex = (int)Mathf.Lerp(0, _states.Length + (maxDarkNumber), animationTimer / animationClipTime) * dir;
        int min = (_isUseAntiOrder ? (_states.Length - 1) + maxDarkNumber : 0 - maxDarkNumber) + timeIndex;
        int max = (_isUseAntiOrder ? min - (maxDarkNumber - 1) : min + (maxDarkNumber - 1));
        //Debug.Log("min : " + min + " max : " + max);
        for (int i = 0; i < _states.Length; i++)
        {
            float i_min = Mathf.Abs(i - min);
            float i_max = Mathf.Abs(i - max);
            //Debug.Log("min : " + min + " max : " + max + " i : " + i + " i-max : " + i_max + " i-min : " + i_min);
            if (i_min + i_max < maxDarkNumber)
            {
                _states[i] = LogicStateSetting.State1 ;
                //Debug.Log("Lighting up");
            }
            else
            {
                _states[i] = LogicStateSetting.State2;

                //Debug.Log("Lighting off");
            }
        }
        if(!isUseSnakeBodyAnimation) return;

        Color[] listColor = new Color[_states.Length];
        float center = (max + min)/2 ;

        for (int i = 0; i < listColor.Length; i++)
        {
            //Debug.Log(_states[i]);
            //Debug.Log("min : " + min + " max : " + max + " i : " + i + " i-max : " + i_max + " i-min : " + i_min);
            if (_states[i])
            {

                float index = i >= center ? i - center : center - i;
                float length = i >= center ? max - center : center - min;
                listColor[i] = Color.Lerp(color2, color1, index / length);
            }
            else
            {
                listColor[i] = color1;
            }
            if(i<bodyList.Count)
                bodyList[i].GetComponent<MeshRenderer>().material.SetColor("_TintColor", listColor[i]);
        }


    }
    #endregion

}
public static class LogicStateSetting
{
    //default true
    public static bool State1 = true;
    //default false
    public static bool State2 = false;
    //public bool isUseAntiLogic = false;
}
public class SnakeParticleBoundaryEvent : BoundaryEvent
{

    public override void StayBoundary()
    {
        throw new NotImplementedException();
    }
    public override void ExitBoundary()
    {
        throw new NotImplementedException();
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractiveSystemWithMainParticle : MonoBehaviour {

    [Header("Force")]
    public float RepulsiveForce = 100f;
    public float AttrativeForce = 10f;

    [Header("VisualizerObject")]
    public GameObject ExplosionVisualizer;
    public GameObject TirggerVidsualizer;
    public GameObject ColliderObject;
    bool UseDebugVisualizer = false;

    [Header("Radius")]
    [Range(0.5f, 20f)] public float attractiveRadius = 10f;
    [Range(0.5f, 20f)] public float triggerRadius = 2f;
    [Range(0.5f, 20f)] public float explosionRadius = 5f;
    //[Range(0.5f, 20f)]public float deathRadius = 0.5f;

    [Header("Time Setting")]
    public float explosionTime = 0.3f;
    public float attractiveTime = 10f;
    private float timer;

    //計算吸收數量
    public int substractNumber = 0;
    public int HowManyToGrow = 20;

    Rigidbody m_rigidbody;
    SphereCollider m_collider;

    public PlayerStage m_stage = PlayerStage.Beginning;
    public enum PlayerStage
    {
        Beginning,
        update,
        end
    }

	// Use this for initialization
	void Start () {
        GetComponent<Star>().frequency += 1;
        StartCoroutine(StageControl());
	}
	
	// Update is called once per frame
	void Update () {
        if(substractNumber>HowManyToGrow)
        {
            GetComponent<Star>().frequency += 1;
            GetComponent<Star>().Reset();
            substractNumber = 0;
            //Debug.Log(GetComponent<Star>().frequency);
        }
	}
    private void Initialize()
    {
        //component setting
        m_collider = this.GetComponent<SphereCollider>();
        m_rigidbody = this.GetComponent<Rigidbody>();

        //game object setting
        if (ExplosionVisualizer == null)
        {
            GameObject _ExplosionVisualizer = new GameObject();
            _ExplosionVisualizer.name = "_ExplosionVisualizer";
            _ExplosionVisualizer.AddComponent<MeshFilter>();
            _ExplosionVisualizer.AddComponent<MeshRenderer>();
            _ExplosionVisualizer.transform.localScale = Vector3.one * explosionRadius;

            ExplosionVisualizer = _ExplosionVisualizer;
        }
        else
        {
            ExplosionVisualizer.transform.localScale = Vector3.one * explosionRadius;

        }

        if (TirggerVidsualizer == null)
        {
            GameObject _TirggerVidsualizer = new GameObject();
            _TirggerVidsualizer.name = "_ExplosionVisualizer";
            _TirggerVidsualizer.AddComponent<MeshFilter>();
            _TirggerVidsualizer.AddComponent<MeshRenderer>();
            _TirggerVidsualizer.transform.localScale = Vector3.one * triggerRadius / 2;

            TirggerVidsualizer = _TirggerVidsualizer;
        }
        else
        {
            TirggerVidsualizer.transform.localScale = Vector3.one * triggerRadius;
        }

        if (ColliderObject == null)
        {
            GameObject _ColliderObject = new GameObject();
            _ColliderObject.name = "_ExplosionVisualizer";
            _ColliderObject.AddComponent<MeshFilter>();
            _ColliderObject.AddComponent<MeshRenderer>();
            _ColliderObject.transform.localScale = Vector3.one * triggerRadius;

            ColliderObject = _ColliderObject;
        }
        else
        {
            ColliderObject.transform.localScale = this.transform.localScale;
        }

        if(!UseDebugVisualizer)
        {
            TirggerVidsualizer.SetActive(false);
            ExplosionVisualizer.SetActive(false);
        }
    }

    void AttributeInitialize()
    {
        switch (m_stage)
        {
            //explosion stage
            case PlayerStage.Beginning:
                m_collider.radius = explosionRadius/2;
                substractNumber = 0;
                if(UseDebugVisualizer)
                {
                    ExplosionVisualizer.SetActive(true);
                    TirggerVidsualizer.SetActive(false);
                    ExplosionVisualizer.transform.localScale = new Vector3(explosionRadius, explosionRadius, explosionRadius);
                }

               
                break;

            //Attractive stage
            case PlayerStage.update:
                m_collider.radius = attractiveRadius/2;
                //substractNumber = 0;

                if(UseDebugVisualizer)
                {
                    ExplosionVisualizer.SetActive(false);
                    TirggerVidsualizer.SetActive(true);
                    TirggerVidsualizer.transform.localScale = new Vector3(attractiveRadius, attractiveRadius, attractiveRadius);
                }


                break;

            case PlayerStage.end:
                break;
                            
        }
    }

    IEnumerator StageControl()
    {
        Initialize();
        while(true)
        {
            timer = 0;
            switch(m_stage)
            {
                case PlayerStage.Beginning:
                    AttributeInitialize();
                    while(timer/explosionTime<1)
                    {
                        timer += Time.deltaTime;
                        yield return new WaitForEndOfFrame(); 
                    }
                    m_stage = PlayerStage.update;
                    break;

                case PlayerStage.update:
                    
                    AttributeInitialize();
                    while (timer / attractiveTime < 1)
                    {
                        timer += Time.deltaTime;
                        yield return new WaitForEndOfFrame();
                    }
                    m_stage = PlayerStage.Beginning;
                    break;

                case PlayerStage.end:
                    break;
            }
        }

    }

    //debug use function 
    private void OnMouseEnter()
    {
        m_stage = PlayerStage.Beginning;
        Debug.Log("On Mouse Enter");
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "LittleParticle" && (other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage == mainParticleStage.update ||
                                              other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage == mainParticleStage.end))
        {
            Rigidbody pRigbody = other.GetComponent<Rigidbody>();
            Vector3 Force;
            float distance = Vector3.Distance(other.transform.position, this.transform.position);

            switch (m_stage)
            {
                case PlayerStage.Beginning:
                    if(other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage == mainParticleStage.end)
                    {
                        other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage = mainParticleStage.update;
                    }
                    Force = (other.transform.position - this.transform.position).normalized * 
                        Mathf.Lerp(0,RepulsiveForce,distance/triggerRadius);
                    
                    pRigbody.AddForce(Force);
                    break;

                case PlayerStage.update:
                    if(other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage == mainParticleStage.update)
                    {
                        Color firstColor = other.GetComponent<MainParticleLifeCycle>().fisrtColor;
                        Color finalColor = other.GetComponent<MainParticleLifeCycle>().finalColor;
                        Color newColor = Color.Lerp(firstColor, finalColor, 1 - distance / triggerRadius);

                        //Debug.Log(1 - distance / triggerRadius);
                        other.GetComponent<MeshRenderer>().material.SetColor("_TintColor", newColor);
                    }

                    Force = (this.transform.position - other.transform.position).normalized *
                            Mathf.Lerp(AttrativeForce,AttrativeForce/2 ,distance / triggerRadius);
                    
                    if(pRigbody.GetComponent<Rigidbody>().velocity.magnitude < pRigbody.GetComponent<MainParticleLifeCycle>().maxMoveSpeed)
                        pRigbody.AddForce(Force);
                    
                    break;

                case PlayerStage.end:
                    break;
            }

        }
    }
    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "LittleParticle" && (collision.gameObject.GetComponent<MainParticleLifeCycle>().m_stage ==  mainParticleStage.end))

        {
            //Rigidbody pRigbody = collision.gameObject.GetComponent<Rigidbody>();
            switch (m_stage)
            {
                case PlayerStage.Beginning:
                    break;

                case PlayerStage.update:
                    substractNumber += 1;
                    collision.gameObject.GetComponent<MainParticleLifeCycle>().m_stage = mainParticleStage.beEaten;
                    break;

                case PlayerStage.end:
                    break;
            }

        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "LittleParticle")
        {
            other.GetComponent<MeshRenderer>().material.SetColor("_TintColor", other.GetComponent<MainParticleLifeCycle>().fisrtColor);
        }
    }


}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParticleMouse : MonoBehaviour {
    public int EatingNumber;
    public float EatingTimeInterval = 0.5f;
    public bool isEating = false;
    public bool isBeEaten = false;
    [HideInInspector] public Collider MouseCollider;
    [HideInInspector] public float timer;

    public LayerManager[] HuntingTargets;
    //ParticleSystem m_particleEffect;
	// Use this for initialization
	void Start () {
        MouseCollider = GetComponent<SphereCollider>();
	}
	
	// Update is called once per frame
	void Update () {
		
	}
    public void setHunigTarget(LayerManager[] _HuntingTargets)
    {
        HuntingTargets = _HuntingTargets;
    }
    public void Reset()
    {
        EatingNumber = 0;
        timer = 0;
        isEating = false;

    }
    void OnTriggerEnter(Collider other)
    {
        //Debug.Log(other.gameObject.layer);
        if (!isEating)
        {
            EatingEvent(other.gameObject);
        }
    }
    
    private void OnTriggerStay(Collider other)
    {
        if (!isEating)
        {
            EatingEvent(other.gameObject);
        }
    }

    public void BeEaten()
    {
        isBeEaten = true;
    }

    //call event 
    void EatingEvent(GameObject beEatenGameObject)
    {

        if(HuntingTargets == null)return;
        //Debug.Log(beEatenGameObject.layer);
        for(int i = 0;i<HuntingTargets.Length;i++)
        {
            if(beEatenGameObject.layer == (int)HuntingTargets[i])
            {
                
                switch(beEatenGameObject.layer)
                {
                    case 9:
                        beEatenGameObject.GetComponent<MainParticleLifeCycle>().BeEaten();
                        isEating = true;
                        break;

                    //player layer
                    case 10:
                        break;


                    //spring worm layer 
                    case 12:
                        beEatenGameObject.GetComponent<ParticleBase>().BeEaten();
                        isEating = true;
                        break;

                    case 13:
                        if(beEatenGameObject.GetComponent<SnakeHead>() != true)return;
                        beEatenGameObject.GetComponent<SnakeHead>().beEaten = true;
                        isEating = true;
                        break;

                    case 14:
                        if (beEatenGameObject.GetComponent<ParticleMouse>() == null || beEatenGameObject.layer == gameObject.layer) return;
                        if (!beEatenGameObject.GetComponent<ParticleMouse>().isBeEaten)
                            beEatenGameObject.GetComponent<ParticleMouse>().BeEaten();
                        else Debug.Log("Emitter has already be eaten");
                        break;

                    case 16:
                        
                        break;
                }
                break;
            }
        }
        

    }

}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class ParticleBase : MonoBehaviour{
    [HideInInspector]public float mass;
    public float lifeTime;

    [HideInInspector]public Vector3 direction;
    //[HideInInspector]public Vector3 position;
    [HideInInspector]public Vector3 velocity;
    [Range(0, 100)] public float maxMoveSpeed = 100;
    private float _lerpTime = 2;
    public bool isBeaten = false;
    [HideInInspector]public Vector3 angVelocity;
    //public float lerpTime = 1f;
    private void Update()
    {
        if(GetComponent<Rigidbody>().velocity.magnitude > maxMoveSpeed)
        {
            GetComponent<Rigidbody>().velocity = GetComponent<Rigidbody>().velocity.normalized * maxMoveSpeed;
        }
    }

    //spring joint worm use 
    public void BeEaten()
    {
        isBeaten = true;
        Color now = GetComponent<MeshRenderer>().material.GetColor("_TintColor");
        GetComponent<Collider>().enabled = false;
        GetComponent<MeshRenderer>().material.SetColor("_TintColor", new Vector4(now.r, now.g, now.b, 0));
    }

    // spring joint worm use
    public void FadeIn()
    {
        isBeaten = false;
        Debug.Log("start fade in ");
        StartCoroutine(fadein());
    }
    
    public IEnumerator fadein()
    {
        Color nowTransparent = GetComponent<Renderer>().material.GetColor("_TintColor");
        Color now = new Vector4(nowTransparent.r, nowTransparent.g, nowTransparent.b, 1f);

        GetComponent<MeshRenderer>().material.SetColor("_TintColor", nowTransparent);
        for (float i = 0; i < _lerpTime; i+=Time.deltaTime)
        {
            Color _c = Color.Lerp(nowTransparent,now , i / _lerpTime);
            //Debug.Log("fade in" + _c);
            GetComponent<MeshRenderer>().material.SetColor("_TintColor", _c);
            yield return new WaitForFixedUpdate();
        }
        GetComponent<Collider>().enabled = true;

    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Hunter
{
    public LayerManager m_Layer;
    public LayerManager[] HuntingTargets;
    public ParticleMouse mouse;
    [HideInInspector] public bool ifHasTarget
    {
        get{
            return HuntingList.Count > 0;
        }
    }
    public List<GameObject> HuntingList;
    public bool getIsEating{get { return mouse.isEating; }}

    public virtual void SelectTracingTarget()
    {

    }

    public virtual void TracingTarget()
    {

    }

}

<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.CompilerServices;
using System.Timers;
//using NUnit.Framework.Internal.Commands;
[System.Serializable]
public class WaveParticleHunter : Hunter
{

    public ParticleMouse[] mice;
    public void setHuntingTargetToMice()
    {
        for (int i = 0; i < mice.Length;i++)
        {
            mice[i].HuntingTargets = HuntingTargets;
        }
    }

    public bool getIsMiceEating {
        get {
            for (int i = 0; i < mice.Length;i++)
            {
                if (mice[i].isEating) return true;
            }
            return false; 
        } 
    }
    public bool getIsMiceBeEaten{
        get {
            for (int i = 0; i < mice.Length;i++)
            {
                if (mice[i].isBeEaten) return true;
            }
            return false; 
        } 
    }
}

public class WaveParticleBehaviour : ParticleBehaiour
{
    public WaveParticleHunter m_hunter;

    [Header("Move motion setting")]
    [Tooltip("multiply")] public float globalMoveSpeed = 1;
    public float moveSpeed = 1;
    public int direction = 1;

    [Header("Color setting")]
    public Color firstColor;
    public Color secondColor;

    [Header("Time setting")]
    public float shiningIntervalTime = 0.15f;
    public float shiningTotalTime = 2f;
    public float eatingInterval = 2f;
    public float lerpTime = 2f;

    [Header("Animation speed")]
    public float defaultAnimationSpeed = 1;
    public float EatingAnimationSpeed = 3;
    public float BeEatenAnimationSpeed = 5;
    private int index;
    private float timer;
    private float timerAtFirst;
    float nextTimeToEatOrBeEaten;

    public AudioClip waveOST;
    public AudioSource m_audioPlayer;
    private void Start()
    {
        m_hunter.setHuntingTargetToMice();
        InitializeComponent();

    }

    private void FixedUpdate()
    {
        LifeCycleStateSelector();
    }

    #region state setting function
    //state setting function

    //life state funtion region
    public override void LifeCycleStateSelector()
    {
        timer += Time.deltaTime;
        switch (stateNow)
        {
            case ParticleLifeState.Start:
                Initialize();
                break;
            case ParticleLifeState.Update:
                UpdateCycleStateSelector();
                break;
            case ParticleLifeState.End:
                EndBehaviour();
                break;

        }
    }
    public override void Initialize()
    {

        direction = m_Boundary.worldCenter.x - transform.position.x > 0 ? 1 : -1;
        RegenerateStartPosition(direction);
        GetComponent<SpriteRenderer>().color = firstColor;
        stateNow = ParticleLifeState.Update;
        timer = 0;
    }
    
    public void EndBehaviour()
    {
        stateNow = ParticleLifeState.Start;
    }

    public override void UpdateCycleStateSelector()
    {
        EventManager();
        switch (motionStateNow)
        {
            case ParticleMotionState.FirstUpdate:
                FirstUpdateEventHandler();
                break;
            case ParticleMotionState.Idle:
                GetComponent<Animator>().speed = defaultAnimationSpeed;
                IdldeEventHandler();
                break;
            case ParticleMotionState.Eating:
                break;
            case ParticleMotionState.BeEaten:
                break;
            case ParticleMotionState.EndOfUpdate:
                EndOfUpdateEventHandler();
                break;
        }
    }

    public void EventManager()
    {
        //Debug.Log("isEating" + m_hunter.getIsMiceEating);
        if (!m_Boundary.isPointInside(transform) && timer > 5)
        {
            stateNow = ParticleLifeState.End;
        }
        else if(!inAnimation &&
                Time.time > nextTimeToEatOrBeEaten &&
                m_hunter.getIsMiceBeEaten &&
                motionStateNow != ParticleMotionState.BeEaten)
        {
            
            GetComponent<Animator>().speed = BeEatenAnimationSpeed;
            StartCoroutine(ColorShining(firstColor, secondColor, shiningTotalTime, shiningIntervalTime));
            motionStateNow = ParticleMotionState.BeEaten;
        }
        else if (!inAnimation &&
                Time.time > nextTimeToEatOrBeEaten && 
                 m_hunter.getIsMiceEating &&
                 motionStateNow != ParticleMotionState.Eating)
        {
            GetComponent<Animator>().speed = EatingAnimationSpeed;
            StartCoroutine(ColorLerpChanging(firstColor, secondColor, lerpTime));
            motionStateNow = ParticleMotionState.Eating;
        }
        //else 
        //{
        //    motionStateNow = ParticleMotionState.Idle;
        //}
    }

    void FirstUpdateEventHandler()
    {
        timerAtFirst += Time.deltaTime;
    }

    void IdldeEventHandler() { Run(); }
    void EndOfUpdateEventHandler(){}

    #endregion

    #region behaviour function

    //behaviour function
    void Run()
    {
        float velocity = Mathf.PerlinNoise(Time.time + index, index) * direction * moveSpeed * Time.deltaTime;
        m_rigidbody.MovePosition(transform.position + velocity * Vector3.right);

    }
    bool inAnimation = false;
    IEnumerator ColorShining(Color _firstColor, Color _secondColor, float _shiningTotalTime, float _shiningIntervalTime)
    {
        inAnimation = true;
        int counter = 0;
        float endingTime = Time.time + _shiningTotalTime;
        Color nowColor = GetComponent<SpriteRenderer>().color;

        while (Time.time < endingTime)
        {
            counter += 1;
            switch (counter % 2)
            {
                case 1:
                    nowColor = _firstColor;
                    break;
                case 0:
                    nowColor = _secondColor;
                    break;
            }

            GetComponent<SpriteRenderer>().color = nowColor;
            yield return new WaitForSeconds(_shiningIntervalTime);

        }
        inAnimation = false;
        GetComponent<SpriteRenderer>().color = _firstColor;
        motionStateNow = ParticleMotionState.Idle;
        nextTimeToEatOrBeEaten = eatingInterval+ Time.time;
        foreach (ParticleMouse mouse in m_hunter.mice) mouse.isBeEaten = false;
    }

    IEnumerator ColorLerpChanging(Color _firstColor, Color _finalColor, float _lerpTotalTime)
    {
        inAnimation = true;
        float endingTime = Time.time + _lerpTotalTime;
        Color nowColor = GetComponent<SpriteRenderer>().color;

        //avoid blink
        if(nowColor != _firstColor || nowColor == _finalColor)
        {
            Color temp = _firstColor;
            _firstColor = _finalColor;
            _finalColor = temp;
        }
        m_audioPlayer.clip = waveOST;
        m_audioPlayer.Play();
        while (Time.time < endingTime)
        {
            nowColor = Color.Lerp(_finalColor, _firstColor, (endingTime - Time.time) / _lerpTotalTime);
            GetComponent<SpriteRenderer>().color = nowColor;
            yield return new WaitForEndOfFrame();
        }
        inAnimation = false;
        GetComponent<SpriteRenderer>().color = _finalColor;
        motionStateNow = ParticleMotionState.Idle;
        nextTimeToEatOrBeEaten = eatingInterval + Time.time;
        foreach (ParticleMouse mouse in m_hunter.mice) mouse.isBeEaten = false;
        //GetComponent<SpriteRenderer>().material.SetColor("_TintColor", _firstColor);

    }

    #endregion
        
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum GameState{
    Start,
    Update,
    end
}
public class GameStageManager : MonoBehaviour
{
    public GameState m_GameState; 
    [Header("Time setting")]
    [Tooltip("it means update time length")]
    public float stageTimeLength = 60f;
    float timer;
    // Start is called before the first frame update
    void Start()
    {
        
    }
    IEnumerator GameStageControl()
    {
        yield return new WaitForEndOfFrame();
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[ExecuteInEditMode]
public class ScreenSpaceBoundary : BoundaryBase
{
    [Header("塞入相機物件")]
    public GameObject cameraObject ;

    [Header("到相機的距離")]
    [Range(0f,100f)]public float distanceToCamera = 10;

    public Color debugColor = Color.white;

    [HideInInspector]public float minX, maxX, minY, maxY = 0;
    [HideInInspector]public Vector3 worldCenter;

	

    private void Update()
    {
        SetDistanceToCamera();
        GetBoundaryConrner();
        BoundaryVisualizer();
    }
    void SetDistanceToCamera()
    {
        //check camera gameObject
        if(cameraObject == null)
            cameraObject = GameObject.FindWithTag("MainCamera");
        
        this.transform.position = new Vector3(0, cameraObject.transform.position.y, distanceToCamera);
        worldCenter = this.transform.position;
    }

    void GetBoundaryConrner()
    {
        
        Vector3 bottomCorner = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, distanceToCamera));
        Vector3 TopCorner = Camera.main.ViewportToWorldPoint(new Vector3(1, 1, distanceToCamera));

        maxX = TopCorner.x;
        minX = bottomCorner.x;
        maxY = TopCorner.y;
        minY = bottomCorner.y;

    }
    void BoundaryVisualizer()
    {

        Vector3 TopCornerRight = new Vector3(maxX,maxY,transform.position.z);
        Vector3 TopCornerLeft = new Vector3(minX, maxY, transform.position.z);
        Vector3 BottomCornerRight = new Vector3(maxX, minY, transform.position.z);
        Vector3 BottomCornerLeft = new Vector3(minX, minY, transform.position.z);


        Debug.DrawRay(TopCornerRight, TopCornerLeft - TopCornerRight , debugColor);
        Debug.DrawRay(TopCornerRight, BottomCornerRight - TopCornerRight , debugColor);
        Debug.DrawRay(BottomCornerLeft, TopCornerLeft - BottomCornerLeft  , debugColor);
        Debug.DrawRay(BottomCornerLeft, BottomCornerRight - BottomCornerLeft , debugColor);

    }

    public override bool isPointInside(Transform _point)
    {
        bool checkPositionX = (_point.position.x < maxX && _point.position.x > minX);
        bool checkPositionY = (_point.position.y < maxY && _point.position.y > minY);
        bool pointChecker = checkPositionX && checkPositionY;
        return pointChecker;
    }
}

<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerManager : MonoBehaviour, KinectGestures.GestureListenerInterface
{
    KinectManager manager;
    private static ModelGestureListener instance = null;

    public static ModelGestureListener Instance
	{
		get
		{
			return instance;
		}
	}
    public List<GameObject> PlayerList;
    public List<KinectSkeletonTracker> PlayerParticleEffect;
    public int usersSaved = 0;
    public GameObject flashLight ;
    void Update()
    {
        if(manager == null)manager = KinectManager.Instance;
        // switch( manager.GetUsersCount())
        // {
        //     case 0:
        //         for(int i = 1;i<PlayerList.Count;i++)
        //         {
        //             PlayerList[i].SetActive(false);
        //             //PlayerParticleEffect[i].enabled = false;
        //         }
        //         break;
        //     case 1:
        //         for(int i = 1;i<PlayerList.Count;i++)
        //         {
        //             PlayerList[i].SetActive(false);
        //             //PlayerParticleEffect[i].enabled = false;
        //         }
        //         break;
        //     case 2:
        //         break;
        //     case 3:
        //         break;
        // }
        // if(manager && manager.IsInitialized())
        // {
        //     int usersNow = manager.GetUsersCount();

        //     if(usersNow > usersSaved)
        //     {
        //         OndetectUser();
        //     }
        //     if(usersNow < usersSaved)
        //     {
        //         OnLostUser();
        //     }

        //     usersSaved = usersNow;
        // }
        if(manager.GetUsersCount() == 0 && flashLight.activeSelf != true)
        {
            flashLight.SetActive(true);
        }
        else if(manager.GetUsersCount() != 0 && flashLight.activeSelf != false)
        {
            flashLight.SetActive(false);
        }
    }
    void OndetectUser(){
        
    }
    void OnLostUser(){

    }
    
    public void UserDetected(long userId, int userIndex){
        Debug.Log("User detect");
        PlayerParticleEffect[userIndex].enabled = (true);
        PlayerParticleEffect[userIndex].PlayerIndex = userIndex;
        PlayerParticleEffect[userIndex].Idle = false;
        StartCoroutine(PlayerParticleEffect[userIndex].Timer());
        
        PlayerList[userIndex].SetActive(true);
        PlayerList[userIndex].GetComponent<PlayerData>().userID = userId;
        PlayerList[userIndex].GetComponent<PlayerData>().userIndex = userIndex;
        PlayerList[userIndex].GetComponent<PlayerData>().ResetPalayerParticlePosition();

        manager.DetectGesture(userId, KinectGestures.Gestures.Jump);
		manager.DetectGesture(userId,KinectGestures.Gestures.Tpose);
        manager.DetectGesture(userId,KinectGestures.Gestures.SwipeRight);
        manager.DetectGesture(userId,KinectGestures.Gestures.SwipeLeft);

    }
    public void UserLost(long userId, int userIndex){
        Debug.Log("user lost");
        foreach(GameObject user in PlayerList)
        {
            long _userId = user.GetComponent<PlayerData>().userID;
            int _userIndex = user.GetComponent<PlayerData>().userIndex;

            if(_userId == userId)
            {
                //Debug.Log(userIndex);
                if((manager.GetUsersCount() == 1 ))
                {
                    user.GetComponent<PlayerData>().userID = -1;
                    PlayerParticleEffect[userIndex].enabled = false;
                    PlayerList.Insert(0,user);
                    return;
                }
                else if((manager.GetUsersCount() > 1 ))
                {
                    PlayerList.Remove(user);
                    PlayerList.Add(user);

                    user.GetComponent<PlayerData>().userID = -1;
                    user.GetComponent<PlayerData>().userIndex = PlayerList.Count - 1;
                    PlayerParticleEffect[userIndex].enabled = false;
                    user.SetActive(false);

                    break;
                }
                
            }
        }
    }
    public void PlayerGestureDetect(int userIndex, KinectGestures.Gestures gesture){}
    public void GestureInProgress(long userId, int userIndex, KinectGestures.Gestures gesture,
                                  float progress, KinectInterop.JointType joint, Vector3 screenPos){

           if(progress >0.5f &&(gesture == KinectGestures.Gestures.Tpose || 
              gesture == KinectGestures.Gestures.Jump
           ||gesture == KinectGestures.Gestures.SwipeRight ||
           gesture == KinectGestures.Gestures.SwipeLeft ||
           gesture == KinectGestures.Gestures.RaiseRightHand
         ))
		{
            
            KinectSkeletonTracker vfx = PlayerParticleEffect[userIndex];
            Color m_color = vfx.m_Color;
            Color _color = new Color(m_color.r, m_color.g, m_color.b, 1);
            vfx.changeColor(_color);
            vfx.Idle = false;
            StartCoroutine(vfx.Timer());
             PlayerList[userIndex].GetComponent<PlayerData>().ResetPalayerParticlePosition();
            Debug.Log("Get complete gesture id : " + userId);
            return;
        }
                                  }
    public bool GestureCompleted(long userId, int userIndex, KinectGestures.Gestures gesture,
                                  KinectInterop.JointType joint, Vector3 screenPos)
    {
        
       if((gesture == KinectGestures.Gestures.Tpose || 
              gesture == KinectGestures.Gestures.Jump
           ||gesture == KinectGestures.Gestures.SwipeRight 
         ))
		{
            
            KinectSkeletonTracker vfx = PlayerParticleEffect[userIndex];
            Color m_color = vfx.m_Color;
            Color _color = new Color(m_color.r, m_color.g, m_color.b, 1);
            vfx.changeColor(_color);
            vfx.Idle = false;
            StartCoroutine(vfx.Timer());
            Debug.Log("Get complete gesture id : " + userId);   
            PlayerList[userIndex].GetComponent<PlayerData>().ResetPalayerParticlePosition();
            return true;
        }
        else if(gesture == KinectGestures.Gestures.SwipeLeft)
        {
            
        }
        else if( gesture == KinectGestures.Gestures.RaiseRightHand)
        {

        }
        return false;
        
    }
    public bool GestureCancelled(long userId, int userIndex, KinectGestures.Gestures gesture,
                                  KinectInterop.JointType joint)
    {
        return true;
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseControllMove : MonoBehaviour
{
    public GameObject controllObject;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        MouseControlMove();
    }
    public void MouseControlMove()
    {
        //Vector3 point = new Vector3();
        Event currentEvent = Event.current;
        //Vector2 mousePos = new Vector2();
        ScreenSpaceBoundary m_Boundary = GetComponent<ScreenSpaceBoundary>();
        Vector3 mousePointToPlayerLayer = Camera.main.ScreenToWorldPoint(
            new Vector3(Input.mousePosition.x,
                        Input.mousePosition.y,
                        m_Boundary.distanceToCamera));
        controllObject.transform.position = mousePointToPlayerLayer;
        //m_rigidbody.MovePosition(mousePointToPlayerLayer);
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class BoundaryBase : MonoBehaviour {
    
    public void CollisionBoundary(Transform particleTransform,ref BoundaryEvent @event){

        if(isPointInside(particleTransform))
        {
            @event.StayBoundary();
        }
        else
        {
            @event.ExitBoundary();
        }
    }

    public virtual bool isPointInside(Transform _point){
        return false;
    }

}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml.Schema;
using System.Runtime.CompilerServices;
public enum mainParticleStage
{
    rebornDelay,
    start,
    update,
    beEaten,
    end
}

 
public class MainParticleLifeCycle : ParticleBase
{
    [HideInInspector] public int index;

    [Range(0, 10)] public float rebornDelayTimeRange = 5f;
    float rebornDelayTime = 5f;

    [Range(0, 20)] public float localMoveSpeed = 2;

    //private Color m_color;

    public Color fisrtColor;
    public Color finalColor;

    ScreenSpaceBoundary m_Boundary;
    Rigidbody m_rigidbody;
    Renderer m_renderer;

    #region time comtrol
    public float lerpTime = 1f;
    #endregion
    public mainParticleStage m_stage = mainParticleStage.rebornDelay;
    //[HideInInspector]public MainParticleMove m_move = new MainParticleMove();
    [HideInInspector]public MainParticleMove m_move;
    public BoundaryEvent m_event;
    //ParticleSystem m_particleEffect;
    private void Start()
    {
        Initialized();
        RebornPositionSetting();
        StartCoroutine(StageControl());
    }
    private void Update()
    {
        if (GetComponent<Rigidbody>().velocity.magnitude > maxMoveSpeed)
        {
            GetComponent<Rigidbody>().velocity = GetComponent<Rigidbody>().velocity.normalized * maxMoveSpeed;
        }
    }

    private void FixedUpdate()
    {
        OutputValue();
    }
    public new void BeEaten()
    {
        //Debug.Log("number" + index + "be eaten");
        //m_particleEffect.Play();
        m_stage = mainParticleStage.beEaten;
        GetComponent<MeshRenderer>().enabled = false;
    }
    public void Run()
    {
        
        direction += new Vector3(
            Mathf.Sin(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI) * Mathf.PerlinNoise(Time.time + index, index)),
            Mathf.Cos(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI) * Mathf.PerlinNoise(Time.time + index, index)), 0);
        
        direction = direction.normalized;
        direction.Set(direction.x, direction.y, 0);
        //Debug.Log("Run");
        velocity = Mathf.PerlinNoise( Time.time + index, index ) * direction * localMoveSpeed * Time.deltaTime;

    }

    void OutputValue()
    {
        if(m_move.index % 2 != 0)
        {
            m_rigidbody.AddForce(m_move.velocity * 150);
        }   
           
        else{
            m_rigidbody.MovePosition(transform.position + m_move.velocity);
            //Debug.Log("Move position"+m_move.index);
        }
            
        //m_rigidbody.AddForce(velocity);
        m_rigidbody.angularVelocity = m_move.angVelocity;
        //Debug.Log("m_move" + m_move.velocity);

    }
    public void Initialized()
    {
        rebornDelayTime = Random.Range(rebornDelayTimeRange*0.3f, rebornDelayTimeRange);
        m_Boundary = transform.parent.GetComponent<ScreenSpaceBoundary>();
        m_rigidbody = GetComponent<Rigidbody>();
        m_renderer = GetComponent<Renderer>();
        m_event = new MainParticleBoundaryEvent(GetComponent<MainParticleLifeCycle>());
        //m_move = new MainParticleMove();
        m_move = gameObject.AddComponent<MainParticleMove>();

        //m_color = fisrtColor ;
        m_renderer.material.SetColor("_TintColor", new Color(fisrtColor.a,fisrtColor.g,fisrtColor.b,0));
    }
    public void AttributeInitialze()
    {

        RebornPositionSetting();
        m_move.velocity = Vector3.zero;
        m_move.angVelocity = Vector3.zero;
        m_move.index = Random.Range(12345, 823231);
        m_move.localMoveSpeed = localMoveSpeed;
        rebornDelayTime = Random.Range(0, rebornDelayTimeRange);

    }
    void RebornPositionSetting()
    {
        transform.localPosition = new Vector3(
            Random.Range(m_Boundary.minX, m_Boundary.maxX),
            Random.Range(m_Boundary.minY, m_Boundary.maxY), 0);
    }
    
    public void ExitBoundary()
    {
        //AttributeInitialze();
        //m_renderer.material.SetColor("_TintColor", new Color(fisrtColor.r, fisrtColor.g, fisrtColor.b, 0));
        m_stage = mainParticleStage.end;
    }
    IEnumerator StageControl()
    {
        while (true)
        {
            
            float timer = 0;
            Color nowColor;
            Color lerpColor = new Color(fisrtColor.r, fisrtColor.g, fisrtColor.b, 0);
            Color m_color = m_renderer.material.GetColor("_TintColor");
            switch(m_stage)
            {
                case mainParticleStage.rebornDelay:
                    //velocity = Vector3.zero;
                    angVelocity = Vector3.zero;
                    //GetComponent<Rigidbody>().
                    GetComponent<MeshRenderer>().enabled = true;
                    GetComponent<Collider>().enabled = false;

                    m_renderer.material.SetColor("_TintColor", lerpColor);
                    while (timer / rebornDelayTime < 1)
                    {
                        timer += Time.deltaTime;
                        //Debug.Log("Timer"+timer);
                        if(m_stage != mainParticleStage.rebornDelay)
                        {
                            break;
                        }
                        yield return new WaitForEndOfFrame();
                    }
                    m_stage = mainParticleStage.start;
                    break;

                case mainParticleStage.start:
                    AttributeInitialze();
                    GetComponent<Collider>().enabled = true;
                    GetComponent<Rigidbody>().isKinematic = false;
                    //m_rigidbody.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY;
                    while (timer / lerpTime < 1)
                    {
                        timer += Time.deltaTime;
                        nowColor = Color.Lerp(m_color, fisrtColor, timer / lerpTime);
                        m_renderer.material.SetColor("_TintColor", nowColor);
                        m_Boundary.CollisionBoundary(transform, ref m_event);
                        //CollisionBoundary();
                        //m_Boundary.CollisionBoundary(transform,ref m_event);
                        // if (m_stage != mainParticleStage.start)
                        // {
                        //     break;
                        // }

                        yield return new WaitForEndOfFrame();
                    }
                    m_stage = mainParticleStage.update;
                    break;

                case mainParticleStage.update:
                    while (timer / lifeTime < 1)
                    {
                        timer += Time.deltaTime;
                        m_Boundary.CollisionBoundary(transform, ref m_event);
                        if (m_stage != mainParticleStage.update)
                        {
                            break;
                        }
                        yield return new WaitForEndOfFrame();
                    }
                    m_stage = mainParticleStage.end;
                    break;
                case mainParticleStage.beEaten:
                    m_stage = mainParticleStage.rebornDelay;
                    break;
                case mainParticleStage.end:
                    
                    while (timer / lerpTime < 1)
                    {
                        timer += Time.deltaTime;
                        nowColor = Color.Lerp(m_color, lerpColor, timer / lerpTime);
                        m_renderer.material.SetColor("_TintColor", nowColor);
                        //CollisionBoundary();
                        m_Boundary.CollisionBoundary(transform, ref m_event);
                        if(m_Boundary.isPointInside(transform))
                        {
                            m_move.Run();
                        }
                        if (m_stage != mainParticleStage.end)
                        {
                            
                            break;

                        }
                        yield return new WaitForEndOfFrame();
                    }
                    m_stage = mainParticleStage.rebornDelay;
                    break;

            }

        }


    }



}

public class MainParticleBoundaryEvent : BoundaryEvent
{
    public MainParticleLifeCycle _particle;
    public MainParticleBoundaryEvent(MainParticleLifeCycle particle)
    {
        _particle = particle;
        //Debug.Log(_particle);
    }
    public override void StayBoundary()
    {
        _particle.m_move.Run();
        //Debug.Log("Stay boundary");

    }
    public override void ExitBoundary()
    {
        _particle.m_stage = mainParticleStage.end;
        _particle.velocity = Vector3.zero;

        //Debug.Log("Exit boundary");
    }
}

public class MainParticleMove : ParticleBase
{
    public int index;
    public float localMoveSpeed = 100;

    public void Run()
    {
        direction += new Vector3(
            Mathf.Sin(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI) * Mathf.PerlinNoise(Time.time + index, index)),
            Mathf.Cos(Mathf.Rad2Deg * Random.Range(-Mathf.PI, Mathf.PI) * Mathf.PerlinNoise(Time.time + index, index)), 0);

        direction = direction.normalized;
        direction.Set(direction.x, direction.y, 0);

        velocity = Mathf.PerlinNoise(Time.time + index, index) * direction * localMoveSpeed * Time.deltaTime;

    }
}<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
//using Boo.Lang;

[System.Serializable]
public class PlayerHunter : Hunter
{
}
public enum ForceType
{
    attractive,
    explosition
}
public class PlayerParticleBehaviour : ParticleBehaiour{
    private static PlayerParticleBehaviour _instance;
    public PlayerParticleBehaviour instance{
        get
        {
            if (_instance == null) _instance = this;
            return _instance;
        }
    }

    int index;
    int eatNumberCounter;
    float timer;
    float timerAtIdle;
    float timerAtEnd;
    float timerAtFirst;

    /* 參考用
    public ApearenceStructure apearence;
    public PhysicMotionSetting physicMotion;
    public bool isUseRandomReborn;
    
    //public Hunter hunter;
    
    [Header("State  setting")]
    public bool isHunter = false;
    public ParticleLifeState stateNow;
    public ParticleMotionState motionStateNow;
    
    [Header("Growing Up attribute")]
    public bool canItGrowUp = false;
    public int HowMuchNumberForEatingToGrowUp;
    [HideInInspector] public bool beEaten = false;

    //int index;
    [HideInInspector]public ScreenSpaceBoundary m_Boundary;
    [HideInInspector]public Rigidbody m_rigidbody;
    [HideInInspector]public SphereCollider m_collider;
    */
    public PlayerHunter m_hunter;

    [Header("Force effect Radius")]
    [Range(0.5f, 10f)] public float attractiveRadius = 7.5f;
    [Range(0.5f, 10f)] public float collisionRadius = 2f;
    [Range(0.5f, 10f)] public float explosionRadius = 7.5f;

    [Header("Force")]
    public float RepulsiveForce = 100f;
    public float AttrativeForce = 10f;

    [Header("Time Setting")]
    public float lifeTime = 20f;
    public float explosionTime = 0.3f;
    public float attractiveTime = 10f;

    [Header("Move motion setting")]
    public Vector2 stepRandomMoveDistance = new Vector2(1, 2);
    public Vector2 maxMoveAngle = new Vector2(60, 120);

    [Header("Interactive target")]
    [Tooltip("the particle who will affected by player particle")]
    public LayerManager[] InteractTarget;
    public LayerManager[] HuntingTarget;
    public bool isUseMouseToControl = true;
    public int MaxCorner = 18;
    public float stage1Scale = 2.8f;
    public float stage2Scale = 5;

    public float stage1ColliderTrigger = 5;
    public float stage2ColliderTrigger = 1;
    

    [Header("Audio Sound Effect")]
    public AudioClip EatingSnakeOST;
    public AudioClip EatingLittleParticleOST;
    public AudioClip EatingEmitterParticleOST;
    public AudioClip EatingWaveOST;

    public AudioSource m_audioPlayer;

    private GameObject stage2;

	// Use this for initialization
	void Start () {
		stage2 = GameObject.Find("Stage2");
         GetComponent<SphereCollider>().radius = stage1ColliderTrigger;
         HowMuchNumberForEatingToGrowUp = 15;
	}
	
	// Update is called once per frame
	void Update () {
        if(stage2 == null)
        { 
            stage2 = GameObject.Find("Stage2");
            return;
        }
		if(stage2.activeSelf && transform.localScale.x != stage2Scale)
        {
            transform.localScale = Vector3.one * stage2Scale;
            
        }
        else if(!stage2.activeSelf && transform.localScale.x != stage1Scale)
        {
            transform.localScale = Vector3.one * stage1Scale;
           
        }

        if(!stage2.activeSelf && GetComponent<SphereCollider>().radius != stage1ColliderTrigger)
        {
             GetComponent<SphereCollider>().radius = stage1ColliderTrigger;
        }
        else if(stage2.activeSelf && GetComponent<SphereCollider>().radius != stage2ColliderTrigger)
        {
            GetComponent<SphereCollider>().radius = stage2ColliderTrigger;
        }
	}

    private void FixedUpdate()
    {
        LifeCycleStateSelector();
    }
    public void Inititalize()
    {
        m_Boundary = transform.parent.GetComponent<ScreenSpaceBoundary>();
        m_collider = this.GetComponent<SphereCollider>();
        m_rigidbody = this.GetComponent<Rigidbody>();

        m_hunter.HuntingTargets = HuntingTarget;
        m_hunter.mouse.HuntingTargets = HuntingTarget;
        timer = 0;
        stateNow = ParticleLifeState.Update;
    }

    public override void LifeCycleStateSelector()
    {
        timer += Time.deltaTime;
        switch (stateNow)
        {
            case ParticleLifeState.Start:
                Inititalize();
                if (isUseMouseToControl) MouseControlMove();
                else { IdleMove(); }
                stateNow = ParticleLifeState.Update;
                break;
            case ParticleLifeState.Update:
                UpdateCycleStateSelector();
                break;
            case ParticleLifeState.End:
                stateNow = ParticleLifeState.Start;
                break;
        }
    }

    public override void UpdateCycleStateSelector()
    {
        EventManager();
        switch (motionStateNow)
        {
            case ParticleMotionState.FirstUpdate:
                FirstUpdateEventHandler();
                break;
            case ParticleMotionState.Idle:
                IdldeEventHandler();
                if (isUseMouseToControl) MouseControlMove();
                break;
            case ParticleMotionState.Hunting:
                break;
            case ParticleMotionState.Eating:
                m_hunter.mouse.isEating = false;
                break;
            case ParticleMotionState.interactive:
                if (isUseMouseToControl) MouseControlMove();
                break;
            case ParticleMotionState.BeEaten:
                break;
            case ParticleMotionState.EndOfUpdate:
                EndOfUpdateEventHandler();
                break;
        }
    }

    public bool interaciveStateTrigger = false; 
    void EventManager()
    {
        
        if(timerAtFirst / explosionTime < 1)
        {
            motionStateNow = ParticleMotionState.FirstUpdate;
        }
        else if(timerAtIdle/lifeTime < 1)
        {
            if(interaciveStateTrigger)
            {
                motionStateNow = ParticleMotionState.interactive;
            }
            else if (m_hunter.getIsEating)
            {
                motionStateNow = ParticleMotionState.Eating;
            }
            else if(m_hunter.ifHasTarget)
            {
                motionStateNow = ParticleMotionState.Hunting;
            }
            else if(beEaten)
            {
                motionStateNow = ParticleMotionState.BeEaten;
            }
            else
            {
                motionStateNow = ParticleMotionState.Idle;
            }
        }
        else
        {
            motionStateNow = ParticleMotionState.EndOfUpdate;
        }
    }
    void FirstUpdateEventHandler()
    {
        timerAtFirst += Time.deltaTime;
    }
    void IdldeEventHandler()
    {
        timerAtIdle += Time.deltaTime;
    }
    void EndOfUpdateEventHandler()
    {
        timerAtEnd += Time.deltaTime;
        if (timerAtEnd / explosionTime > 1)
        {
            stateNow = ParticleLifeState.End;
            timerAtEnd = 0;
            timerAtIdle = 0;
            timerAtFirst = 0;
        }
            
    }
    private void OnTriggerStay(Collider other)
    {
        InteractiveStateSelector(other.gameObject);
    }
    void OnTriggerEnter(Collider other)
    {
        EatingEvent(other.gameObject);
    }
    public void InteractiveStateSelector(GameObject collisionObject)
    {
        if (!checkIfInTargetList(InteractTarget, collisionObject))
            return;


        if(stateNow == ParticleLifeState.Update)
        {
            switch (motionStateNow)
            {
                case ParticleMotionState.FirstUpdate:
                    ForceSelector(collisionObject,ForceType.explosition);
                    break;
                case ParticleMotionState.Idle:
                    ForceSelector(collisionObject, ForceType.attractive);
                    break;

                case ParticleMotionState.Hunting:
                    break;

                case ParticleMotionState.Eating:
                    Grow();
                    break;

                case ParticleMotionState.interactive:
                    if(collisionObject.GetComponent<Rigidbody>() != null)
                        ForceSelector(collisionObject, ForceType.explosition);
                    if(m_hunter.getIsEating)Grow();
                    break;

                case ParticleMotionState.BeEaten:
                    break;

                case ParticleMotionState.EndOfUpdate:
                    ForceSelector(collisionObject, ForceType.explosition);
                    break;
            }  
        }

    }
     void EatingEvent(GameObject beEatenGameObject)
    {
        switch (beEatenGameObject.layer)
        {
            //object
            case 9:

                break;
            //snake
            case 13:
                if(beEatenGameObject.GetComponent<SnakeHead>() == null)return;
                m_audioPlayer.clip = EatingSnakeOST;
                m_audioPlayer.Play();
                break;
            //emitter partcle
            case 14:
                m_audioPlayer.clip = EatingEmitterParticleOST;
                m_audioPlayer.Play();
                break;

            //wave
            case 16:
                m_audioPlayer.clip = EatingWaveOST;
                m_audioPlayer.Play();
                break;
        }
        

    }
    /// <summary>
    /// direct add force to input game object
    /// </summary>
    /// <param name="_collisionObject">.</param>
    /// <param name="type">Type.</param>
    public void ForceSelector(GameObject _collisionObject,ForceType type)
    {
        Vector3 Force = Vector3.zero;
        Rigidbody pRigidbody = _collisionObject.GetComponent<Rigidbody>();
        float distance = Vector3.Distance(transform.position, _collisionObject.transform.position);
        switch(type)
        {
            case ForceType.attractive:
                Force = (this.transform.position - _collisionObject.transform.position).normalized *
                    Mathf.Lerp(AttrativeForce, AttrativeForce / 2, distance / attractiveRadius);
                break;

            case ForceType.explosition:
                Force = (_collisionObject.transform.position - this.transform.position).normalized *
                    Mathf.Lerp(0, RepulsiveForce, distance / explosionRadius);
                break;
        }

        pRigidbody.AddForce(Force);
    }
    int direction = 1;
    void IdleMove()
    {
        direction = Random.Range(0, 100) > 50 ? 1 : -1;
        float mediumAngle = direction == 1 ? (maxMoveAngle.x + maxMoveAngle.y) * Mathf.Deg2Rad * 0.5f : (maxMoveAngle.x + maxMoveAngle.y) * Mathf.Deg2Rad * 0.5f + 180f * Mathf.Deg2Rad;
        float moveAngle = Random.Range(maxMoveAngle.x * Mathf.Deg2Rad - mediumAngle, maxMoveAngle.y * Mathf.Deg2Rad - mediumAngle);
        float moveDistance = Random.Range(stepRandomMoveDistance.x, stepRandomMoveDistance.y);
        float newX = (float)(moveDistance * Mathf.Cos(moveAngle));
        float newY = (float)(moveDistance * Mathf.Sin(moveAngle));
        m_rigidbody.MovePosition(transform.position + new Vector3(newX, newY, 0).normalized * Time.deltaTime * physicMotion.speed);
    }
    public void MouseControlMove()
    {
        //Vector3 point = new Vector3();
        Event currentEvent = Event.current;
        //Vector2 mousePos = new Vector2();

        Vector3 mousePointToPlayerLayer = Camera.main.ScreenToWorldPoint(
            new Vector3(Input.mousePosition.x,
                        Input.mousePosition.y,
                        m_Boundary.distanceToCamera));
        m_rigidbody.MovePosition(mousePointToPlayerLayer);
    }

    public bool checkIfInTargetList(LayerManager[] list, GameObject checkThisObject)
    {
        if(list.Length == 0)
        {
            Debug.Log("the list dont have any target");
            return false;
        }

        for (int i = 0; i < list.Length;i++)
        {
            if(checkThisObject.layer == (int)list[i])
            {
                return true;
            }
        }
        return false;
    }

    private void OnMouseDown()
    {
        m_hunter.mouse.MouseCollider.isTrigger = true;
        interaciveStateTrigger = true;
    }
    private void OnMouseUp()
    {
        m_hunter.mouse.MouseCollider.isTrigger = false;
        interaciveStateTrigger = false;
    }
    float timerToEat;
    void Grow()
    {
        eatNumberCounter += 1;
        m_hunter.mouse.Reset();
        if (eatNumberCounter % HowMuchNumberForEatingToGrowUp == 0 && canItGrowUp)
        {
            Star m_shape = GetComponent<Star>();
            if (m_shape.frequency < MaxCorner &&  Time.time >  timerToEat)
            {
                timerToEat = Time.time + 6f;
                transform.localScale *=1.1f;
                m_shape.frequency++;
                m_shape.Reset();
                eatNumberCounter = 0;
            }
        }
    }

}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpinAround : MonoBehaviour {
    
	// Use this for initialization
	void Start () {
        StartCoroutine(spinAround());
	}
    public float frequency = 0.5f;
    public int direction = 1;
    public float minSpeed = 50;
    public float maxSpeed = 150;
    public bool isUsePhysicWayToRotate = false;
    IEnumerator spinAround()
    {
        while(true)
        {
            float angle = (minSpeed + (maxSpeed - minSpeed) *
                        Mathf.PerlinNoise(Time.deltaTime *
                                          Mathf.Sin(minSpeed + maxSpeed) *
                                          Mathf.Cos((maxSpeed - minSpeed)),
                                         1)) *
                Time.deltaTime * direction * Mathf.Sin((minSpeed + Time.time) * frequency);

            if(!isUsePhysicWayToRotate)
                transform.Rotate(0,0,angle);
            else
                GetComponent<Rigidbody>().angularVelocity += new Vector3(0, 0, angle);
            //Debug.Log(angle);
            yield return new WaitForEndOfFrame();
        }

    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class StageTransferTool : MonoBehaviour
{

    [Header("Game Object setting")]
    public Camera MainCamera;
    public PostProcessVolume postProcessing;

    public Text TimerText;
    public GameObject Stage1;
    public GameObject Stage2;

    public bool isUseKinect;
    public GameObject noKinectPLayer;
    public GameObject kinectPlayer;
    private float timer;

    [Header("Time setting")]
    public float fadeInTime = 0.3f;
    public float fadeOutTime = 1f;
    public float Stage1TimeLength = 60;
    public float Stage2TimeLength = 60;
    public float EndingStageTimeLength = 30;
    public gameStage gameStageNow = gameStage.Stage1;

    [Header("[Start]Vignette Animation setting (Blink)")]
    public Color vignetteColor = new Color(0,19,67,255);
    public Color vignetteColor2 = new Color(0,19,67,255);
    public AnimationCurve vignetteIntensity = AnimationCurve.EaseInOut(0,0.5f,1,0.3f);
    public AnimationCurve vignetteRoundness = AnimationCurve.EaseInOut(0,1f,1,0.9f);

    [Header("[Start]Color grading Attribte setting (Blink)")]
    public AnimationCurve ColorGrading_ColorFilter_Intensity = AnimationCurve.EaseInOut(0,0,1,1);

    [Header("[Transfer]Vignette Animation setting")]
    public float cameraMotionTimeLength = 2f;
    public AnimationCurve cameraMotionTime1 = AnimationCurve.EaseInOut(0,0.5f,1,-0.1f);
    public AnimationCurve cameraMotionTime2 = AnimationCurve.EaseInOut(0,1.1f,1,0.5f);

    public GameObject EndingCanvas;
    
    public enum gameStage{
        Stage1,
        Stage2
    }
    
    // Start is called before the first frame update
    void Start()
    {
        //if(isFullScreen) Screen.fullScreen = true;
        if (!isUseKinect)
        {
            //switch to mouse
            noKinectPLayer.SetActive(true);
            kinectPlayer.SetActive(false);
            MainCamera = noKinectPLayer.GetComponent<PlayerObjectManager>().MainCamera;
            postProcessing = MainCamera.GetComponent<PostProcessVolume>();
        }
        else
        {
            //switch to kinect
            noKinectPLayer.SetActive(false);
            kinectPlayer.SetActive(true);
            MainCamera = kinectPlayer.GetComponent<PlayerObjectManager>().MainCamera;
            postProcessing = MainCamera.GetComponent<PostProcessVolume>();
        }
        ChangeBoundaryLayerCamera();
        attributeInitate();
        StartCoroutine( GameStageManager());
        
    }

    // Update is called once per frame
    void Update()
    {
        timer += Time.deltaTime;
        TimerText.text = "Time : " + (int)timer;
        if(Input.GetKeyDown(KeyCode.Space))
        {
            SceneManager.LoadSceneAsync(0);
        }
    }

    IEnumerator GameStageManager()
    {
        BlinkEffect();
        yield return new WaitForSeconds(Stage1TimeLength);
        if(gameStageNow == gameStage.Stage1)
            TransferEffect();
        yield return new WaitForSeconds(Stage2TimeLength);
        EndingCanvas.SetActive(true);
        Stage1.SetActive(false);
        Stage2.SetActive(false);
        yield return new WaitForSeconds(EndingStageTimeLength);
        
       
        SceneManager.LoadSceneAsync(0);
    }
    void attributeInitate()
    {
        if(MainCamera == null)
        {
            MainCamera = Camera.main;
        }

        if(postProcessing == null)
        {
            postProcessing = MainCamera.GetComponent<PostProcessVolume>();
        }

        timer = 0;
    }

    public void SwitchPlayerControll()
    {
        isUseKinect = !isUseKinect;
        if(!isUseKinect)
        {
            //switch to mouse
            noKinectPLayer.SetActive(true);
            kinectPlayer.SetActive(false);
            MainCamera = noKinectPLayer.GetComponent<PlayerObjectManager>().MainCamera;
            postProcessing = MainCamera.GetComponent<PostProcessVolume>();
        }
        else
        {
            //switch to kinect
            noKinectPLayer.SetActive(false);
            kinectPlayer.SetActive(true);
            MainCamera = kinectPlayer.GetComponent<PlayerObjectManager>().MainCamera;
            postProcessing = MainCamera.GetComponent<PostProcessVolume>();
        }
        ChangeBoundaryLayerCamera();
    }

    public void ChangeBoundaryLayerCamera()
    {
        switch(gameStageNow)
        {
            case gameStage.Stage1:
                foreach(ScreenSpaceBoundary layerBoundary in Stage1.GetComponentsInChildren<ScreenSpaceBoundary>())
                {
                    layerBoundary.cameraObject = MainCamera.gameObject;
                }
                break;
            case gameStage.Stage2:
             foreach(ScreenSpaceBoundary layerBoundary in Stage2.GetComponentsInChildren<ScreenSpaceBoundary>())
                {
                    layerBoundary.cameraObject = MainCamera.gameObject;
                }
                break;

        }
    }
    public void BlinkEffect()
    {
        gameStageNow = gameStage.Stage1;
        StartCoroutine(Blink());
        
    }
    public void TransferEffect()
    {
        gameStageNow = gameStage.Stage2;
        StartCoroutine(camerMotion());
    }
    public void TimeMachine()
    {
        Time.timeScale = 10;
    }

    void stageObjectManager()
    {
        switch(gameStageNow)
        {
            case gameStage.Stage1:
                Stage1.SetActive(true);
                Stage2.SetActive(false);
                break;

            case gameStage.Stage2:
                Stage1.SetActive(false);
                Stage2.SetActive(true);
                break;
        }
    }
    IEnumerator Blink()
    {
        Vignette vignette = null;
        ColorGrading colorGrading = null;
        postProcessing.profile.TryGetSettings(out vignette);
        postProcessing.profile.TryGetSettings(out colorGrading);
        vignette.color.value = vignetteColor;
        stageObjectManager();
        for (float i = 0; i < fadeInTime; i+=Time.deltaTime)
        {
            vignette.intensity.value = vignetteIntensity.Evaluate(i/fadeInTime);
            vignette.roundness.value = vignetteRoundness.Evaluate(i/fadeInTime);
            
            colorGrading.colorFilter.value = new Color(
                ColorGrading_ColorFilter_Intensity.Evaluate(i/fadeInTime),
                ColorGrading_ColorFilter_Intensity.Evaluate(i/fadeInTime),
                ColorGrading_ColorFilter_Intensity.Evaluate(i/fadeInTime),0);
            yield return new WaitForEndOfFrame();
        }

    }


    
    IEnumerator camerMotion()
    {
        Vignette vignette = null;
        postProcessing.profile.TryGetSettings(out vignette);
        fadeInTime = 0.15f;
        // for (float i = 0; i < fadeInTime; i+=Time.deltaTime)
        // {
        //     vignette.intensity.value = vignetteIntensity.Evaluate(1 - i/fadeInTime);
        //     vignette.roundness.value = vignetteRoundness.Evaluate(1- i/fadeInTime);
        //     yield return new WaitForEndOfFrame();
        // }
        // vignette.rounded.value = true;
         vignette.color.value = vignetteColor2;
        for (float i = 0; i <cameraMotionTimeLength; i+=Time.deltaTime)
        {
            float x =  cameraMotionTime1.Evaluate(i/cameraMotionTimeLength);
            vignette.center.value =new Vector2(x,vignette.center.value.y);
            yield return new WaitForEndOfFrame();
        }

        stageObjectManager();
        for (float i = 0; i < cameraMotionTimeLength; i+=Time.deltaTime)
        {
            float x =  cameraMotionTime2.Evaluate(i/cameraMotionTimeLength);
            vignette.center.value =new Vector2(x,vignette.center.value.y);
            yield return new WaitForEndOfFrame();
        }
        // vignette.rounded.value = false;
        // for (float i = 0; i < fadeInTime; i+=Time.deltaTime)
        // {
        //     vignette.intensity.value = vignetteIntensity.Evaluate(i/fadeInTime);
        //     vignette.roundness.value = vignetteRoundness.Evaluate(i/fadeInTime);
        //     yield return new WaitForEndOfFrame();
        // }
    }

}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FlashTool : MonoBehaviour
{
    public float flashInterval = 0.5f;
    Image m_img;
    
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(Flash());
    }
    
    IEnumerator Flash()
    {
        Image m_img = GetComponent<Image>();
        Color m_color = new Color( m_img.color.r,m_img.color.g,m_img.color.b,m_img.color.a);
        Color m_Color_transparent = new Color(m_color.r,m_color.g,m_color.b,0);
        while(true)
        {
            //alpha now to 0
            for(float i = 0;i<flashInterval;i+=Time.deltaTime)
            {
                m_img.color = Color.Lerp(m_color,m_Color_transparent,i/flashInterval);
                yield return new WaitForEndOfFrame();
            }
            //alpha 0 to now
            for(float i = 0;i<flashInterval;i+=Time.deltaTime)
            {
                m_img.color = Color.Lerp(m_Color_transparent,m_color,i/flashInterval);
                yield return new WaitForEndOfFrame();
            }
        }
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;

[System.Serializable]
public struct ApearenceStructure
{
    public Gradient randomRebbornColor;
}
[System.Serializable]
public struct PhysicMotionSetting
{
    public float speed;
    public float maxMoveSpeed;
}
public enum ParticleLifeState
{
    RebornDelay,
    Start,
    Update,
    End
}
public enum ParticleMotionState
{
    Idle,
    Hunting,
    Eating,
    BeEaten,
    interactive,
    grow,
    FirstUpdate,
    EndOfUpdate
}
public enum LayerManager
{
    Object = 9,
    Player = 10,
    SpringJointWorm = 12,
    Snake = 13,
    EmitterParticle = 14,
    Wave = 15,
    Trash = 16


}

public class ParticleBehaiour : MonoBehaviour {

    //public Hunter hunter;
    [Header("State  setting")]
    public bool isHunter = false;
    public ParticleLifeState stateNow;
    public ParticleMotionState motionStateNow;

    [Header("Growing Up attribute")]
    public bool isUseRandomReborn;
    public bool canItGrowUp = false;
    public int HowMuchNumberForEatingToGrowUp;
    [HideInInspector] public bool beEaten = false;

    [Header("struct data setting")]
    public PhysicMotionSetting physicMotion;
    //int index;
    [HideInInspector]public ScreenSpaceBoundary m_Boundary;
    [HideInInspector]public Rigidbody m_rigidbody;
    [HideInInspector]public SphereCollider m_collider;
    public void InitializeComponent()
    {
        m_Boundary = transform.parent.GetComponent<ScreenSpaceBoundary>();
        m_rigidbody = GetComponent<Rigidbody>();
        m_collider = GetComponent<SphereCollider>();
    }

    public virtual void RandomReborn(){}
    public virtual void Initialize(){}
    public virtual void LifeCycleStateSelector(){}
    public virtual void UpdateCycleStateSelector(){}
    //public virtual void EventManagement(){}
    public virtual void GrowUp()
    {
        if(canItGrowUp)
        {
            
        }
    }

    public Vector3 RegenerateStartPosition(int direction)
    {
        float newPositionX = (direction == 1 ? m_Boundary.minX : m_Boundary.maxX) - 5f * direction;
        float newPositionY = (m_Boundary.maxY + m_Boundary.minY) / 2 + ((m_Boundary.maxY - m_Boundary.minY) / 4) * Mathf.Sin(Time.time * 0.5f);
        Vector3 newPosition = new Vector3(newPositionX, newPositionY, 0);
        return newPosition;
    }

    public void PositionInitialize()
    {
        this.transform.localPosition = new Vector3(transform.localPosition.x, transform.localPosition.y, 0);
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;


public class SnakeHead : MonoBehaviour {

    //public LayerManager HuntingTarget;
    public bool beEaten =  false;
    public LayerManager[] HuntingTargets;
    public List<GameObject> HuntingList = new List<GameObject>();
    public GameObject snakeMouse;
    public bool getIfEating
    {
        get{
            return snakeMouse.GetComponent<SnakeMouse>().isEating;
        }
    }
    [HideInInspector]public GameObject _currentTarget;

	// Use this for initialization
	void Start () {
		snakeMouse.GetComponent<SnakeMouse>().HuntingTargets = HuntingTargets;
	}
	
	// Update is called once per frame
	void Update () {
		
    
    }

    private void FixedUpdate()
    {
        checkEveryTarget();
    }
    void checkEveryTarget()
    {
        if (HuntingList.Count == 0) return;
        for (int i = 0; i < HuntingList.Count;i++)
        {
            if(HuntingList[i] == null)
            {
                HuntingList.Remove(HuntingList[i]);
                break;
            }
            switch (HuntingList[i].layer)
            {
                //object layer
                case 9:
                    if (HuntingList[i].GetComponent<MainParticleLifeCycle>().m_stage != mainParticleStage.update)
                    {
                        
                        if(_currentTarget == HuntingList[i].gameObject)
                        {
                            _currentTarget = null;
                        }
                        HuntingList.Remove(HuntingList[i].gameObject);
                    }
                    break;

                //player layer
                case 10:
                    break;

                //spring worm layer 
                case 12:
                    break;

                case 13:
                    break;

                case 14:
                    if(Vector3.Distance(transform.position,HuntingList[i].transform.position)>10)
                    {
                        if (_currentTarget == HuntingList[i].gameObject)
                        {
                            _currentTarget = null;
                        }
                        HuntingList.Remove(HuntingList[i].gameObject);
                    }
                    else if(HuntingList[i].GetComponent<ParticleMouse>().isBeEaten)
                    {
                        HuntingList.Remove(HuntingList[i].gameObject);
                    }
                    break;
            }
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        
        for (int i = 0; i < HuntingTargets.Length;i++)
        {
            //Debug.Log(other.gameObject.layer + " " + (int)HuntingTargets[i]);
            if(other.gameObject.layer == (int)HuntingTargets[i])
            {
                switch(other.gameObject.layer)
                {
                    //object layer
                    case 9:
                        if (other.gameObject.GetComponent<MainParticleLifeCycle>() == false) return;
                        if(other.gameObject.GetComponent<MainParticleLifeCycle>().m_stage == mainParticleStage.update)
                        {
                            HuntingList.Add(other.gameObject);
                        }
                        break;

                    //player layer
                    case 10:
                        break;

                    //spring worm layer 
                    case 12:
                        break;

                    case 13:
                        break;

                    case 14:
                        if (other.GetComponent<ParticleMouse>() == null) return;
                        if (!other.GetComponent<ParticleMouse>().isBeEaten)
                            HuntingList.Add(other.gameObject);
                        else Debug.Log("Emitter has already be eaten");
                        break;

                    case 16:
                        HuntingList.Add(other.gameObject);
                        break;
                }

            }
        }
    }

    private void OnTriggerExit(Collider other)
    {
        //if (other.gameObject.layer == huntingTarget)
           
        for (int i = 0; i < HuntingTargets.Length; i++)
        {
            if (other.gameObject.layer == (int)HuntingTargets[i])
            {
                HuntingList.Remove(other.gameObject);
            }
        }
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class BoundaryEvent
{
    public abstract void StayBoundary();
    public abstract void ExitBoundary();
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Rendering.PostProcessing;
public class FocusDistanceControlWithPlayerLayer : MonoBehaviour {
    public ScreenSpaceBoundary playerLayerBoundary;
    public float changingFrequency = 5f;
    PostProcessVolume volume;
	// Use this for initialization
	void Start () {
        StartCoroutine(changeFocusDistance());
	}
	
	// Update is called once per frame
	void Update () {
		
	}
    IEnumerator changeFocusDistance()
    {
        while(true)
        {
            ControlFocusDistance();
            yield return new WaitForSeconds(changingFrequency);
        }
    }
    void ControlFocusDistance()
    {
        volume = gameObject.GetComponent<PostProcessVolume>();
        DepthOfField depthOfField = null;
        volume.profile.TryGetSettings(out depthOfField);
        depthOfField.focusDistance.value = ReadPlayerLayerDistance();
    }
    float ReadPlayerLayerDistance()
    {
        float distanceOfPlayerLayer = 0;
        distanceOfPlayerLayer = playerLayerBoundary.distanceToCamera;
        return distanceOfPlayerLayer;
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Security.Cryptography.X509Certificates;

[RequireComponent(typeof(SphereCollider))]
public class TrackingTargetBehaviour : MonoBehaviour
{
    [Header("Motion setting")]
    public float circleAroundRadius=5;
    public float trackingSpeed = 1;
    public float circcleAroundSpeed = 1;

    [Header("Trigger setting")]
    public float triggerRadius;
    public bool isUseVisualizer = true;
    public Color nowTargetColor = Color.white;
    public Color otherTargetColor = Color.red;

    [Header("Target list")]
    public List<GameObject> allTargets;
    public GameObject NowTarget;

    Rigidbody m_rigidbody;
    MotionState m_state = MotionState.Idle;
    enum MotionState
    {
        Idle,
        Tracking,
        CircleArdound
    }
    // Start is called before the first frame update
    void Start()
    {
        triggerRadius = GetComponent<SphereCollider>().radius;
        m_rigidbody = GetComponent<Rigidbody>();
    }

    private void FixedUpdate()
    {
        //checkEveryObject();
        Moving();
    }
    void Moving()
    {
        MovingEventSelector();
        SwitchState();
    }
    void MovingEventSelector()
    {
        if(NowTarget == null)
        {
            m_state = MotionState.Idle;
        }
        else
        {
            float distanceToTarget = Vector3.Distance(NowTarget.transform.position, transform.position);
            if(distanceToTarget > circleAroundRadius)
            {
                m_state = MotionState.Tracking;
            }
            else if(distanceToTarget <= circleAroundRadius)
            {
                m_state = MotionState.CircleArdound;
            }
        }
    }
    void SwitchState()
    {
        switch(m_state)
        {
            case MotionState.Idle:
                IdleMove();
                break;
            case MotionState.Tracking:
                TrackingMove();
                break;
            case MotionState.CircleArdound:
                CircleAroundMove();
                break;
        }
    }
    void IdleMove()
    {
        //Debug.Log("Idle Move");

    }
    void TrackingMove()
    {
        //Debug.Log("TrackingMove");
        //Vector3 moveStep = (NowTarget.transform.position - transform.position).normalized;
        //m_rigidbody.MovePosition(transform.position + moveStep * trackingSpeed * Time.deltaTime);
        LerpMove(NowTarget.transform.position, transform.position, 5f);

    }
    void CircleAroundMove()
    {
        //Debug.Log("CircleAround");
        Vector3 towardDir = Vector3.Cross(transform.position - NowTarget.transform.position, Vector3.forward).normalized;
        m_rigidbody.MovePosition(transform.position + towardDir * circcleAroundSpeed * Time.deltaTime);
    }

    void LerpMove(Vector3 forwardPosition, Vector3 currentPosition, float minCloseDistance)
    {
        float _distance = Vector3.Distance(forwardPosition, currentPosition);
        Vector3 dir = (forwardPosition - currentPosition).normalized;
        float t = Time.deltaTime * _distance / minCloseDistance * trackingSpeed;
        if (t > 0.5) t = 0.5f;
        m_rigidbody.MovePosition(
        Vector3.Slerp(currentPosition, forwardPosition, t));
    }

    void checkEveryObject()
    {
        if (allTargets.Count == 0) return;
        float mostCloseDistance = 10;
        foreach(GameObject gb in allTargets.ToArray())
        {
            
            bool active = gb.active;
            float distanceToTarget = Vector3.Distance(gb.transform.position, transform.position);
            bool ifOutOfRange = ( distanceToTarget > triggerRadius * transform.localScale.x);
            Debug.Log("Distance to target : " + distanceToTarget + " most close distance : " + mostCloseDistance);

            //if (NowTarget == null && mostCloseDistance > distanceToTarget)
            //{
            //    mostCloseDistance = distanceToTarget;
            //    NowTarget = gb;
            //}
            
            if (!active || ifOutOfRange)
            {
                if (NowTarget == gb)
                    NowTarget = null;
                allTargets.Remove(gb);

                    
            }

            Color color = gb == NowTarget ? nowTargetColor : otherTargetColor;
            if(isUseVisualizer) 
                Debug.DrawRay(transform.position, gb.transform.position - transform.position, color);  
                
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        addListObject(other.gameObject);
    }
    //use to check every object is existing
    private void OnTriggerStay(Collider other)
    {
        addListObject(other.gameObject);
    }

    private void OnTriggerExit(Collider other)
    {
        removeListObject(other.gameObject);
    }

    void addListObject(GameObject _gb)
    {
        GameObject enterGameObject = _gb;

        if (enterGameObject.tag != "TrackingTarget") return;
        if (!allTargets.Contains(enterGameObject))
        {
            allTargets.Add(enterGameObject);
            NowTarget = enterGameObject;
        }
            
    }
    void removeListObject(GameObject _gb)
    {
        GameObject enterGameObject = _gb;
        if (enterGameObject.tag != "TrackingTarget") return;

        if (allTargets.Contains(enterGameObject))
            allTargets.Remove(enterGameObject);

        if (NowTarget == enterGameObject)
        {
            NowTarget = null;
        }
    }
}
<file_sep>﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerData : MonoBehaviour
{
    public long userID;
    public int userIndex;
    public GameObject playerHand;
    public GameObject playerParticle;

    private KinectManager manager;
    
    
    public void ResetPalayerParticlePosition()
    {
        if(manager == null)
		{
			manager = KinectManager.Instance;
		}
        if(manager && manager.IsInitialized())
		{
            playerHand.GetComponent<PlayerKinectManager>().OverlayJoint(
                userID,
                (int)KinectInterop.JointType.Head,
                playerParticle.transform);
            
        }
    }
}
