//play effect
    //lifetime: character effect may have a lift time from outside, > 0 will take effect.
    //          < 0 means use effect's built-in life time.
    public EffectInstance PlayEffect(FC_CHARACTER_EFFECT effId, AvatarController avatar, float liftTime)
    {
        if (effId == FC_CHARACTER_EFFECT.INVALID)
        {
            return(null);
        }

        //get empty gameobject?
        List <EffectInstance> effList   = _allEffectArray[effId];
        EffectInstance        effResult = null;

        if (effList.Count > 0)
        {
            foreach (EffectInstance effInst in effList)
            {
                if (effInst == null ||
                    effInst.myObject == null)
                {
                    int zz = 0;
                    zz++;
                }
                if (!effInst.myObject.activeSelf)
                {
                    effResult = effInst;
                    break;
                }
            }
        }

        //no empty? create one
        if (effResult == null)
        {
            GameObject ego = AddEffectToPool(effId);
            effResult = ego.GetComponent <EffectInstance>();
            Assertion.Check(effResult != null);
            effResult.character_effect_id = effId;
            effResult.myTransform         = ego.transform;
            effResult.myObject            = ego;
            effList.Add(effResult);
        }

        //set enable and parent and pos
        Assertion.Check(effResult != null);
        effResult.myObject.SetActive(true);

        //find parent node
        CharacterEffectConfig effConfig = _characterEffectTable[effId] as CharacterEffectConfig;

        Assertion.Check(effConfig != null);

        Transform parent = Utils.FindTransformByNodeName(avatar.myTransform,
                                                         FCEquipmentsBase.GetNodeByEquipSlot(effConfig._parentSlot)
                                                         );

        if (parent == null)
        {
            parent = avatar.myTransform;
        }
        Assertion.Check(parent != null);
        effResult.myTransform.parent        = parent;
        effResult.myTransform.localPosition = Vector3.zero;
        effResult.myTransform.localRotation = Quaternion.identity;

        //add to living list
        LivingEffect liveEff = new LivingEffect();

        liveEff._effect = effResult;
        liveEff._avatar = avatar;
        liveEff._effID  = (int)effId;
        _livingEffects.Add(liveEff);

        //get effect instance and start effect
        EffectInstance eff = effResult;

        Assertion.Check(eff != null);
        if (liftTime > 0)
        {
            eff.LifeTick = liftTime;
        }
        else
        {
            eff.LifeTick = eff._lifeTime;
        }

        eff.DeadTick = eff._deadTime;

        eff.BeginEffect();

        return(effResult);
    }
    public EffectInstance PlayEffect(FC_GLOBAL_EFFECT effId, Vector3 effPos, Quaternion effRot)
    {
        if (effId == FC_GLOBAL_EFFECT.INVALID)
        {
            return(null);
        }


        //get empty gameobject?
        List <EffectInstance> effList   = _allEffectArray[effId];
        EffectInstance        effResult = null;

        if (effList.Count > 0)
        {
            foreach (EffectInstance effInst in effList)
            {
                if (!effInst.gameObject.activeSelf)
                {
                    effResult = effInst;
                    break;
                }
            }
        }

        //no empty? create one
        if (effResult == null)
        {
            if (effList.Count == FCConst.GLOBAL_EFFECT_COUNT)
            {
                //already full, select a slot which is nearly dead
                effList.Sort(Compare);
                EffectInstance slot = effList[0];

                EffectInstance effTemp = slot;
                if (effTemp != null)
                {
                    //recycle back to pool
                    effTemp.LifeTick = effTemp._lifeTime;
                    effTemp.FinishEffect(true);
                    slot.gameObject.SetActive(false);
                    effResult = slot;
                }
            }
            else
            {
                //size is not full, add a new one
                GameObject ego = AddEffectToPool(effId);
                effResult = ego.GetComponent <EffectInstance>();
                Assertion.Check(effResult != null);
                effResult.global_effect_id = effId;
                effList.Add(effResult);
            }
        }

        //set enable and pos
        Assertion.Check(effResult != null);
        effResult.gameObject.SetActive(true);
        Transform effectRsltTransform = effResult.myTransform;

        effectRsltTransform.position = effPos;
        effectRsltTransform.rotation = effRot;

        //add to living list
        LivingEffect liveEff = new LivingEffect();

        liveEff._effect = effResult;
        liveEff._avatar = null;
        liveEff._effID  = (int)effId;

        _livingEffects.Add(liveEff);


        //get effect instanse and start effect
        EffectInstance eff = effResult;

        if (eff != null)
        {
            eff.LifeTick = eff._lifeTime;
            eff.DeadTick = eff._deadTime;
            eff.BeginEffect();
        }

        return(effResult);
    }