void PlayNextFrame(float delta)
    {
        TryPlayEffect();
        ChangeAttack();
        ChangeWeaponTrail();

        if (PoseEvent.ContainsKey(po.Idx))
        {
            //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223
            if ((PoseEvent[po.Idx] & (int)PoseEvt.WeaponIsReturned) != 0)
            {
                PoseEvent[po.Idx] &= ~(int)PoseEvt.WeaponIsReturned;
                loop     = false;
                curIndex = po.LoopEnd;
            }
        }

        //有连招.
        if (TestInputLink())
        {
            return;
        }
        if (loop)
        {
            if (curIndex > po.LoopEnd)
            {
                if (curIndex > po.LoopStart)
                {
                    PlayPosEvent();
                    curIndex = po.LoopStart;
                    if (loop)
                    {
                        return;
                    }
                }
                curIndex = po.LoopStart;
            }
        }
        else
        {
            if (curIndex > po.End)
            {
                if (single)
                {
                    Pause = true;
                }
                else
                {
                    posMng.OnActionFinished();
                }
                return;
            }

            if (TheFirstFrame == curIndex)
            {
                ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx);
            }
            if (TheLastFrame == curIndex)
            {
                ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx);
            }
        }

        BoneStatus status = null;

        if (po.SourceIdx == 0)
        {
            status = AmbLoader.CharCommon[curIndex];
        }
        else if (po.SourceIdx == 1)
        {
            status = AmbLoader.FrameBoneAni[CharacterIdx][curIndex];
        }

        if (mOwner.Attr.IsPlayer && FightWnd.Exist)
        {
            FightWnd.Instance.UpdatePoseStatus(po.Idx, curIndex);
        }

        for (int i = 0; i < bo.Count; i++)
        {
            bo[i].localRotation = status.BoneQuat[i];
            if (i == 0)
            {
                bo[i].localPosition = status.BonePos;
            }
        }

        bool IgnoreActionMoves = IgnoreActionMove(po.Idx);

        for (int i = 0; i < dummy.Count; i++)
        {
            if (i == 0)
            {
                if (lastPosIdx == po.Idx)
                {
                    Vector3 targetPos = status.DummyPos[i];
                    Vector3 vec       = transform.rotation * (targetPos - lastDBasePos) * moveScale;
                    if (IgnoreActionMoves)
                    {
                        vec.x = 0;
                        vec.z = 0;
                        vec.y = 0;
                    }
                    else
                    {
                    }
                    moveDelta   += vec;
                    lastDBasePos = targetPos;
                }
            }
            else
            {
                dummy[i].localRotation = status.DummyQuat[i];
                dummy[i].localPosition = status.DummyPos[i];
            }
        }

        lastFrameIndex = curIndex;
        curIndex++;
        lastSource = po.SourceIdx;
        lastPosIdx = po.Idx;
    }
    public void PlayFrame(float timeRatio)
    {
        TryPlayEffect();
        ChangeAttack();
        ChangeWeaponTrail();
        ActionEvent.HandlerActionEvent(owner, po.Idx, curIndex);
        if (PoseEvent.ContainsKey(po.Idx))
        {
            //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223
            PoseEvent.Remove(po.Idx);
            loop     = false;
            curIndex = po.LoopEnd;
        }
        if (TestInputLink())
        {
            return;
        }
        if (loop)
        {
            if (LockCurrentFrame)
            {
                if (PoseStraight <= 0.0f)
                {
                    loop             = false;
                    curIndex         = po.LoopEnd + 1;
                    LockCurrentFrame = false;
                    return;
                }
            }

            if (curIndex >= po.LoopEnd)
            {
                LoopCount++;
                PlayPosEvent();
                if (loop)
                {
                    curIndex = po.LoopStart;
                }
                return;
            }
        }
        else
        {
            if (curIndex > po.End)
            {
                posMng.OnActionFinished();
                return;
            }
            if (TheFirstFrame <= curIndex && TheFirstFrame != -1)
            {
                ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx);
                TheFirstFrame = -1;
            }
            if (TheLastFrame <= curIndex && TheLastFrame != -1)
            {
                ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx);
                TheLastFrame = -1;
            }
        }
        //Debug.Log("PlayKeyFrame:" + Time.frameCount);
        //curIndex = targetIndex;
        BoneStatus status     = null;
        BoneStatus lastStatus = null;

        if (lastSource == 0 && AmbLoader.CharCommon.Count > lastFrameIndex && lastFrameIndex >= 0)
        {
            lastStatus = AmbLoader.CharCommon[lastFrameIndex];
        }
        else if (AmbLoader.PlayerAnimation.ContainsKey(owner.UnitId) && AmbLoader.PlayerAnimation[owner.UnitId].Count > lastFrameIndex && lastFrameIndex >= 0)
        {
            lastStatus = AmbLoader.PlayerAnimation[owner.UnitId][lastFrameIndex];
        }
        if (po.SourceIdx == 0)
        {
            status = AmbLoader.CharCommon[curIndex];
        }
        else if (po.SourceIdx == 1)
        {
            status = AmbLoader.PlayerAnimation[owner.UnitId][curIndex];
        }
        else
        {
            status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, curIndex);
        }

        if (status != null && lastStatus != null)
        {
            bo[0].localRotation = Quaternion.Slerp(lastStatus.BoneQuat[0], status.BoneQuat[0], timeRatio);
            bo[0].localPosition = Vector3.Lerp(lastStatus.BonePos, status.BonePos, timeRatio);
            for (int i = 1; i < bo.Count; i++)
            {
                bo[i].localRotation = Quaternion.Slerp(lastStatus.BoneQuat[i], status.BoneQuat[i], timeRatio);
            }
        }

        bool IgnoreActionMoves = PoseStatus.IgnoreActionMove(po.Idx);

        if (owner.IsDebugUnit())
        {
            if (OnAnimationFrame != null)
            {
                OnAnimationFrame(po.SourceIdx, po.Idx, curIndex, timeRatio);
            }
            //IgnoreActionMoves = false;
        }

        bool IgnoreActionXZMove = PoseStatus.IgnoreXZMove(po.Idx);

        if (lastStatus != null && status != null)
        {
            if (lastPosIdx == po.Idx)
            {
                Vector3 targetPos = Vector3.Lerp(lastStatus.DummyPos[0], status.DummyPos[0], timeRatio);
                Vector3 vec       = Target.rotation * (targetPos - lastDBasePos) * moveScale;
                if (IgnoreActionMoves)
                {
                    vec.x = 0;
                    vec.z = 0;
                    vec.y = 0;
                }
                else if (IgnoreActionXZMove)
                {
                    vec.x = vec.z = 0;
                }
                moveDelta   += vec;
                lastDBasePos = targetPos;
            }

            for (int i = 1; i < dummy.Count; i++)
            {
                dummy[i].localRotation = Quaternion.Slerp(lastStatus.DummyQuat[i], status.DummyQuat[i], timeRatio);
                dummy[i].localPosition = Vector3.Lerp(lastStatus.DummyPos[i], status.DummyPos[i], timeRatio);
            }
        }
    }
    public void SetPosData(Pose pos, float BlendTime = 0.0f)
    {
        //一些招式,需要把尾部事件执行完才能切换武器.
        LoopCount        = 0;
        LockCurrentFrame = false;
        if (TheLastFrame != -1 && po != null)
        {
            ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx);
            TheLastFrame = -1;
        }
        else
        {
            if (po != null && po.Link != 0)
            {
                //一些动作,默认连接其他动作,类似,486第一帧会收刀,收刀会切换武器为2
                ActionEvent.HandlerPoseAction(mOwner, po.Link);
            }
        }
        //一些招式,动作结束会给使用者加上BUFF,另外一些招式,会让受击方得到BUFF
        int lastPosIdx = 0;

        if (po != null && po.Idx != 0)
        {
            lastPosIdx = po.Idx;
        }

        moveScale    = 1.0f;
        attackTarget = Vector3.zero;
        //重置速度
        bool isAttackPos = false;

        if (po == null)
        {
            isAttackPos = false;
        }
        else
        {
            //isAttackPos = po.Idx >= CommonAction.AttackActStart && po.Idx != CommonAction.GunIdle;
            isAttackPos = posMng.IsAttackPose(po.Idx);
        }
        //从IDLE往IDLE是不许融合的,否则武器位置插值非常难看
        if (pos != null && po != null && pos.Idx == po.Idx && pos.Idx == 0)
        {
            BlendTime = 0.0f;
        }
        //保存当前帧的姿势,用于和下个动作融合
        //当前状态下有姿势,且帧存在状态缓存
        if (po != null)
        {
            lastPosIdx = po.Idx;
        }
        else
        {
            lastPosIdx = pos.Idx;
        }
        if (BlendTime != 0.0f)
        {
            GetCurrentSnapShot();
            //如果有混合,重置混合位置.
            nextDBasePos = lastFrameStatus.DummyPos[0];
        }
        //动画帧率与运行帧率可能要转换一下.
        blendTime            = BlendTime;
        lastFramePlayedTimes = 0;
        po   = pos;
        loop = (pos.LoopStart != 0 && pos.LoopEnd != 0);//2帧相同不为0

        //查看第一个blend的最后一帧,如果有,切换目标帧设置为这个,若第一个是act则目标帧为起始帧
        //PosAction blend = null;
        PosAction act = null;

        if (pos.ActionList.Count != 0)
        {
            if (isAttackPos)
            {
                for (int i = 0; i < pos.ActionList.Count; i++)
                {
                    //过滤掉565,刀雷电斩的头一个 第一个混合段与整个动画一致.
                    if (pos.ActionList[i].Start == pos.Start && pos.ActionList[i].End == pos.End)
                    {
                        continue;
                    }
                    act = pos.ActionList[i];
                    break;
                }
            }
            else
            {
                act = pos.ActionList[0];
            }
        }

        TheLastFrame  = pos.End - 1;
        TheFirstFrame = pos.Start;

        //算第一个过渡帧条件很多,有切换目的帧是否设定,第一个过渡帧是否存在,上一个动作是否攻击动作,锤绝325BUG,其他招式接325,还要在地面等,应该不需要在地面等
        //curIndex = targetFrame != 0 ? targetFrame : (act != null ? (act.Type == "Action" ? act.Start: (isAttackPos ? act.End : pos.Start)): pos.Start);
        curIndex = act != null ? (act.Type == "Action" ? (isAttackPos ? act.Start : pos.Start) : (isAttackPos ? act.End : act.Start)) : pos.Start;
        //部分动作混合帧比开始帧还靠前
        if (curIndex < pos.Start)
        {
            curIndex = pos.Start;
        }
        blendStart = curIndex;
        //if (blendTime != 0.0f && (pos.Idx == CommonAction.JumpFall || pos.Idx == CommonAction.Jump || pos.Idx == CommonAction.JumpFallOnGround))
        //    Debug.Log("过渡帧为" + blendStart + " 转换到动作:" + pos.Idx);
        effectPlayed = false;
        sfxEffect    = null;
        playedTime   = 0;

        //下一个动作的第一帧所有虚拟物体
        if (po.SourceIdx == 0)
        {
            lastDBasePos = AmbLoader.CharCommon[curIndex].DummyPos[0];
        }
        else if (po.SourceIdx == 1)
        {
            lastDBasePos = AmbLoader.PlayerAnimation[owner.UnitId][curIndex].DummyPos[0];
        }

        if (lastPosIdx != 0)
        {
            Option poseInfo = Main.Ins.MenuResLoader.GetPoseInfo(lastPosIdx);
            if (poseInfo.first.Length != 0 && poseInfo.first[0].flag[0] == 18 && lastPosIdx != 468) //18为,使用招式后获取物品ID 468-469都会调用微尘,hack掉468pose的
            {
                owner.GetItem(poseInfo.first[0].flag[1]);                                           //忍刀小绝,同归于尽,会获得微尘物品,会即刻死亡
            }
        }

        curPos = pos.Idx;
    }
    void PlayNextKeyFrame()
    {
        TryPlayEffect();
        ChangeAttack();
        ChangeWeaponTrail();
        ActionEvent.HandlerActionEvent(owner, po.Idx, curIndex);
        if (PoseEvent.ContainsKey(po.Idx))
        {
            //当218发射飞轮,很快返回,还未到219动作时,下次播放219,就得立即取消循环,221 223
            PoseEvent.Remove(po.Idx);
            loop     = false;
            curIndex = po.LoopEnd;
        }

        //有连招.
        if (TestInputLink())
        {
            return;
        }

        if (loop)
        {
            if (LockCurrentFrame)
            {
                if (PoseStraight <= 0.0f)
                {
                    loop             = false;
                    curIndex         = po.LoopEnd + 1;
                    LockCurrentFrame = false;
                    return;
                }
            }
            if (curIndex > po.LoopEnd)
            {
                if (curIndex > po.LoopStart)
                {
                    LoopCount++;
                    PlayPosEvent();
                    if (loop)
                    {
                        curIndex = po.LoopStart;
                    }
                    return;
                }
                curIndex = po.LoopStart;
            }
        }
        else
        {
            if (curIndex > po.End)
            {
                posMng.OnActionFinished();
                return;
            }

            if (TheFirstFrame <= curIndex && TheFirstFrame != -1)
            {
                ActionEvent.HandlerFirstActionFrame(mOwner, po.Idx);
                TheFirstFrame = -1;
            }
            if (TheLastFrame <= curIndex && TheLastFrame != -1)
            {
                ActionEvent.HandlerFinalActionFrame(mOwner, po.Idx);
                TheLastFrame = -1;
            }
        }
        //Debug.Log("PlayKeyFrame:" + Time.frameCount);
        BoneStatus status = null;

        if (po.SourceIdx == 0)
        {
            status = AmbLoader.CharCommon[curIndex];
        }
        else if (po.SourceIdx == 1)
        {
            status = AmbLoader.PlayerAnimation[owner.UnitId][curIndex];
        }
        else
        {
            status = AmbLoader.GetBoneStatus(po.SourceIdx, owner.UnitId, curIndex);
        }

        //Debug.LogError("play keyframe " + " idx:" + curIndex);
        if (bo.Count != 0)
        {
            bo[0].localRotation = status.BoneQuat[0];
            bo[0].localPosition = status.BonePos;
        }

        for (int i = 1; i < bo.Count; i++)
        {
            bo[i].localRotation = status.BoneQuat[i];
        }

        bool IgnoreActionMoves = PoseStatus.IgnoreActionMove(po.Idx);
        //if (owner.IsDebugUnit())
        //    IgnoreActionMoves = false;
        bool IgnoreActionXZMove = PoseStatus.IgnoreXZMove(po.Idx);

        if (lastPosIdx == po.Idx)
        {
            Vector3 targetPos = status.DummyPos[0];
            Vector3 vec       = Target.rotation * (targetPos - lastDBasePos) * moveScale;
            //如果忽略位移,或者在动作的循环帧中,即第一次从循环头开始播放后,不再计算位移.
            if (IgnoreActionMoves)
            {
                vec.x = 0;
                vec.z = 0;
                vec.y = 0;
            }
            else if (IgnoreActionXZMove)
            {
                vec.x = vec.z = 0;
            }
            moveDelta += vec;
            //if (po.Idx == 151)
            //    Debug.LogError(string.Format("pose:{0} frame:{1} move: x ={2}, y ={3} z = {4}", po.Idx, curIndex, moveDelta.x, moveDelta.y, moveDelta.z));
            lastDBasePos = targetPos;
        }

        for (int i = 1; i < dummy.Count; i++)
        {
            dummy[i].localRotation = status.DummyQuat[i];
            dummy[i].localPosition = status.DummyPos[i];
        }

        lastFrameIndex = curIndex;
        curIndex++;
        lastSource = po.SourceIdx;
        lastPosIdx = po.Idx;
    }