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);
            }
        }
    }
    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;
    }
    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;
    }