new protected HandModel CreateHand(HandModel model)
    {
        HandModel hand_model = Instantiate(model, transform.position, transform.rotation)
                               as HandModel;

        hand_model.gameObject.SetActive(true);

        ParticleSystem[] particleSystems = hand_model.GetComponentsInChildren <ParticleSystem>();
        foreach (ParticleSystem system in particleSystems)
        {
            system.Stop();
        }

        Utils.IgnoreCollisions(hand_model.gameObject, gameObject);

        // add scripts...
        foreach (FingerModel finger in hand_model.fingers)
        {
            if (finger.GetType() == typeof(RigidFinger))
            {
                RigidFinger rigidFinger = finger as RigidFinger;
                foreach (Transform bone in rigidFinger.bones)
                {
                    if (bone == null)
                    {
                        continue;
                    }
                    GameObject bGameObject = bone.gameObject;
                    Rigidbody  bRigidBody  = bGameObject.gameObject.GetComponent <Rigidbody>() as Rigidbody;
                    bRigidBody.isKinematic            = false;
                    bRigidBody.useGravity             = false;
                    bRigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
                }

                rigidFinger.bones[rigidFinger.bones.Length - 1].gameObject.tag = "FingerTip";
            }
        }

        // add grasp script
        if (hand_model.GetType() == typeof(RigidHand))
        {
            hand_model.gameObject.AddComponent <GraspController>();
            GraspController graspController = hand_model.gameObject.GetComponent <GraspController>();
            //graspController.GraspTriggerDistance = 1.0f * this.GraspDistanceScale;
            //graspController.ReleaseTriggerDistance = 2.5f * this.GraspDistanceScale;
            graspController.GraspObjectDistance = 3.5f * this.GraspDistanceScale * transform.localScale.x;
        }

        Collider[] allCls = hand_model.GetComponentsInChildren <Collider>();
        foreach (Collider lcl in allCls)
        {
            foreach (Collider refCl in allCls)
            {
                if (!lcl.Equals(refCl))
                {
                    Physics.IgnoreCollision(lcl, refCl, true);
                }
            }
        }

        if (this.enableFingerParticleSystems && hand_model.GetType() == typeof(SkeletalHand))
        {
            SkeletalHand skeletalHand = hand_model as SkeletalHand;
            foreach (FingerModel finger in skeletalHand.fingers)
            {
                if (finger.GetType() == typeof(SkeletalFinger))
                {
                    SkeletalFinger skeletalFinger = finger as SkeletalFinger;

                    if (skeletalFinger.fingerType == Finger.FingerType.TYPE_INDEX)
                    {
                        Transform bone = skeletalFinger.bones[skeletalFinger.bones.Length - 1];

                        /*GameObject indexProxy = GameObject.Instantiate(this.IndexStimulationProxyPrefab, Vector3.zero, Quaternion.identity) as GameObject;
                         * indexProxy.transform.parent = bone;
                         * indexProxy.transform.localPosition = Vector3.zero;*/
                    }
                    else if (skeletalFinger.fingerType == Finger.FingerType.TYPE_THUMB)
                    {
                        Transform bone = skeletalFinger.bones[skeletalFinger.bones.Length - 1];

                        /*GameObject thumbProxy = GameObject.Instantiate(this.ThumbStimulationProxyPrefab, Vector3.zero, Quaternion.identity) as GameObject;
                         * thumbProxy.transform.parent = bone;
                         * thumbProxy.transform.localPosition = Vector3.zero;*/
                    }
                }
            }
            //skeletalHand.gameObject.AddComponent<StimulationProxy>();
        }

        return(hand_model);
    }
    new protected void UpdateHandModels(Dictionary <int, HandModel> all_hands,
                                        HandList leap_hands,
                                        HandModel left_model, HandModel right_model)
    {
        List <int> ids_to_check = new List <int>(all_hands.Keys);

        // Go through all the active hands and update them.
        int num_hands = leap_hands.Count;

        for (int h = 0; h < num_hands; ++h)
        {
            Hand leap_hand = leap_hands[h];

            HandModel model = (mirrorZAxis != leap_hand.IsLeft) ? left_model : right_model;

            // hmm, quite stupid way to keep track of the right hand ID...
            if (leap_hand.IsRight && !(right_model.GetType() == typeof(RigidHand)))
            {
                this.currentRightHandID = leap_hand.Id;
            }

            // If we've mirrored since this hand was updated, destroy it.
            if (all_hands.ContainsKey(leap_hand.Id) &&
                all_hands[leap_hand.Id].IsMirrored() != mirrorZAxis)
            {
                DestroyHand(all_hands[leap_hand.Id]);
                all_hands.Remove(leap_hand.Id);
            }

            // Only create or update if the hand is enabled.
            if (model != null)
            {
                ids_to_check.Remove(leap_hand.Id);

                // Create the hand and initialized it if it doesn't exist yet.
                if (!all_hands.ContainsKey(leap_hand.Id))
                {
                    HandModel new_hand = CreateHand(model);
                    new_hand.SetLeapHand(leap_hand);
                    new_hand.MirrorZAxis(mirrorZAxis);
                    new_hand.SetController(this);

                    // Set scaling based on reference hand.
                    float hand_scale = MM_TO_M * leap_hand.PalmWidth / new_hand.handModelPalmWidth;
                    new_hand.transform.localScale = hand_scale * transform.lossyScale;

                    new_hand.InitHand();
                    new_hand.UpdateHand();
                    all_hands[leap_hand.Id] = new_hand;
                    if (leap_hand.Id == this.currentRightHandID)
                    {
                        this.currentRelevantPalmPosition = all_hands[leap_hand.Id].GetPalmPosition();
                        foreach (FingerModel finger in all_hands[leap_hand.Id].fingers)
                        {
                            if (finger.fingerType == Finger.FingerType.TYPE_INDEX)
                            {
                                this.currentRelevantIndexPosition = finger.GetTipPosition();
                            }
                            else if (finger.fingerType == Finger.FingerType.TYPE_THUMB)
                            {
                                this.currentRelevantThumbPosition = finger.GetTipPosition();
                            }
                        }
                    }
                }
                else
                {
                    // Make sure we update the Leap Hand reference.
                    HandModel hand_model = all_hands[leap_hand.Id];
                    hand_model.SetLeapHand(leap_hand);
                    hand_model.MirrorZAxis(mirrorZAxis);

                    // Set scaling based on reference hand.
                    float hand_scale = MM_TO_M * leap_hand.PalmWidth / hand_model.handModelPalmWidth;
                    hand_model.transform.localScale = hand_scale * transform.lossyScale;
                    hand_model.UpdateHand();
                    if (leap_hand.Id == this.currentRightHandID)
                    {
                        this.currentRelevantPalmPosition = all_hands[leap_hand.Id].GetPalmPosition();
                        foreach (FingerModel finger in all_hands[leap_hand.Id].fingers)
                        {
                            if (finger.fingerType == Finger.FingerType.TYPE_INDEX)
                            {
                                this.currentRelevantIndexPosition = finger.GetTipPosition();
                            }
                            else if (finger.fingerType == Finger.FingerType.TYPE_THUMB)
                            {
                                this.currentRelevantThumbPosition = finger.GetTipPosition();
                            }
                        }
                    }
                }
            }
        }

        // Destroy all hands with defunct IDs.
        for (int i = 0; i < ids_to_check.Count; ++i)
        {
            DestroyHand(all_hands[ids_to_check[i]]);
            all_hands.Remove(ids_to_check[i]);
            if (ids_to_check[i] == this.currentRightHandID)
            {
                this.currentRightHandID = -1;
            }
        }
    }