// [런타임에서] Portrait를 연결하고, Portrait를 검색하여 animPlayData를 세팅한다. // 다른 Link가 모두 끝난뒤에 호출하자 /// <summary> /// Connect to Portrait and initialize it for runtime processing. /// </summary> /// <param name="portrait"></param> public void LinkPortrait(apPortrait portrait) { _portrait = portrait; InitAndLink(); if (_animPlayDataList == null) { _animPlayDataList = new List <apAnimPlayData>(); } apAnimPlayData animPlayData = null; for (int i = 0; i < _animPlayDataList.Count; i++) { animPlayData = _animPlayDataList[i]; animPlayData._isValid = false; //일단 유효성 초기화 (나중에 값 넣으면 자동으로 true) apAnimClip animClip = _portrait.GetAnimClip(animPlayData._animClipID); apOptRootUnit rootUnit = _portrait._optRootUnitList.Find(delegate(apOptRootUnit a) { if (a._rootOptTransform != null) { if (a._rootOptTransform._meshGroupUniqueID == animPlayData._meshGroupID) { return(true); } } return(false); }); if (animClip != null && rootUnit != null) { animPlayData.Link(animClip, rootUnit); //추가 : 여기서 ControlParamResult를 미리 만들어서 이후에 AnimClip이 미리 만들수 있게 해주자 animClip.MakeAndLinkControlParamResults(); } } //추가 : 메카님 연동 _mecanim.LinkPortrait(portrait, this); if (portrait._isUsingMecanim && portrait._animator != null) { _isMecanim = true; } else { _isMecanim = false; } }
//추가 : AnimPlayData로 PlayQueued를 바로 실행하는 함수가 나오면서, 이름으로 검색하는 건 오버로드로 뺌 public apAnimPlayData PlayQueued(string animClipName, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, bool isAutoEndIfNotloop = false) { apAnimPlayData playData = GetAnimPlayData_Opt(animClipName); if (playData == null) { Debug.LogError("PlayQueued Failed : No AnimClip [" + animClipName + "]"); return(null); } return(PlayQueued(playData, layer, blendMethod, isAutoEndIfNotloop)); }
public bool IsPlaying(string animClipName) { apAnimPlayData animPlayData = GetAnimPlayData_Opt(animClipName); if (animPlayData == null) { Debug.LogError("No AnimCip : " + animClipName); return(false); } return(animPlayData._linkedAnimClip.IsPlaying_Opt); }
//추가 : AnimPlayData로 PlayQueued를 바로 실행하는 함수가 나오면서, 이름으로 검색하는 건 오버로드로 뺌 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); } return(CrossFade(playData, layer, blendMethod, fadeTime, playOption, isAutoEndIfNotloop)); }
//애니메이션 속도 설정 public void SetAnimSpeed(string animClipName, float speed) { apAnimPlayData animPlayData = GetAnimPlayData_Opt(animClipName); if (animPlayData == null) { Debug.LogError("No AnimCip : " + animClipName); return; } animPlayData._linkedAnimClip._speedRatio = speed; }
public apAnimPlayData CrossFadeQueuedAt(string animClipName, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, float fadeTime, bool isAutoEndIfNotloop = false) { apAnimPlayData playData = GetAnimPlayData_Opt(animClipName); if (playData == null) { Debug.LogError("CrossFadeQueuedAt Failed : No AnimClip [" + animClipName + "]"); return(null); } return(CrossFadeQueuedAt(playData, frame, layer, blendMethod, fadeTime, isAutoEndIfNotloop)); }
public apAnimPlayData.AnimationPlaybackStatus GetAnimationPlaybackStatus(string animClipName) { apAnimPlayData animPlayData = GetAnimPlayData_Opt(animClipName); if (animPlayData == null) { Debug.LogError("No AnimCip : " + animClipName); return(apAnimPlayData.AnimationPlaybackStatus.None); } return(animPlayData.PlaybackStatus); }
/// <summary> /// [Please do not use it] Set AnimClip to get data /// </summary> /// <param name="playData"></param> /// <param name="layer"></param> /// <param name="blendMethod"></param> /// <param name="isAutoEndIfNotLoop"></param> /// <param name="isEditor"></param> public void SetAnimClip(apAnimPlayData playData, int layer, BLEND_METHOD blendMethod, bool isAutoEndIfNotLoop, bool isEditor) { _linkedAnimClip = playData._linkedAnimClip; _targetRootUnit = playData._linkedOptRootUnit; //추가 if (_linkedAnimClip._parentPlayUnit != null && _linkedAnimClip._parentPlayUnit != this) { //이미 다른 PlayUnit이 사용중이었다면.. _linkedAnimClip._parentPlayUnit.SetEnd(); //_linkedAnimClip._parentPlayUnit._linkedAnimClip = null; } _linkedAnimClip._parentPlayUnit = this; _layer = layer; _isLoop = _linkedAnimClip.IsLoop; _isAutoEnd = isAutoEndIfNotLoop; if (_isLoop) { _isAutoEnd = false; //<<Loop일때 AutoEnd는 불가능하다 } _blendMethod = blendMethod; _isPause = false; _playStatus = PLAY_STATUS.Ready; _isPlayStartEventCalled = false; _isEndEventCalled = false; //_speedRatio = 1.0f; _isFirstFrame = true; _nextPlayStatus = _playStatus; //추가 1.14 _isResetFrameOnReadyStatus = true; if (isEditor) { _linkedAnimClip.Stop_Editor(false); //Stop은 하되 업데이트는 하지 않는다. (false) } else { _linkedAnimClip.Stop_Opt(false); } _unitWeight = 0.0f; _totalRequestWeights = 0.0f; }
/// <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 apAnimPlayData PlayAt(string animClipName, int frame, int layer, apAnimPlayUnit.BLEND_METHOD blendMethod, PLAY_OPTION playOption = PLAY_OPTION.StopSameLayer, bool isAutoEndIfNotloop = false, bool isDebugMsg = true) { apAnimPlayData playData = GetAnimPlayData_Opt(animClipName); if (playData == null) { if (isDebugMsg) { Debug.LogError("PlayAt Failed : No AnimClip [" + animClipName + "]"); } return(null); } return(PlayAt(playData, frame, layer, blendMethod, playOption, isAutoEndIfNotloop, isDebugMsg)); }
/// <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); }
/// <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); }
/// <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); }
//---------------------------------------------------- // 재생/정지 요청 함수들 //---------------------------------------------------- /// <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 bool SetTrack(string trackName, int layerIndex, apAnimPlayUnit.BLEND_METHOD blendMethod, apPortrait portrait, apAnimPlayManager animPlayManager) { #if UNITY_2017_1_OR_NEWER //PlayableDirector playDirector = _parentTrackSet._playableDirector; PlayableAsset playAsset = _parentTrackSet._playableAsset; #endif _trackName = trackName; _layerIndex = layerIndex; #if UNITY_2017_1_OR_NEWER _layerOrder = _layerIndex; #endif _blendMethod = blendMethod; if (string.IsNullOrEmpty(_trackName)) { //이름이 빈칸이거나 null이다. return(false); } _clipData = new List <TimelineClipData>(); #if UNITY_2017_1_OR_NEWER _timelineClips = new List <TimelineClip>(); _clipDataByTrack = new Dictionary <TimelineClip, TimelineClipData>(); #endif _nClipData = 0; //연결을 하자 bool isFind = false; #if UNITY_2017_1_OR_NEWER _animationTrack = null; #endif //그 전에 AnimClip <-> AnimationClipAsset을 서로 연결해야한다. apAnimClip curAnimClip = null; AnimationClip curAnimationClipAsset = null; Dictionary <AnimationClip, apAnimClip> animClipAsset2AnimClip = new Dictionary <AnimationClip, apAnimClip>(); for (int i = 0; i < portrait._animClips.Count; i++) { curAnimClip = portrait._animClips[i]; if (curAnimClip == null) { continue; } curAnimationClipAsset = curAnimClip._animationClipForMecanim; if (curAnimationClipAsset == null) { continue; } if (animClipAsset2AnimClip.ContainsKey(curAnimationClipAsset)) { continue; } animClipAsset2AnimClip.Add(curAnimationClipAsset, curAnimClip); } //apAnimClip에 해당하는 apOptRootUnit을 알아야 한다. //apAnimPlayData에 그 정보가 저장되어 있으니 참조하자 apAnimPlayData curPlayData = null; Dictionary <apAnimClip, apOptRootUnit> animClip2RootUnit = new Dictionary <apAnimClip, apOptRootUnit>(); for (int i = 0; i < animPlayManager._animPlayDataList.Count; i++) { curPlayData = animPlayManager._animPlayDataList[i]; if (curPlayData == null) { continue; } if (curPlayData._linkedAnimClip == null || curPlayData._linkedOptRootUnit == null) { continue; } if (animClip2RootUnit.ContainsKey(curPlayData._linkedAnimClip)) { continue; } //apAnimClip -> apOptRootUnit으로 연결 데이터 추가 animClip2RootUnit.Add(curPlayData._linkedAnimClip, curPlayData._linkedOptRootUnit); } #if UNITY_2017_1_OR_NEWER foreach (PlayableBinding playableBinding in playAsset.outputs) { #endif #if UNITY_2018_1_OR_NEWER bool isAnimTrack = playableBinding.sourceObject != null && playableBinding.sourceObject is AnimationTrack; #elif UNITY_2017_1_OR_NEWER bool isAnimTrack = playableBinding.streamType == DataStreamType.Animation; #endif //if (playableBinding.streamType != DataStreamType.Animation) #if UNITY_2017_1_OR_NEWER if (!isAnimTrack) { //애니메이션 타입이 아니라면 패스 continue; } AnimationTrack animTrack = playableBinding.sourceObject as AnimationTrack; if (animTrack == null) { continue; } //if(animTrack.isEmpty) //{ // //클립이 아예 없는데용 // continue; //} if (!animTrack.name.Equals(_trackName)) { //이름이 다르다. continue; } if (animTrack.isEmpty) { //클립이 아예 없는데용 //continue; Debug.LogWarning("AnyPortrait : ( Warning ) No Clip in the requested track. [ " + trackName + " ]"); //일단 처리는 하자 } //이름도 같고 유효한 트랙을 찾았다! isFind = true; _animationTrack = animTrack; AnimationClip animClipInTrack = null; apAnimClip targetAnimClip = null; apOptRootUnit targetRootUnit = null; foreach (TimelineClip timelineClip in _animationTrack.GetClips()) { //Track의 TimelineClip 중에서 유효한 AnimationClip만 선택한다. animClipInTrack = timelineClip.animationClip; if (!animClipAsset2AnimClip.ContainsKey(animClipInTrack)) { //유효한 AnimationClip이 아니다. continue; } targetAnimClip = animClipAsset2AnimClip[animClipInTrack]; if (targetAnimClip == null) { //animClip이 비어있다. continue; } if (!animClip2RootUnit.ContainsKey(targetAnimClip)) { //apAnimClip -> apOptRootUnit을 조회할 수 없다. continue; } targetRootUnit = animClip2RootUnit[targetAnimClip]; if (targetRootUnit == null) { //RootUnit이 null이다. continue; } TimelineClipData newClipData = new TimelineClipData(timelineClip, targetAnimClip, targetRootUnit); _clipData.Add(newClipData); _timelineClips.Add(timelineClip); _clipDataByTrack.Add(timelineClip, newClipData); //_clipDataByAnimClip.Add(targetAnimClip, newClipData); _nClipData++; } //Debug.Log("Track [" + trackName + "] Added"); //<<추가>> 시간대에 따라서 Sort _clipData.Sort(delegate(TimelineClipData a, TimelineClipData b) { return((int)((a._timelineClip.start - b._timelineClip.start) * 100.0)); }); if (isFind) { break; } } #endif if (!isFind) { Debug.LogError("AnyPortrait : No track with the requested name. [" + trackName + "]"); } return(isFind); }
/// <summary> /// [Please do not use it] Set AnimClip to get data /// </summary> /// <param name="playData"></param> /// <param name="layer"></param> /// <param name="blendMethod"></param> /// <param name="isAutoEndIfNotLoop"></param> /// <param name="isEditor"></param> public void SetAnimClip(apAnimPlayData playData, int layer, BLEND_METHOD blendMethod, bool isAutoEndIfNotLoop, bool isEditor) { _linkedAnimClip = playData._linkedAnimClip; _targetRootUnit = playData._linkedOptRootUnit; //추가 if (_linkedAnimClip._parentPlayUnit != null && _linkedAnimClip._parentPlayUnit != this) { //이미 다른 PlayUnit이 사용중이었다면.. _linkedAnimClip._parentPlayUnit.SetEnd(); //_linkedAnimClip._parentPlayUnit._linkedAnimClip = null; } _linkedAnimClip._parentPlayUnit = this; _layer = layer; _isLoop = _linkedAnimClip.IsLoop; _isAutoEnd = isAutoEndIfNotLoop; if (_isLoop) { _isAutoEnd = false; //<<Loop일때 AutoEnd는 불가능하다 } _blendMethod = blendMethod; _isPause = false; _playStatus = PLAY_STATUS.Ready; _isPlayStartEventCalled = false; _isEndEventCalled = false; //_fadeInTime = 0.0f; //_fadeOutTime = 0.0f; //_delayToPlayTime = 0.0f; //_delayToEndTime = 0.0f; _speedRatio = 1.0f; _isFirstFrame = true; _nextPlayStatus = _playStatus; if (isEditor) { _linkedAnimClip.Stop_Editor(false); //Stop은 하되 업데이트는 하지 않는다. (false) } else { _linkedAnimClip.Stop_Opt(false); } //_tAnimClipLength = _linkedAnimClip.TimeLength; _unitWeight = 0.0f; _isWeightCalculated = false; _totalRequestWeights = 0.0f; //_prevUnitWeight = 0.0f; //_debugWeight1 = 0.0f; //_debugWeight2 = 0.0f; //_debugWeight3 = 0.0f; //_isDelayIn = false; //_isDelayOut = false; //_tDelay = 0.0f; }
public void LinkPortrait(apPortrait portrait, apAnimPlayManager animPlayManager) { _portrait = portrait; _animPlayManager = animPlayManager; _animator = _portrait._animator; _animController = null; _isValidAnimator = false; if (_animator == null) { //Debug.LogError("No Animator"); return; } _animController = _animator.runtimeAnimatorController; if (_animController == null) { Debug.LogError("AnyPortrait : No RuntimeAnimatorController on Animator"); return; } _isValidAnimator = true; _layers.Clear(); _clipData.Clear(); _clipDataByAsset.Clear(); _clipDataByAnimClip.Clear(); //레이어 정보를 담자 _nLayers = _animator.layerCount; //저장된 AnimClip 체크를 위해서 리스트를 만들자 //유효하지 않은 AnimClip은 제외해야한다. List <AnimationClip> allClips = new List <AnimationClip>(); List <AnimationClip> validClips = new List <AnimationClip>(); for (int iLayer = 0; iLayer < _animator.layerCount; iLayer++) { MecanimLayer newLayer = new MecanimLayer(); newLayer._index = iLayer; newLayer._blendType = apAnimPlayUnit.BLEND_METHOD.Interpolation; if (iLayer < portrait._animatorLayerBakedData.Count) { if (portrait._animatorLayerBakedData[iLayer]._blendType == apAnimMecanimData_Layer.MecanimLayerBlendType.Additive) { //미리 설정된 데이터가 있고, Additive라면 Additive로 설정 newLayer._blendType = apAnimPlayUnit.BLEND_METHOD.Additive; } } _layers.Add(newLayer); } //어떤 AnimClip이 있는지 체크하자 for (int i = 0; i < _animController.animationClips.Length; i++) { if (!allClips.Contains(_animController.animationClips[i])) { allClips.Add(_animController.animationClips[i]); } } //apAnimClip <-> AnimationClip Asset을 서로 연결하자 _animClip2Asset.Clear(); _asset2AnimClip.Clear(); //Debug.Log("animPlayManager._animPlayDataList Count : " + animPlayManager._animPlayDataList.Count); for (int i = 0; i < animPlayManager._animPlayDataList.Count; i++) { apAnimPlayData playData = animPlayManager._animPlayDataList[i]; //Debug.Log("[" + i + "] : " + playData._animClipName); apAnimClip animClip = playData._linkedAnimClip; if (animClip == null) { //Debug.LogError("[" + i + "] : " + playData._animClipName + " >> Linked Anim Clip is Null"); continue; } AnimationClip assetClip = animClip._animationClipForMecanim; if (assetClip != null) { _animClip2Asset.Add(animClip, assetClip); _asset2AnimClip.Add(assetClip, animClip); MecanimClipData newClipData = new MecanimClipData(assetClip, animClip, playData._linkedOptRootUnit); _clipData.Add(newClipData); _clipDataByAsset.Add(assetClip, newClipData); _clipDataByAnimClip.Add(animClip, newClipData); if (!validClips.Contains(assetClip)) { validClips.Add(assetClip); } //Debug.Log("[" + i + "] : " + playData._animClipName + " >> " + assetClip.name); } else { if (Application.isPlaying) { Debug.LogError("[" + i + "] : " + playData._animClipName + " >> AnimAsset is Null"); } } } _nClipData = _clipData.Count; //여기서 유효성 체크 //(유효성 체크는 Application 실행 시에) //if (Application.isPlaying) { for (int i = 0; i < allClips.Count; i++) { if (!validClips.Contains(allClips[i])) { if (allClips[i] != _portrait._emptyAnimClipForMecanim) { //유효하지 않은 Clip이 발견되었다. Debug.LogError("AnyPortrait : ( Caution! ) Contains an invalid AnimationClip. An error may occur when playing. [" + allClips[i].name + " < " + _portrait.gameObject.name + "]"); Debug.LogError("Valid Clips : " + validClips.Count); } } } } }
/// <summary> /// AnimClip을 PlayUnit에 담아서 재생한다. /// Queue에 저장된 클립들이 모두 끝나면 블렌드 없이 바로 실행된다. /// </summary> /// <param name="blendMethod"></param> /// <param name="isAutoEndIfNotloop">True이면 Clip의 재생 후 자동으로 종료한다. (Loop일 경우 무시됨)</param> /// <returns></returns> public apAnimPlayUnit PlayQueued(apAnimPlayData playData, apAnimPlayUnit.BLEND_METHOD blendMethod, float blendTime = 0.0f, bool isAutoEndIfNotloop = true) { //현재 재생되는 플레이 유닛 중에서 "가장 많이 남은 플레이 시간"을 기준으로 타이머를 잡자 //Fade 타임은 없고, 자동 삭제 타이머 + 자동 재생 대기 타이머를 지정 //현재 Queue에 있는 객체가 없다면 Play와 동일하다 if (_nPlayedUnit == 0) { return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop)); } //마지막 PlayUnit을 가져오자 apAnimPlayUnit lastPlayUnit = _animPlayUnits[_animPlayUnits.Count - 1]; if (lastPlayUnit.IsLoop) { //만약 마지막 PlayUnit이 Loop라면 => Queued 되지 않는다. 자동으로 [Play]로 바뀜 return(Play(playData, blendMethod, blendTime, isAutoEndIfNotloop)); } //Request를 생성한다. apAnimPlayRequest request = PopRequest(); request.SetCurrentPlayedUnits(this, _animPlayUnits); apAnimPlayUnit newPlayUnit = MakePlayUnit(playData, blendMethod, isAutoEndIfNotloop); newPlayUnit.Pause(); //Play Queued 명령을 준다. request.PlayQueued(newPlayUnit, lastPlayUnit, blendTime); #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; return(newPlayUnit); }