void Update()
    {
        if (GlobalSingleton.GetHealth() < 0)
        {
            return;
        }

        if (hitCooldown > 0)
        {
            hitCooldown -= Time.deltaTime;
        }
        beat += GlobalSingleton.GetBPM() * 0.0166666666666f * Time.deltaTime;

        if (beat > DESTROY_BEAT + sustainLength)
        {
            NoteGenerator.RemoveNote(this);
            Destroy(gameObject);
            return;
        }

        if (beat > lateDistance && !playerMissed && !playerHit)
        {
            GlobalSingleton.GetShake().StartShake(0.5f, 0.1f);
            MissNote(0);
        }

        if (beat > lateDistance && lastNote)
        {
            lastNote = false;
            if (numMissed <= 0)
            {
                GlobalSingleton.IncreaseScore();
            }
            numMissed = 0;
        }

        if (beat >= COMPUTER_BEAT && !computerHit)
        {
            computerHit = true;
            StartCoroutine(PlayNote());
        }

        if (beat >= HIDDING_BEAT && !hideHit && hideNote)
        {
            hideHit = true;
            for (int i = 0; i < noteColors.Length; ++i)
            {
                StartCoroutine(HitchLib.Tweening.FadeTo(noteColors[i], 60f / GlobalSingleton.GetBPM(),
                                                        HitchLib.Easing.EASE_LINEAR, 0));
            }
            StartCoroutine(HitchLib.Tweening.FadeTo(keyText, 60f / GlobalSingleton.GetBPM(),
                                                    HitchLib.Easing.EASE_LINEAR, 0));
        }

        float   yPos = BEAT_PLAYER_Y - (beat * BEAT_SIZE);
        Vector3 pos  = rTrans.localPosition;

        pos.y = yPos * GlobalSingleton.GetTimelineScale();
        rTrans.localPosition = pos;
    }
    void Update()
    {
        if (GlobalSingleton.GetHealth() < 0)
        {
            return;
        }

        cooldown -= Time.deltaTime * GlobalSingleton.GetBPM() * 0.0166666666f;
        if (cooldown < 0)
        {
            GameObject go = Instantiate(notePrefab);
            go.transform.SetParent(transform);
            if (noteIndex % 3 == 0)
            {
                go.transform.localPosition = new Vector3(-60.0f, -100000, 0);
            }
            else if (noteIndex % 3 == 1)
            {
                go.transform.localPosition = new Vector3(0.0f, -100000, 0);
            }
            else
            {
                go.transform.localPosition = new Vector3(60.0f, -100000, 0);
            }
            go.transform.localScale = Vector3.one;
            NoteController nc = go.GetComponent <NoteController>();
            nc.hideNote      = (noteIndex - GlobalSingleton.GetHideThreshold() < 0);
            nc.id            = notes[noteIndex].id;
            nc.sustainLength = (notes[noteIndex].length - 1) / 2.0f;
            nc.lateDistance  = lateDistance;
            nc.lastNote      = noteIndex >= (notes.Count - 1);
            if (notes[noteIndex].rest / 2.0f > 0)
            {
                while (cooldown < 0)
                {
                    cooldown += notes[noteIndex].rest / 2.0f;
                }
            }
            else
            {
                cooldown = 0;
            }
            liveNotes.Add(nc);

            if (++noteIndex >= notes.Count)
            {
                cooldown -= notes[noteIndex - 1].rest / 2.0f;
                noteIndex = 0;
                if (notes.Count > 8)
                {
                    while (cooldown < 0)
                    {
                        cooldown += 4;
                    }
                }
                else
                {
                    while (cooldown < 0)
                    {
                        cooldown += 8;
                    }
                }
                notes.Add(GenerateNote(notes.Count));
            }
        }
        NoteController nearestNote         = null;
        float          nearestDist         = float.PositiveInfinity;
        NoteController nearestUnplayed     = null;
        float          nearestUnplayedDist = float.PositiveInfinity;
        NoteController nearestPositive     = null;
        float          nearestPositiveDist = float.PositiveInfinity;

        foreach (NoteController note in liveNotes)
        {
            float signedDist = note.GetDistance();
            float dist       = Mathf.Abs(signedDist);

            if (dist < nearestDist && dist < triggerRange)
            {
                nearestNote = note;
                nearestDist = dist;
            }

            if (dist < nearestUnplayedDist && !note.GetHit() && dist < triggerRange)
            {
                nearestUnplayed     = note;
                nearestUnplayedDist = dist;
            }

            if (signedDist >= 0 && signedDist < nearestPositiveDist && dist < triggerRange)
            {
                nearestPositive     = note;
                nearestPositiveDist = signedDist;
            }
        }

        bool hitNote  = false;
        int  pressKey = -1;

        for (int i = 0; i < 4; ++i)
        {
            if (Input.GetKeyDown(GlobalSingleton.GetKey(i)))
            {
                pressKey = i;
                if (nearestNote != null && nearestNote.id == i &&
                    (!nearestNote.GetHit() || nearestNote.GetCooldown() > 0) &&
                    nearestDist < okayDistance && nearestNote.GetDistance() > -lateDistance)
                {
                    hitNote = true;
                    nearestNote.HitNote(perfectDistance);
                }
                else if (nearestUnplayed != null && nearestUnplayed.id == i &&
                         nearestUnplayedDist < okayDistance && nearestUnplayed.GetDistance() > -lateDistance)
                {
                    hitNote = true;
                    nearestUnplayed.HitNote(perfectDistance);
                }
                else if (nearestPositive != null && nearestPositive.id == i &&
                         (!nearestPositive.GetHit() || nearestPositive.GetCooldown() > 0) &&
                         nearestPositiveDist < okayDistance && nearestPositiveDist > -lateDistance)
                {
                    hitNote = true;
                    nearestPositive.HitNote(perfectDistance);
                }
            }
        }
        if (pressKey >= 0 && !hitNote)
        {
            NoteController missed = null;
            if (nearestPositive != null && nearestPositive.id == pressKey)
            {
                missed = nearestPositive;
            }
            else if (nearestNote != null)
            {
                missed = nearestNote;
            }
            else if (nearestUnplayed != null)
            {
                missed = nearestUnplayed;
            }
            else if (nearestPositive != null)
            {
                missed = nearestPositive;
            }
            if (missed != null)
            {
                missed.MissNote(okayDistance);
                GlobalSingleton.GetShake().StartShake(1.0f, 0.1f);
                GlobalSingleton.GetSound().SourNote(pressKey);
            }
        }
    }