/// <summary> /// Wait for the previous animation to finish, then play it smoothly. /// (If the previously playing animation is a loop animation, it will not be executed.) /// </summary> /// <param name="animClipName">Name of the Animation Clip</param> /// <param name="fadeTime">Fade Time</param> /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param> /// <param name="blendMethod">How it is blended with the animation of the lower layers</param> /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param> /// <returns>Animation data to be played. If it fails, null is returned.</returns> public apAnimPlayData CrossFadeQueuedAt(apAnimPlayData playData, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false) { if (playData == null) { Debug.LogError("CrossFadeQueuedAt Failed : Unknown AnimPlayData"); return(null); } if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX) { Debug.LogError("CrossFadeQueuedAt Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX); return(null); } if (fadeTime < 0.0f) { fadeTime = 0.0f; } //Debug.Log("CrossFadeQueued [" + animClipName + "]"); apAnimPlayQueue playQueue = _animPlayQueues[layer]; apAnimPlayUnit resultPlayUnit = playQueue.PlayQueuedAt(playData, frame, blendMethod, fadeTime, isAutoEndIfNotloop); if (resultPlayUnit == null) { return(null); } RefreshPlayOrders(); return(playData); }
public void Clear() { _parentAnimPlayQueue = null; //_tNextPlayStart = 0.0f; _tBlend = 0.0f; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.New; _nextPlayUnit = null; _prevWaitingPlayUnit = null; //_prevPlayUnits.Clear(); _prevPlayUnitKeys.Clear(); _prevPlayUnitWeight.Clear(); _requestWeight = 1.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = 0.0f; _tActiveMiddle = 0.0f; _status = STATUS.Ready; _isNextPlayUnitIsInPrevUnit = false; //추가 1.15 사용자가 지정한 시작 프레임을 쓸 것인지 여부 (True면 StartFrame으로 강제됨) _isResetPlayAtStartFrame = true; _frameToStart = -1; ReleaseChainedRequest(); }
public void PlayQueuedAt(apAnimPlayUnit nextPlayUnit, apAnimPlayUnit prevLastPlayUnit, int frame, float tBlend) { //Debug.LogError(">> AnimRequest <Queued> : " + nextPlayUnit._linkedAnimClip._name + " >> 대기"); //_tNextPlayStart = -1;//Queued 타입은 플레이 시간을 받지 않는다. _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.Queued; _nextPlayUnit = nextPlayUnit; _nextPlayUnit.SetOwnerRequest_Next(this); _prevWaitingPlayUnit = prevLastPlayUnit; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = -1.0f; _tActiveEnd = -1.0f; //<<알 수 없다. _tActiveMiddle = -1.0f; _status = STATUS.Ready; //<<일단 대기 _isNextPlayUnitIsInPrevUnit = false; _nextUnitWeight_Overlap = 1.0f; //추가 1.15 사용자가 지정한 시작 프레임 > On _isResetPlayAtStartFrame = false; _frameToStart = frame; }
public void Clear() { _parentAnimPlayQueue = null; //_tNextPlayStart = 0.0f; _tBlend = 0.0f; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.New; _nextPlayUnit = null; _prevWaitingPlayUnit = null; _prevPlayUnits.Clear(); _requestWeight = 1.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = 0.0f; _tActiveMiddle = 0.0f; _status = STATUS.Ready; _isNextPlayUnitIsInPrevUnit = false; }
public void PlayNew(apAnimPlayUnit nextPlayUnit, float tBlend) { //Debug.LogError(">> AnimRequest <New> : " + nextPlayUnit._linkedAnimClip._name + " >> 바로 시작한다"); //_tNextPlayStart = tNextPlay;//<<이게 필요한가? _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.New; _nextPlayUnit = nextPlayUnit; _nextPlayUnit.SetOwnerRequest_Next(this); _prevWaitingPlayUnit = null; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = _tBlend; _tActiveMiddle = _tBlend * 0.5f; _status = STATUS.Active; //<<바로 시작 _isNextPlayUnitIsInPrevUnit = false; //이전 코드 //for (int i = 0; i < _prevPlayUnits.Count; i++) //{ // if (nextPlayUnit == _prevPlayUnits[i] // && _prevPlayUnits[i].UnitWeight > 0.05f) // { // _isNextPlayUnitIsInPrevUnit = true; // break; // } //} _isNextPlayUnitIsInPrevUnit = _parentAnimPlayQueue.IsAlreadyAnimUnitPlayed(_nextPlayUnit); _nextUnitWeight_Overlap = 1.0f; if (_isNextPlayUnitIsInPrevUnit) { _nextUnitWeight_Overlap = _nextPlayUnit.UnitWeight; if (!_nextPlayUnit.IsLoop) { _nextPlayUnit.ResetPlay(); } } else { _nextPlayUnit.ResetPlay(); } }
// Event //----------------------------------------------------------------- public void OnAnimPlayUnitPlayStart(apAnimPlayUnit playUnit) { //Play Unit이 재생을 시작했다. //Delay 이후에 업데이트되는 첫 프레임에 이 이벤트가 호출된다. // > Root Unit이 바뀔 수 있으므로 Play Manager에도 신고를 해야한다. _playManager.OnAnimPlayUnitPlayStart(playUnit, this); }
/// <summary> /// Event : Animation is started /// </summary> /// <param name="playUnit"></param> /// <param name="playQueue"></param> public void OnAnimPlayUnitPlayStart(apAnimPlayUnit playUnit, apAnimPlayQueue playQueue) { //Play Unit이 재생을 시작했다. //Delay 이후에 업데이트되는 첫 프레임에 이 이벤트가 호출된다. // > Root Unit이 바뀔 수 있으므로 Play Manager에도 신고를 해야한다. SetOptRootUnit(playUnit._targetRootUnit); }
public void Resume() { for (int i = 0; i < _nPlayedUnit; i++) { _tmpCurPlayUnit = _animPlayUnits[i]; _tmpCurPlayUnit.Resume(); } }
//AnimClip중에 요청된 RootUnit에 대한 것이 아니면 강제로 종료한다. public void StopWithInvalidRootUnit(apOptRootUnit usingRootUnit) { for (int i = 0; i < _nPlayedUnit; i++) { _tmpCurPlayUnit = _animPlayUnits[i]; if (_tmpCurPlayUnit._targetRootUnit != usingRootUnit) { _animPlayUnits[i].SetEnd(); } } }
/// <summary> /// Wait for the previous animation to finish, then play it smoothly. /// (If the previously playing animation is a loop animation, it will not be executed.) /// </summary> /// <param name="animClipName">Name of the Animation Clip</param> /// <param name="fadeTime">Fade Time</param> /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param> /// <param name="blendMethod">How it is blended with the animation of the lower layers</param> /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param> /// <returns>Animation data to be played. If it fails, null is returned.</returns> public apAnimPlayData CrossFadeQueued(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false) { //Debug.LogError("Start CrossFadeQueued [" + animClipName + "]"); apAnimPlayData playData = GetAnimPlayData_Opt(animClipName); if (playData == null) { Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]"); return(null); } if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX) { Debug.LogError("CrossFade Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX); return(null); } if (fadeTime < 0.0f) { fadeTime = 0.0f; } //Debug.Log("CrossFadeQueued [" + animClipName + "]"); apAnimPlayQueue playQueue = _animPlayQueues[layer]; apAnimPlayUnit resultPlayUnit = playQueue.PlayQueued(playData, blendMethod, fadeTime, isAutoEndIfNotloop); if (resultPlayUnit == null) { return(null); } //float delayTime = resultPlayUnit.DelayToPlayTime; //float delayTime = Mathf.Clamp01(resultPlayUnit.RemainPlayTime - fadeTime); //if (playOption == PLAY_OPTION.StopAllLayers) //{ // //다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다. // for (int i = 0; i < _animPlayQueues.Count; i++) // { // if (i == layer) // { continue; } // _animPlayQueues[i].StopAll(delayTime); // } //} RefreshPlayOrders(); return(playData); }
public void PlayQueued(apAnimPlayUnit nextPlayUnit, apAnimPlayUnit prevLastPlayUnit, float tBlend) { //Debug.LogError(">> AnimRequest <Queued> : " + nextPlayUnit._linkedAnimClip._name + " >> 대기"); //_tNextPlayStart = -1;//Queued 타입은 플레이 시간을 받지 않는다. _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.Queued; _nextPlayUnit = nextPlayUnit; _nextPlayUnit.SetOwnerRequest_Next(this); _prevWaitingPlayUnit = prevLastPlayUnit; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = -1.0f; _tActiveEnd = -1.0f; //<<알 수 없다. _tActiveMiddle = -1.0f; _status = STATUS.Ready; //<<일단 대기 _isNextPlayUnitIsInPrevUnit = false; //이전코드 //for (int i = 0; i < _prevPlayUnits.Count; i++) //{ // if (nextPlayUnit == _prevPlayUnits[i] // && _prevPlayUnits[i].UnitWeight > 0.05f) // { // _isNextPlayUnitIsInPrevUnit = true; // break; // } //} _nextUnitWeight_Overlap = 1.0f; //이걸 플레이하는 시점에서 지정 //_isNextPlayUnitIsInPrevUnit = _parentAnimPlayQueue.IsAlreadyAnimUnitPlayed(_nextPlayUnit); //_nextUnitWeight_Overlap = 1.0f; //if (_isNextPlayUnitIsInPrevUnit) //{ // _nextUnitWeight_Overlap = _nextPlayUnit.UnitWeight; //} }
public apAnimPlayUnit _playUnit = null; //<<미리 만들어놓고, 실행중일 때에는 연결, 그렇지 않을 때에는 해제한다. public MecanimClipData(AnimationClip clipAsset, apAnimClip animClip, apOptRootUnit linkedRootUnit) { _clipAsset = clipAsset; _animClip = animClip; _linkedRootUnit = linkedRootUnit; //Mecanim용 PlayUnit을 만든다. _playUnit = new apAnimPlayUnit(null, -1, -1); _playUnit.SetMecanimPlayUnit(); _isCalculatedPrev = false; ReadyToUpdate(); Unlink(); }
/// <summary> /// AnimClip 이름을 인자로 받아서 애니메이션을 재생한다. /// Fade 타임을 받아서 다른 모든 클립에서 자연스럽게 변환된다. /// </summary> /// <param name="animClipName">Clip 이름. 맞지 않을 경우 처리 실패</param> /// <param name="layer">실행되는 레이어. 0부터 실행되며 최대값은 20</param> /// <param name="blendMethod">다른 레이어와 블렌드시 옵션</param> /// <param name="playOption">StopAllLayer인 경우 요청된 레이어 외의 Clip들이 다음 Clip이 실행되는 순간 같이 종료된다.</param> /// <param name="isAutoEndIfNotloop">[Loop 타입이 아닌 경우] True이면 재생 종료시 자동으로 처리 데이터가 삭제된다.</param> /// <param name="fadeTime">페이드 시간. 기본값은 0.3</param> /// <returns></returns> public apAnimPlayData CrossFade(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false) { apAnimPlayData playData = GetAnimPlayData_Opt(animClipName); if (playData == null) { Debug.LogError("CrossFade Failed : No AnimClip [" + animClipName + "]"); return(null); } if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX) { Debug.LogError("CrossFade Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX); return(null); } if (fadeTime < 0.0f) { fadeTime = 0.0f; } apAnimPlayQueue playQueue = _animPlayQueues[layer]; apAnimPlayUnit resultPlayUnit = playQueue.Play(playData, blendMethod, fadeTime, isAutoEndIfNotloop); if (resultPlayUnit == null) { return(null); } //float fadeInTime = resultPlayUnit.FadeInTime; if (playOption == PLAY_OPTION.StopAllLayers) { //다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다. for (int i = 0; i < _animPlayQueues.Count; i++) { if (i == layer) { continue; } _animPlayQueues[i].StopAll(fadeTime); } } RefreshPlayOrders(); return(playData); }
private apAnimPlayUnit MakePlayUnit(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop) { //새로 만들고 //그 전에.. //재생중인 PlayUnit이 있으면 그걸 사용하자 //레이어는 같아야 한다. apAnimPlayUnit existPlayUnit = null; for (int i = 0; i < _animPlayUnits.Count; i++) { if (_animPlayUnits[i]._linkedAnimClip == playData._linkedAnimClip && _animPlayUnits[i].IsUpdatable ) { existPlayUnit = _animPlayUnits[i]; break; } } if (existPlayUnit != null) { //Debug.Log("아직 재생중인 PlayUnit을 다시 재생하는 요청이 왔다. [" + existPlayUnit._linkedAnimClip._name + "]"); existPlayUnit.SetSubOption(blendMethod, isAutoEndIfNotloop, GetNextPlayUnitRequestOrder(), GetNextRequestLinkKey()); _nPlayedUnit = _animPlayUnits.Count; return(existPlayUnit); } apAnimPlayUnit newPlayUnit = new apAnimPlayUnit(this, GetNextPlayUnitRequestOrder(), GetNextRequestLinkKey()); newPlayUnit.SetAnimClip(playData, _layer, blendMethod, isAutoEndIfNotloop, false); //if(!newPlayUnit._linkedAnimClip.IsPlaying) //{ // if(newPlayUnit.Frame != newPlayUnit.StartFrame) // { // Debug.Log("새로운 재생 요청 - 프레임이 초기화되지 않음 [" + newPlayUnit._linkedAnimClip._name + "]"); // } // newPlayUnit.ResetPlay(); //} //리스트에 넣자 _animPlayUnits.Add(newPlayUnit); _nPlayedUnit = _animPlayUnits.Count; _isInitPlayUnit = false; return(newPlayUnit); }
public void PlayNew(apAnimPlayUnit nextPlayUnit, float tBlend) { _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.New; _nextPlayUnit = nextPlayUnit; _nextPlayUnit.SetOwnerRequest_Next(this); _prevWaitingPlayUnit = null; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = _tBlend; _tActiveMiddle = _tBlend * 0.5f; _status = STATUS.Active; //<<바로 시작 _isNextPlayUnitIsInPrevUnit = false; _isNextPlayUnitIsInPrevUnit = _parentAnimPlayQueue.IsAlreadyAnimUnitPlayed(_nextPlayUnit); _nextUnitWeight_Overlap = 1.0f; //추가 1.15 사용자가 지정한 시작 프레임 > Off _isResetPlayAtStartFrame = true; _frameToStart = -1; if (_isNextPlayUnitIsInPrevUnit) { _nextUnitWeight_Overlap = _nextPlayUnit.UnitWeight; if (!_nextPlayUnit.IsLoop) { _nextPlayUnit.ResetPlay(); } } else { _nextPlayUnit.ResetPlay(); } }
/// <summary> /// Play the animation /// </summary> /// <param name="animClipName">Name of the Animation Clip</param> /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param> /// <param name="blendMethod">How it is blended with the animation of the lower layers</param> /// <param name="playOption">How to stop which animations</param> /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param> /// <returns>Animation data to be played. If it fails, null is returned.</returns> public apAnimPlayData Play(apAnimPlayData playData, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false, bool isDebugMsg = true) { if (playData == null) { if (isDebugMsg) { Debug.LogError("Play Failed : Unknown AnimPlayData"); } return(null); } if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX) { if (isDebugMsg) { Debug.LogError("Play Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX); } return(null); } apAnimPlayQueue playQueue = _animPlayQueues[layer]; apAnimPlayUnit resultPlayUnit = playQueue.Play(playData, blendMethod, 0.0f, isAutoEndIfNotloop); if (resultPlayUnit == null) { return(null); } if (playOption == PLAY_OPTION.StopAllLayers) { //다른 레이어를 모두 정지시킨다. for (int i = 0; i < _animPlayQueues.Count; i++) { if (i == layer) { continue; } _animPlayQueues[i].StopAll(0.0f); } } RefreshPlayOrders(); return(playData); }
//---------------------------------------------------------------------------------- //Queue에서 재생하고자 하는 AnimPlayUnit이 실행 중인지 확인하는 함수. public bool IsAlreadyAnimUnitPlayed(apAnimPlayUnit playUnit) { //Debug.LogError("TODO : IsArleadyAnimUnitPlayed"); if (playUnit == null) { return(false); } if (_animPlayUnits.Contains(playUnit)) { if (playUnit.PlayStatus == apAnimPlayUnit.PLAY_STATUS.Play && playUnit.UnitWeight > 0.001f) { return(true); } } return(false); }
public void PlayNew(apAnimPlayUnit nextPlayUnit, float tBlend) { //_tNextPlayStart = tNextPlay;//<<이게 필요한가? _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.New; _nextPlayUnit = nextPlayUnit; _nextPlayUnit._ownerRequest = this; _prevWaitingPlayUnit = null; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = _tBlend; _tActiveMiddle = _tBlend * 0.5f; _status = STATUS.Active; //<<바로 시작 _isNextPlayUnitIsInPrevUnit = false; for (int i = 0; i < _prevPlayUnits.Count; i++) { if (nextPlayUnit == _prevPlayUnits[i]) { _isNextPlayUnitIsInPrevUnit = true; break; } } _nextUnitWeight_Overlap = 1.0f; if (_isNextPlayUnitIsInPrevUnit) { _nextUnitWeight_Overlap = _nextPlayUnit.UnitWeight; } }
public void PlayQueued(apAnimPlayUnit nextPlayUnit, apAnimPlayUnit prevLastPlayUnit, float tBlend) { //_tNextPlayStart = -1;//Queued 타입은 플레이 시간을 받지 않는다. _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.Queued; _nextPlayUnit = nextPlayUnit; _nextPlayUnit._ownerRequest = this; _prevWaitingPlayUnit = prevLastPlayUnit; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = -1.0f; _tActiveEnd = -1.0f; //<<알 수 없다. _tActiveMiddle = -1.0f; _status = STATUS.Ready; //<<일단 대기 _isNextPlayUnitIsInPrevUnit = false; for (int i = 0; i < _prevPlayUnits.Count; i++) { if (nextPlayUnit == _prevPlayUnits[i]) { _isNextPlayUnitIsInPrevUnit = true; break; } } _nextUnitWeight_Overlap = 1.0f; if (_isNextPlayUnitIsInPrevUnit) { _nextUnitWeight_Overlap = _nextPlayUnit.UnitWeight; } }
//Request의 AdaptWeightToPlayUnits에서 호출하는 함수 public void SetRequestWeightToPlayUnits(apAnimPlayRequest request, float prevUnitWeight, float nextUnitWeight, float requestWeight) { //TODO. AdaptWeightToPlayUnits 함수의 내용을 적자 //단, Prev 지점 확실히 해야함 //Debug.LogError("TODO : SetRequestWeightToPlayUnits"); if (request._nextPlayUnit != null) { //Weight가 적용되는 방식 1) To Next request._nextPlayUnit.AddWeight(nextUnitWeight, requestWeight); } //이전 유닛에 대해서 Weight 지정 apAnimPlayUnit playUnit = null; //테스트 코드 : 뒤에서부터 체크해서 "유효한" 한개의 PrevUnit만 Weight를 적용 if (request._prevPlayUnitKeys.Count > 0) { for (int i = request._prevPlayUnitKeys.Count - 1; i >= 0; i--) { playUnit = GetPlayUnitByLinkKey(request._prevPlayUnitKeys[i]); //prevUnitWeight 총 합이 1이 되도록 분할한다. if (playUnit != null) { //Weight가 적용되는 방식 2) To Prev playUnit.AddWeight(prevUnitWeight, requestWeight); break; } } } //Prev에 있었지만 다음 Request로 인해 연결이 끊겨버린 //Next Chained에 해당하는 AnimPlayUnit에 대해서도 Weight를 지정해주자 SetRequestWeightToNextChained(request, prevUnitWeight, requestWeight); }
/// <summary> /// Wait for the previous animation to finish, then play it. /// (If the previously playing animation is a loop animation, it will not be executed.) /// </summary> /// <param name="animClipName">Name of the Animation Clip</param> /// <param name="layer">The layer to which the animation is applied. From 0 to 20</param> /// <param name="blendMethod">How it is blended with the animation of the lower layers</param> /// <param name="isAutoEndIfNotloop">If True, animation that does not play repeatedly is automatically terminated.</param> /// <returns>Animation data to be played. If it fails, null is returned.</returns> public apAnimPlayData PlayQueued(apAnimPlayData playData, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop = false) { if (playData == null) { Debug.LogError("PlayQueued Failed : Unknown AnimPlayData"); return(null); } if (layer < MIN_LAYER_INDEX || layer > MAX_LAYER_INDEX) { Debug.LogError("PlayQueued Failed : Layer " + layer + " is invalid. Layer must be between " + MIN_LAYER_INDEX + " ~ " + MAX_LAYER_INDEX); return(null); } apAnimPlayQueue playQueue = _animPlayQueues[layer]; apAnimPlayUnit resultPlayUnit = playQueue.PlayQueued(playData, blendMethod, 0.0f, isAutoEndIfNotloop); if (resultPlayUnit == null) { return(null); } //if (playOption == PLAY_OPTION.StopAllLayers) //{ // //다른 레이어를 모두 정지시킨다. - 단, 딜레이를 준다. // for (int i = 0; i < _animPlayQueues.Count; i++) // { // if (i == layer) // { continue; } // _animPlayQueues[i].StopAll(delayTime); // } //} RefreshPlayOrders(); return(playData); }
private apAnimPlayUnit MakePlayUnit(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop) { //새로 만들고 //그 전에.. //재생중인 PlayUnit이 있으면 그걸 사용하자 //레이어는 같아야 한다. apAnimPlayUnit existPlayUnit = null; for (int i = 0; i < _animPlayUnits.Count; i++) { if (_animPlayUnits[i]._linkedAnimClip == playData._linkedAnimClip && _animPlayUnits[i].IsUpdatable ) { existPlayUnit = _animPlayUnits[i]; break; } } if (existPlayUnit != null) { //Debug.Log("아직 재생중인 PlayUnit을 다시 재생하는 요청이 왔다. [" + existPlayUnit._linkedAnimClip._name + "]"); existPlayUnit.SetSubOption(blendMethod, isAutoEndIfNotloop); _nPlayedUnit = _animPlayUnits.Count; return(existPlayUnit); } apAnimPlayUnit newPlayUnit = new apAnimPlayUnit(this); newPlayUnit.SetAnimClip(playData, _layer, blendMethod, isAutoEndIfNotloop, false); //리스트에 넣자 _animPlayUnits.Add(newPlayUnit); _nPlayedUnit = _animPlayUnits.Count; return(newPlayUnit); }
public TimelineClipData( #if UNITY_2017_1_OR_NEWER TimelineClip timelineClip, #endif apAnimClip animClip, apOptRootUnit linkedRootUnit) { #if UNITY_2017_1_OR_NEWER _timelineClip = timelineClip; _clipAsset = timelineClip.animationClip; #endif _animClip = animClip; _linkedRootUnit = linkedRootUnit; _isCalculated = false; _isCalculatedPrev = false; _isPlaying = false; //Mecanim용 PlayUnit을 만든다. _playUnit = new apAnimPlayUnit(null, -1, -1); _playUnit.SetMecanimPlayUnit(); ReadyToUpdate(); Unlink(); }
//---------------------------------------------------- // 재생/정지 요청 함수들 //---------------------------------------------------- /// <summary> /// AnimClip을 PlayUnit에 담아서 재생한다. /// Queue에 저장된 모든 클립은 무시되며 블렌드되지 않는다. /// </summary> /// <param name="blendMethod"></param> /// <param name="isAutoEndIfNotloop">True이면 Clip의 재생 후 자동으로 종료한다. (Loop일 경우 무시됨)</param> public apAnimPlayUnit Play(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true) { //Request를 생성한다. apAnimPlayRequest request = PopRequest(); request.SetCurrentPlayedUnits(this, _animPlayUnits); apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop); //newPlayUnit.Play(); //Play 명령을 준다. request.PlayNew(newPlayUnit, blendTime); #region [미사용 코드] //TODO : 이 AnimClip을 CalculatedParam에 연결해야한다. //Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다"); ////플레이 유닛은 플레이 시작 ////나머지는 End로 만든다. //for (int i = 0; i < _animPlayUnits.Count; i++) //{ // if (newPlayUnit != _animPlayUnits[i]) // { // _animPlayUnits[i].SetEnd(); // } //} #endregion _nPlayedUnit = _animPlayUnits.Count; //Debug.Log("Next Play Units [" + _nPlayedUnit + "]"); return(newPlayUnit); }
public void Stop(float tBlend) { //_tNextPlayStart = -1; _tBlend = tBlend; _tLive = 0.0f; _isNextUnitPlayed = false; _isNextUnitFrameReset = false; _requestType = REQUEST_TYPE.Stop; _nextPlayUnit = null; _prevWaitingPlayUnit = null; _requestWeight = 0.0f; _nextUnitWeight = 1.0f; _prevUnitWeight = 1.0f; _tActiveStart = 0.0f; _tActiveEnd = _tBlend; _tActiveMiddle = _tBlend * 0.5f; _status = STATUS.Active; //<<바로 시작 _isNextPlayUnitIsInPrevUnit = false; }
public void Update(float tDelta) { //현재 재생중인 유닛이 있다면 시작 _isUpdated = false; if (_nPlayedUnit > 0) { //업데이트.. //Debug.Log("Update Queue"); for (int i = 0; i < _nPlayedUnit; i++) { _tmpCurPlayUnit = _animPlayUnits[i]; _tmpCurPlayUnit.SetWeight(0.0f, false); //<<일단 Weight를 0으로 둔다. _tmpCurPlayUnit.Update(tDelta); _isUpdated = true; if (_tmpCurPlayUnit.IsRemovable) { //TODO : 이 객체와 연결된 CalculatedParam에 AnimClip이 사라졌음을 알려야한다. //Debug.LogError("TODO : 이 객체와 연결된 CalculatedParam에 AnimClip이 사라졌음을 알려야한다"); _tmpCurPlayUnit.SetWeight(0.0f, true); _isAnyUnitChanged = true; } } _isInitPlayUnit = false; } else { //만약 _nPlayedUnit = 0인 상태로 한번도 초기화를 안했다면.. if (!_isInitPlayUnit) { _isInitPlayUnit = true; } } apAnimPlayRequest curRequest = null; if (_requests_Live.Count > 0) { //Debug.Log("----------------- Request Update[" + _requests_Live.Count + "] ---------------------"); //Request를 업데이트하고 //각 Request별로 연관된 PlayUnit의 Weight를 지정해주자 for (int iCur = 0; iCur < _requests_Live.Count; iCur++) { curRequest = _requests_Live[iCur]; if (curRequest.IsEnded) { continue; } curRequest.Update(tDelta, iCur); } //Debug.Log("------------------------------------------------------"); } //이제 Weight를 지정해준다. //1. Request를 자체적으로 업데이트하여 UnitWeight를 계산한다. //업데이트 방식 //- 앞에서부터 설정한다. //- 일단 Weight를 1로 설정 //- 이전 Prev 시간 영역 (-Start ~ +End)을 비교하여 겹치는 시간이 BlendTime보다 긴지 짧은지 판별한다. //- 겹친 시간계산하고, 현재의 ITP를 구한다. //- 현재 Request에 ITP를 곱하고, 이전 "모든 Weight"에 (1-ITP)를 곱한다. // 겹친 시간 : [ tStart <- tCur ] + [ tCur -> tEnd ] //2. 현재 시점에서 중복된 Request들 간의 RequestWeight를 계산한다. //3. Request를 돌면서 Prev/Next에 대해서 Weight를 지정해준다. float prevCurrent2EndTime = -1.0f; float tmpOverlapTime = 0.0f; float tmpOverlapITP = 0.0f; bool isAnyRequestChanged = false; for (int iCur = 0; iCur < _requests_Live.Count; iCur++) { curRequest = _requests_Live[iCur]; //Ready => Weight : 1 //End => Weight : 0 if (!curRequest.IsLive) { if (curRequest.IsEnded) { curRequest.SetRequestWeight(0.0f); isAnyRequestChanged = true; } else { curRequest.SetRequestWeight(1.0f); } continue; } curRequest.SetRequestWeight(1.0f); //일단 1을 넣는다. if (iCur == 0) { prevCurrent2EndTime = curRequest.Current2EndTime; continue; } //BlendTime보다 짧다면 Overlap 시간이 짧아진다. //CurTime을 기준으로 [tStart <- tCur] 시간과 [tCur -> tEnd] 시간을 나누어 더하여 계산하는데, //[tCur -> tEnd] 시간은 이전 Request와 길이를 비교한다. tmpOverlapTime = curRequest.Current2StartTime + Mathf.Min(prevCurrent2EndTime, curRequest.Current2EndTime); if (tmpOverlapTime < 0.001f) { tmpOverlapITP = 1.0f; } else { tmpOverlapITP = curRequest.Current2StartTime / tmpOverlapTime; } for (int iPrev = 0; iPrev < iCur; iPrev++) { _requests_Live[iPrev].MultiplyRequestWeight(1.0f - tmpOverlapITP); } curRequest.MultiplyRequestWeight(tmpOverlapITP); prevCurrent2EndTime = curRequest.Current2EndTime; } //마지막으로 다시 돌면서 Request에서 계산된 UnitWeight * RequestWeight를 넣어서 완성 float totalRequestWeight = 0.0f; int nLiveRequest = 0; for (int iCur = 0; iCur < _requests_Live.Count; iCur++) { curRequest = _requests_Live[iCur]; //curRequest.AdaptWeightToPlayUnits(); if (!curRequest.IsLive) { continue; } curRequest.AdaptWeightToPlayUnits(); totalRequestWeight += curRequest.RequestWeight; nLiveRequest++; } if (nLiveRequest > 0 && totalRequestWeight > 0.0f) { if (totalRequestWeight > 1.0f) { totalRequestWeight = 1.0f; } //추가 //전체 PlayUnit의 Weight가 totalRequestWeight 또는 1을 넘어가거나 모자르다면 거기에 맞게 Normalize한다. float totalPlayUnitWeight = 0.0f; int nPlayUnit = 0; for (int iPlayUnit = 0; iPlayUnit < _animPlayUnits.Count; iPlayUnit++) { totalPlayUnitWeight += _animPlayUnits[iPlayUnit].UnitWeight; if (totalPlayUnitWeight > 0.0f) { nPlayUnit++; } } if (totalPlayUnitWeight > 0.0f && nPlayUnit > 1) { float normalizeWeight = totalRequestWeight / totalPlayUnitWeight; for (int iPlayUnit = 0; iPlayUnit < _animPlayUnits.Count; iPlayUnit++) { _animPlayUnits[iPlayUnit].NormalizeWeight(normalizeWeight); } } } bool isOrderRefreshable = _isAnyUnitChanged || isAnyRequestChanged; //변화값이 있으면 삭제 여부를 판단하자 if (_isAnyUnitChanged) { _animPlayUnits.RemoveAll(delegate(apAnimPlayUnit a) { return(a.IsRemovable); }); _isAnyUnitChanged = false; _nPlayedUnit = _animPlayUnits.Count; _playManager.OnAnyAnimPlayUnitEnded(); } if (isAnyRequestChanged) { //끝난 Request를 Pool에 돌려놓는다. List <apAnimPlayRequest> endedRequests = new List <apAnimPlayRequest>(); for (int i = 0; i < _requests_Live.Count; i++) { if (_requests_Live[i].IsEnded) { endedRequests.Add(_requests_Live[i]); } } for (int i = 0; i < endedRequests.Count; i++) { PushRequest(endedRequests[i]); } } if (isOrderRefreshable) { //Order를 갱신한다. RefreshOrder(); } }
//AnimClip을 PlayUnit에 담아서 재생한다. //Queue에 저장된 클립들이 모두 끝나면 블렌드 없이 바로 실행된다. public apAnimPlayUnit PlayQueued(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true) { //현재 재생되는 플레이 유닛 중에서 "가장 많이 남은 플레이 시간"을 기준으로 타이머를 잡자 //Fade 타임은 없고, 자동 삭제 타이머 + 자동 재생 대기 타이머를 지정 //현재 Queue에 있는 객체가 없다면 Play와 동일하다 //수정 : //이전에는 Queue 조건을 PlayUnit이 재생되는가..로 판별했다. -> 그러면 Stop 도중의 Unit도 Queue로 인식해버림 //이젠 이전에 존재하는 Request가 있는지 확인하고 Chain으로 연결한다. //Chain 연결시에는 연결된 양쪽이 서로를 알고 있어야 한다. //Request가 없는 경우에 한해서 PlayUnit에 연결한다. //마지막 연결이 apAnimPlayRequest lastRequest = null; if (_requests_Live.Count > 0) { //1. Request가 있는 경우/ //Chain을 시도한다. //마지막 Request를 찾는다. (End가 아닌거면 다 됨) for (int i = _requests_Live.Count - 1; i >= 0; i--) { if (_requests_Live[i].Status != apAnimPlayRequest.STATUS.End) { lastRequest = _requests_Live[i]; break; } } //아직 처리중인 마지막 Request가 있을 때 //Request 타입과 해당 AnimPlayUnit에 따라 //1) Chain+Queued을 할지, 2) 그냥 Play를 할 지, 3) 처리를 포기할 지 //결정을 한다. if (lastRequest != null) { int chainType = -1; switch (lastRequest.RequestType) { case apAnimPlayRequest.REQUEST_TYPE.New: case apAnimPlayRequest.REQUEST_TYPE.Queued: { //대기 중이거나 재생 중이다. //1. 같은 PlayUnit이라면 -> Loop 타입이라면 취소, Once 타입이라면 Chain 처리 //2. Loop 타입이라면 -> 그냥 Play //3. 그외 -> Chain 처리 if (lastRequest._nextPlayUnit._linkedAnimClip == playData._linkedAnimClip) { //1. 같은 PlayUnit이다. if (lastRequest._nextPlayUnit.IsLoop) { //Loop 타입이라면 취소 chainType = QUEUE_CHAIN__3_SKIP; } else { //Once 타입이라면 Chain 처리 //chainType = QUEUE_CHAIN__1_LINK_CHAIN; //변경 : 이미 같은 애니메이션에 대하여 New, Queued가 등록된 요청이다. //처리하지 않는걸로 하자 chainType = QUEUE_CHAIN__3_SKIP; } } else if (lastRequest._nextPlayUnit.IsLoop) { //2. 마지막 PlayUnit이 Loop 타입이다. // -> 그냥 Play chainType = QUEUE_CHAIN__2_PLAY; } else { //3. 그외 -> Chain 처리 chainType = QUEUE_CHAIN__1_LINK_CHAIN; } } break; case apAnimPlayRequest.REQUEST_TYPE.Stop: { //정지 요청이 있다. //Chain 없이 Play를 시도한다. (Stop 이후이므로) chainType = QUEUE_CHAIN__2_PLAY; } break; } switch (chainType) { case QUEUE_CHAIN__1_LINK_CHAIN: { //Last Unit과 Chain으로 연결한다. } break; case QUEUE_CHAIN__2_PLAY: //Debug.LogError("Play Queued -> 2) Play"); return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop)); case QUEUE_CHAIN__3_SKIP: //Debug.LogError("Play Queued -> 3) Skip"); return(null); } } } apAnimPlayUnit lastPlayUnit = null; if (lastRequest != null) { //Chain 처리가 되었다면 //-> LastPlayUnit은 Chain된 Request의 PlayUnit으로 삼는다. lastPlayUnit = lastRequest._nextPlayUnit; } else { //Chain 처리가 안되었을 때 //마지막 PlayUnit을 비교하여 처리한다. //1. 마지막 PlayUnit이 없는 경우 -> 바로 Play //2. 마지막 PlayUnit이 Loop 타입이어서 기다릴 수 없는 경우 -> 바로 Play if (_nPlayedUnit == 0) { //Debug.LogError("현재 남은 PlayUnit이 없으므로 바로 실행 [" + playData._animClipName + "]"); return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop)); } //마지막 PlayUnit을 가져오자 lastPlayUnit = _animPlayUnits[_animPlayUnits.Count - 1]; if (lastPlayUnit.IsLoop) { //만약 마지막 PlayUnit이 Loop라면 => Queued 되지 않는다. 자동으로 [Play]로 바뀜 //Debug.LogError("마지막 PlayUnit [" + lastPlayUnit._linkedAnimClip._name + "] 이 Loop 타입이어서 그냥 무시하고 CrossFade로 실행"); return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop)); } } if (lastPlayUnit != null && lastPlayUnit._linkedAnimClip == playData._linkedAnimClip) { //Debug.LogError("이미 재생중인 애니메이션이다."); return(null); } //Request를 생성한다. apAnimPlayRequest request = PopRequest(); //request.SetCurrentPlayedUnits(this, _animPlayUnits); request.SetCurrentPlayedUnits(this); //현재 플레이 중인 AnimPlayUnit들의 LinkKey를 넣어준다. for (int i = 0; i < _animPlayUnits.Count; i++) { request.AddPrevPlayUnitKeyLink(_animPlayUnits[i].LinkKey, _animPlayUnits[i].UnitWeight); } apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop); newPlayUnit.Pause(); //Play Queued 명령을 준다. request.PlayQueued(newPlayUnit, lastPlayUnit, blendTime); //추가 : Chain 처리를 해주자 if (lastRequest != null) { //if(lastRequest._chainedRequest_Next != null) //{ // Debug.LogError("마지막 Unit을 Chain하려고 했으나 이미 연결되어 있다;;;"); //} //LastRequest.Next <-> Request.Prev lastRequest._chainedRequest_Next = request; request._chainedRequest_Prev = lastRequest; } #region [미사용 코드] 미리 시간을 예상해서 처리하는 것은 문제가 많다. //float maxRemainPlayTime = -1.0f; //float curRemainPlayTime = 0.0f; //bool isAnyOnceAnimClip = false; //for (int i = 0; i < _nPlayedUnit; i++) //{ // _tmpCurPlayUnit = _animPlayUnits[i]; // if(_tmpCurPlayUnit.IsLoop) // { // //하나라도 루프이면 실패다. // //Queue에 넣어도 작동하지 않는다. // //>수정 // //루프는 무시하고 Queue 시간을 잡자 // //만약 Loop를 만나고 Queue가 있다면 그냥 기본값인 0.5초를 Queue 시간으로 쓴다. // //Debug.LogError("PlayQueued Failed : Any Clip has Loop Option. Adding to Queue will be ignored"); // //return null; // continue; // } // isAnyOnceAnimClip = true; // curRemainPlayTime = _tmpCurPlayUnit.GetRemainPlayTime; // if(maxRemainPlayTime < curRemainPlayTime) // { // maxRemainPlayTime = curRemainPlayTime; // } //} //if(!isAnyOnceAnimClip) //{ // maxRemainPlayTime = 0.5f; //} //if(maxRemainPlayTime < 0.0f) //{ // maxRemainPlayTime = 0.0f; //} ////최대 RemainPlayTime 만큼 Delay한다. //// Delay후 신규 플레이 또는 플레이 종료를 한다. ////Fade 시간은 0 //apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop); //newPlayUnit.Play(0.0f, maxRemainPlayTime); ////Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다"); //for (int i = 0; i < _nPlayedUnit; i++) //{ // _tmpCurPlayUnit = _animPlayUnits[i]; // if (newPlayUnit != _tmpCurPlayUnit) // { // _tmpCurPlayUnit.FadeOut(0.0f, maxRemainPlayTime); // } //} #endregion _nPlayedUnit = _animPlayUnits.Count; //Order를 갱신한다. RefreshOrder(); return(newPlayUnit); }
//---------------------------------------------------- // 재생/정지 요청 함수들 //---------------------------------------------------- //AnimClip을 PlayUnit에 담아서 재생한다. //Queue에 저장된 모든 클립은 무시되며 블렌드되지 않는다. public apAnimPlayUnit Play(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true) { //현재 상태에서 실행되지 않은 Queued 애니메이션 재생 요청은 삭제한다. PushAllNoActiveRequests(); //Request를 생성한다. apAnimPlayRequest request = PopRequest(); //request.SetCurrentPlayedUnits(this, _animPlayUnits); request.SetCurrentPlayedUnits(this); //현재 플레이 중인 AnimPlayUnit들의 LinkKey를 넣어준다. //Debug.Log("Add Play Unit Link Key"); for (int i = 0; i < _animPlayUnits.Count; i++) { //Debug.Log(_animPlayUnits[i]._linkedAnimClip._name + " : " + _animPlayUnits[i].LinkKey + " / " + _animPlayUnits[i].PlayStatus); request.AddPrevPlayUnitKeyLink(_animPlayUnits[i].LinkKey, _animPlayUnits[i].UnitWeight); } apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop); //newPlayUnit.Play(); newPlayUnit.Resume(); //Pause가 걸려있으면 풀어주자 //Play 명령을 준다. request.PlayNew(newPlayUnit, blendTime); //이때, 만약 PlayQueued 타입이며 newPlayUnit을 타겟으로 하는게 있으면 처리할 때 무력화시켜야 한다. apAnimPlayRequest overlapQueuedRequest = _requests_Live.Find(delegate(apAnimPlayRequest a) { return(a != request && a.RequestType == apAnimPlayRequest.REQUEST_TYPE.Queued && a._nextPlayUnit == newPlayUnit); }); if (overlapQueuedRequest != null) { //Debug.Log("겹치는 Queue Request를 그냥 바로 삭제"); PushRequest(overlapQueuedRequest); } #region [미사용 코드] //TODO : 이 AnimClip을 CalculatedParam에 연결해야한다. //Debug.LogError("TODO : 이 AnimClip을 CalculatedParam에 연결해야한다"); ////플레이 유닛은 플레이 시작 ////나머지는 End로 만든다. //for (int i = 0; i < _animPlayUnits.Count; i++) //{ // if (newPlayUnit != _animPlayUnits[i]) // { // _animPlayUnits[i].SetEnd(); // } //} #endregion _nPlayedUnit = _animPlayUnits.Count; //Order를 갱신한다. RefreshOrder(); //Debug.Log("Next Play Units [" + _nPlayedUnit + "]"); return(newPlayUnit); }
// Request -> Queue 요청 //Request의 애니메이션의 Fade가 끝나면서 이전에 플레이되던 AnimPlayUnit을 종료하는 함수 //AnimPlayRequest가 호출한다. //직접 SetEnd하는 것이 아니라 Queue에서 확인하여 처리한다. public void SetEndByRequest(apAnimPlayRequest request) { //Debug.Log("----- Check Set End -------------"); bool isStopRequest = request.RequestType == apAnimPlayRequest.REQUEST_TYPE.Stop; bool isLastRequest = false; if (_requests_Live.Count > 0) { int iLastLiveRequest = -1; //Live 중의 마지막 Request를 찾는다. //대기중인 것은 의미 없음 for (int i = _requests_Live.Count - 1; i >= 0; i--) { if (_requests_Live[i].IsLive || _requests_Live[i].IsEnded) { iLastLiveRequest = i; break; } } //Debug.Log("iLastRequest : " + iLastLiveRequest); if (iLastLiveRequest >= 0) { isLastRequest = (_requests_Live[iLastLiveRequest] == request); } } //Debug.Log("Is Stop Request [" + isStopRequest + "] / Is Last Request [" + isLastRequest + "]"); //TODO //이 상태에서 //A -> Play B -> PlayQueued A -> A를 바로 호출시 //[A -> Play B]를 진행하면서 A -> 0 -> End/Ready로 만들고 싶지만 //[PlayQueued A]를 호출하면서 A의 LinkKey가 바뀌면서 [Play B]에서 Weight를 조절할 수 없게 되었다... //if (isStopRequest || isLastRequest) //그냥 해볼까 { //Debug.LogError("!!!!! Set End !!!!!"); //이전의 모든 Request를 모두 End한다. apAnimPlayUnit playUnit = null; for (int i = 0; i < request._prevPlayUnitKeys.Count; i++) { playUnit = GetPlayUnitByLinkKey(request._prevPlayUnitKeys[i]); if (playUnit != null) { //Debug.Log("Set End - " + playUnit._linkedAnimClip._name + " / " + playUnit.LinkKey); if (isStopRequest || isLastRequest) { playUnit.SetEnd(); } else { playUnit.SetWeightZero(); } } //else //{ // Debug.LogError("Is Null Unit [" + request._prevPlayUnitKeys[i] + "]"); //} } } //추가 //만약 Chained 된 상태이고 //Next Chained된 Request가 아직 Ready라면 //SetWeightZero를 해야한다. //이건 반복해서 처리한다. //AdaptWeight도 마찬가지로 처리 SetWeightZeroToNextChained(request); //Debug.Break(); }
public void OnAnimPlayUnitEnded(apAnimPlayUnit playUnit) { _playManager.OnAnimPlayUnitEnded(playUnit, this); }