// Functions //--------------------------------------------- public void Update() { #if UNITY_2017_1_OR_NEWER //추가 3.5 : Timeline의 PlayerDirector가 연결되어 있다면 재생할 수 있는지 확인하자. //재생되는 타임라인이 있다면, 메카님 컨트롤러는 무시하고 타임라인의 제어를 받자 if (_timlinePlay != null) { if (_timlinePlay.IsAnyPlaying) { if (_playType == PLAY_TYPE.Mecanim) { //Mecanim > Timeline _playType = PLAY_TYPE.Timeline; //메카님에서 재생중이던 클립들을 모두 Unlink해야한다. UnlinkAllMecanimClips(); } //타임라인으로 재생을 한다. _timlinePlay.Update(); if (_timlinePlay.IsLastPlayedTimelineClipChanged) { //프레임 보정>> //마지막으로 재생된 TimelineClip과, 현재 Animator에서 백그라운드에서 재생중인 State간의 시간을 보정한다. //- 0번 레이어야 한다. //- 재생 중인 State여야 한다. if (_timlinePlay.LastPlayedTimelineClip != null && _animator != null && _isValidAnimator && _nLayers > 0) { _curStateInfo = _animator.GetCurrentAnimatorStateInfo(0); _curClipInfos = _animator.GetCurrentAnimatorClipInfo(0); UnityEngine.Timeline.TimelineClip lastTimelineClip = _timlinePlay.LastPlayedTimelineClip; float lastLocalTime = _timlinePlay.LastPlayedLocalTime; if (_curClipInfos != null && _curClipInfos.Length > 0) { if (_curClipInfos[0].clip == lastTimelineClip.animationClip) { //현재 "재생중"인 "0번"레이어의 "현재 클립"과 동일하다 //시간을 보정하자 _animator.PlayInFixedTime(0, 0, lastLocalTime); } } } } //더이상 처리를 하지 않는다. return; } if (_playType == PLAY_TYPE.Timeline) { //Timeline > Mecanim _playType = PLAY_TYPE.Mecanim; //Timeline에서 재생중이던 클립들을 모두 Unlink해야한다. _timlinePlay.UnlinkAll(); } } #endif if (!_isValidAnimator) { //변경 : Timeline을 위해서 설정된 경우 RuntimeAnimatorController가 필요 없을 수 있다. //Debug.LogError("AnyPortrait : IsValidAnimator = false"); return; } //1. 일단 Clip Data를 초기화 for (int i = 0; i < _nClipData; i++) { _clipData[i].ReadyToUpdate(); } _curOrder = 0; //2. 레이어를 돌면서 각 클립에 대해 플레이, 시간, 배속(정방향/역방향)을 갱신한다. //AnimPlayUnit에 대해서 값을 넣는다. for (int iLayer = 0; iLayer < _nLayers; iLayer++) { _curMecanimLayer = _layers[iLayer]; if (iLayer == 0) { //Layer 0에서는 GetLayerWeight의 값이 0이 리턴된다. (항상 1이어야함) _curLayerWeight = 1.0f; } else { _curLayerWeight = _animator.GetLayerWeight(iLayer); } //_isInTransition = _animator.IsInTransition(iLayer); _curStateInfo = _animator.GetCurrentAnimatorStateInfo(iLayer); _curClipInfos = _animator.GetCurrentAnimatorClipInfo(iLayer); //Debug.Log("Cur Clip Info : "+ _curClipInfos.Length); //Debug.Log("Mecanim Layer [" + iLayer + "] / _isInTransition : " + _isInTransition + " / _curLayerWeight : " + _curLayerWeight); _curNormalizedTime = _curStateInfo.normalizedTime; //if(_curNormalizedTime > 1.0f) //{ // _curNormalizedTime -= (int)_curNormalizedTime; //} //"현재 Clip" 먼저 처리 if (_curClipInfos != null && _curClipInfos.Length > 0) { for (int iClip = 0; iClip < _curClipInfos.Length; iClip++) { _curClipAsset = _curClipInfos[iClip].clip; if (_curClipAsset == _portrait._emptyAnimClipForMecanim || _curClipAsset == null) { continue; } _curClipData = _clipDataByAsset[_curClipAsset]; if (_curClipData._isCalculated) { //이미 처리가 되었다면 패스 continue; } //업데이트를 하자 <Current> _curClipData.SetData(iLayer, _curOrder, _curMecanimLayer._blendType, _curStateInfo.speed, _curStateInfo.speedMultiplier, _curLayerWeight * _curClipInfos[iClip].weight, _curNormalizedTime); _curOrder++; } } _nextStateInfo = _animator.GetNextAnimatorStateInfo(iLayer); _nextClipInfos = _animator.GetNextAnimatorClipInfo(iLayer); //"다음 Clip" 처리 if (_nextClipInfos != null && _nextClipInfos.Length > 0) { //1. 전환되는 Clip이 존재한다. _nextNormalizedTime = _nextStateInfo.normalizedTime; //if (_nextNormalizedTime > 1.0f) //{ // _nextNormalizedTime -= (int)_nextNormalizedTime; //} for (int iClip = 0; iClip < _nextClipInfos.Length; iClip++) { _nextClipAsset = _nextClipInfos[iClip].clip; if (_nextClipAsset == _portrait._emptyAnimClipForMecanim || _nextClipAsset == null) { continue; } _nextClipData = _clipDataByAsset[_nextClipAsset]; if (_nextClipData._isCalculated) { //이미 처리가 되었다면 패스 continue; } //업데이트를 하자 <Next> _nextClipData.SetData(iLayer, _curOrder, _curMecanimLayer._blendType, //apAnimPlayUnit.BLEND_METHOD.Additive, _nextStateInfo.speed, _nextStateInfo.speedMultiplier, _curLayerWeight * _nextClipInfos[iClip].weight, _nextNormalizedTime); _curOrder++; } } } //3. 플레이 데이터 확인하여 PlayUnit 생성/삭제하여 연결한다. //프레임이나 설정, 이벤트 등을 갱신하고 호출한다. //0번 레이어를 기준으로 RootUnit을 결정한다. for (int i = 0; i < _nClipData; i++) { _curClipData = _clipData[i]; if (!_curClipData._isCalculated) { //계산이 안되었으면 Release를 한다. if (_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 되었던 ClipData이다. _curClipData.Unlink(); } } else { //계산이 되었으면 연결을 하고, 프레임과 Weight를 업데이트한다. if (!_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 안된 ClipData이다. _curClipData.Link(); //Layer = 0인 경우에 Link가 발생하는 경우 => RootUnit을 설정해주자 if (_curClipData._playedLayer == 0) { _animPlayManager.SetOptRootUnit(_curClipData._linkedRootUnit); } } //이제 업데이트를 합시다. _curClipData.UpdateAnimClipAndPlayUnit(); } //Prev를 갱신한다 _curClipData._isCalculatedPrev = _curClipData._isCalculated; } }
// Functions //--------------------------------------------- public void Update() { if (!_isValidAnimator) { Debug.Log("IsValidAnimator = false"); return; } //1. 일단 Clip Data를 초기화 for (int i = 0; i < _nClipData; i++) { _clipData[i].ReadyToUpdate(); } _curOrder = 0; //2. 레이어를 돌면서 각 클립에 대해 플레이, 시간, 배속(정방향/역방향)을 갱신한다. //AnimPlayUnit에 대해서 값을 넣는다. for (int iLayer = 0; iLayer < _nLayers; iLayer++) { _curMecanimLayer = _layers[iLayer]; if (iLayer == 0) { //Layer 0에서는 GetLayerWeight의 값이 0이 리턴된다. (항상 1이어야함) _curLayerWeight = 1.0f; } else { _curLayerWeight = _animator.GetLayerWeight(iLayer); } //_isInTransition = _animator.IsInTransition(iLayer); _curStateInfo = _animator.GetCurrentAnimatorStateInfo(iLayer); _curClipInfos = _animator.GetCurrentAnimatorClipInfo(iLayer); //Debug.Log("Cur Clip Info : "+ _curClipInfos.Length); //Debug.Log("Mecanim Layer [" + iLayer + "] / _isInTransition : " + _isInTransition + " / _curLayerWeight : " + _curLayerWeight); _curNormalizedTime = _curStateInfo.normalizedTime; //if(_curNormalizedTime > 1.0f) //{ // _curNormalizedTime -= (int)_curNormalizedTime; //} //"현재 Clip" 먼저 처리 if (_curClipInfos != null && _curClipInfos.Length > 0) { for (int iClip = 0; iClip < _curClipInfos.Length; iClip++) { _curClipAsset = _curClipInfos[iClip].clip; if (_curClipAsset == _portrait._emptyAnimClipForMecanim || _curClipAsset == null) { continue; } _curClipData = _clipDataByAsset[_curClipAsset]; if (_curClipData._isCalculated) { //이미 처리가 되었다면 패스 continue; } //업데이트를 하자 <Current> _curClipData.SetData(iLayer, _curOrder, _curMecanimLayer._blendType, _curStateInfo.speed, _curLayerWeight * _curClipInfos[iClip].weight, _curNormalizedTime); _curOrder++; } } _nextStateInfo = _animator.GetNextAnimatorStateInfo(iLayer); _nextClipInfos = _animator.GetNextAnimatorClipInfo(iLayer); //"다음 Clip" 처리 if (_nextClipInfos != null && _nextClipInfos.Length > 0) { //1. 전환되는 Clip이 존재한다. _nextNormalizedTime = _nextStateInfo.normalizedTime; //if (_nextNormalizedTime > 1.0f) //{ // _nextNormalizedTime -= (int)_nextNormalizedTime; //} for (int iClip = 0; iClip < _nextClipInfos.Length; iClip++) { _nextClipAsset = _nextClipInfos[iClip].clip; if (_nextClipAsset == _portrait._emptyAnimClipForMecanim || _nextClipAsset == null) { continue; } _nextClipData = _clipDataByAsset[_nextClipAsset]; if (_nextClipData._isCalculated) { //이미 처리가 되었다면 패스 continue; } //업데이트를 하자 <Next> _nextClipData.SetData(iLayer, _curOrder, _curMecanimLayer._blendType, //apAnimPlayUnit.BLEND_METHOD.Additive, _nextStateInfo.speed, _curLayerWeight * _nextClipInfos[iClip].weight, _nextNormalizedTime); _curOrder++; } } } //3. 플레이 데이터 확인하여 PlayUnit 생성/삭제하여 연결한다. //프레임이나 설정, 이벤트 등을 갱신하고 호출한다. //0번 레이어를 기준으로 RootUnit을 결정한다. for (int i = 0; i < _nClipData; i++) { _curClipData = _clipData[i]; if (!_curClipData._isCalculated) { //계산이 안되었으면 Release를 한다. if (_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 되었던 ClipData이다. _curClipData.Unlink(); } } else { //계산이 되었으면 연결을 하고, 프레임과 Weight를 업데이트한다. if (!_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 안된 ClipData이다. _curClipData.Link(); //Layer = 0인 경우에 Link가 발생하는 경우 => RootUnit을 설정해주자 if (_curClipData._playedLayer == 0) { _animPlayManager.SetOptRootUnit(_curClipData._linkedRootUnit); } } //이제 업데이트를 합시다. _curClipData.UpdateAnimClipAndPlayUnit(); } //Prev를 갱신한다 _curClipData._isCalculatedPrev = _curClipData._isCalculated; } }
public void Update(apAnimPlayManager animPlayManager) { #if UNITY_2017_1_OR_NEWER _c_curTime = _parentTrackSet._playableDirector.time; _lastPlayedTimelineClip = null; #endif _lastPlayedLocalTime = 0.0f; //1. 전체 Reday To Update for (int i = 0; i < _nClipData; i++) { _clipData[i].ReadyToUpdate(); } #if UNITY_2017_1_OR_NEWER //2. 범위 체크해서 업데이트 여부 결정과 Set Data _c_curClipData = null; _c_clipA = null; _c_clipB = null; _c_localTimeA = 0.0; _c_localTimeB = 0.0; _c_weightA = 0.0f; _c_weightB = 0.0f; _c_nPlayClips = 0; for (int i = 0; i < _nClipData; i++) { _c_curClipData = _clipData[i]; if (_c_curTime < _c_curClipData._timelineClip.start || _c_curTime > _c_curClipData._timelineClip.end) { continue; } if (_c_clipA == null) { _c_clipA = _c_curClipData; _c_nPlayClips = 1; _c_localTimeA = _c_clipA._timelineClip.ToLocalTimeUnbound(_c_curTime); } else if (_c_clipB == null) { //단, A와 AnimClip이 겹치면 안된다. if (_c_clipA._animClip != _c_curClipData._animClip) { _c_clipB = _c_curClipData; _c_nPlayClips = 2; _c_localTimeB = _c_clipB._timelineClip.ToLocalTimeUnbound(_c_curTime); break; //B까지 연결했으면 끝 } } } if (_c_nPlayClips == 1) { //PlayClip이 1개일 때 if (_c_localTimeA < _c_clipA._timelineClip.easeInDuration) { _c_weightA = GetWeightIn(_c_localTimeA, _c_clipA._timelineClip.easeInDuration); } else if (_c_localTimeA < _c_clipA._timelineClip.duration - _c_clipA._timelineClip.easeOutDuration) { _c_weightA = 1.0f; } else { _c_weightA = GetWeightOut(_c_localTimeA, _c_clipA._timelineClip.easeOutDuration, _c_clipA._timelineClip.duration); } _c_clipA.SetData(true, _c_weightA, (float)_c_localTimeA, _blendMethod, _layerOrder); //Clip A가 마지막에 계산되었다. _lastPlayedTimelineClip = _c_clipA._timelineClip; _lastPlayedLocalTime = (float)_c_localTimeA; } else if (_c_nPlayClips == 2) { //PlayClip이 2개일 때 (무조건 Blend) _c_weightA = GetWeightOut(_c_localTimeA, _c_clipA._timelineClip.blendOutDuration, _c_clipA._timelineClip.duration); _c_weightB = 1.0f - _c_weightA; _c_clipA.SetData(true, _c_weightA, (float)_c_localTimeA, _blendMethod, _layerOrder); _c_clipB.SetData(false, _c_weightB, (float)_c_localTimeB, _blendMethod, _layerOrder); //Clip B가 마지막에 계산되었다. _lastPlayedTimelineClip = _c_clipB._timelineClip; _lastPlayedLocalTime = (float)_c_localTimeB; } //3. 클립데이터 확인하여 Link/Unlink 및 Update for (int i = 0; i < _nClipData; i++) { _c_curClipData = _clipData[i]; if (!_c_curClipData._isCalculated) { //업데이트가 안되었다면 Release if (_c_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 되었던 ClipData다. _c_curClipData.Unlink(); } } else { //업데이트가 되었으면 연결을 하고, 프레임과 Weight를 업데이트 한다. if (!_c_curClipData._isCalculatedPrev) { //이전 프레임에서는 계산이 안되었다. _c_curClipData.Link(); //Root Unit을 갱신할 수도 있다. animPlayManager.SetOptRootUnit(_c_curClipData._linkedRootUnit); } //업데이트 <중요!> _c_curClipData.UpdateTimelineClipAndPlayUnit(); } //Prev 갱신 _c_curClipData._isCalculatedPrev = _c_curClipData._isCalculated; } #endif }