
정말 뻘짓이 많았던 닷트윈 사용이었다.
우선 코드를 보고 가자. 주석 부분은 닷트윈이 아닌 일반적인 코드로 제어한 애니메이션 부분인데 확실히 코드가 많이 줄어들어 정말 간편한 닷트윈 이였다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class UICreditPopup : MonoBehaviour
{
[SerializeField] GameObject logoAndName;
[SerializeField] private Text txtDeveloperName;
[SerializeField] private Image imgTeamLogo;
[SerializeField] private Text[] txtNames;
public void Init()
{
this.logoAndName.transform.GetComponent<RectTransform>().localPosition = new Vector3(0, 40, 0);
this.txtDeveloperName.color = new Color(1, 1, 1, 0);
this.imgTeamLogo.color = new Color(1, 1, 1, 0);
for (int i = 0; i < this.txtNames.Length; i++)
{
this.txtNames[i].color = new Color(1,1,1,0);
}
this.gameObject.SetActive(false);
}
public void StartAnim()
{
Debug.Log("StartAnim");
this.StartCoroutine(this.CoCreditAnimStart());
}
private IEnumerator CoCreditAnimStart()
{
yield return this.txtDeveloperName.DOFade(1f, 1f).SetEase(Ease.InOutBack).SetUpdate(true).WaitForCompletion();
yield return this.imgTeamLogo.DOFade(1f, 1f).SetEase(Ease.InOutBack).SetUpdate(true).WaitForCompletion();
yield return this.logoAndName.transform.GetComponent<RectTransform>().DOMoveY(this.logoAndName.transform.GetComponent<RectTransform>().position.y + 120f, 2f)
.SetEase(Ease.InOutQuad).SetUpdate(true).WaitForCompletion();
foreach (Text txtName in this.txtNames)
{
yield return txtName.DOFade(1f, 1f).SetUpdate(true).WaitForCompletion();
}
}
//private IEnumerator CoCreditAnimStart()
//{
// Debug.Log("CoCreditAnimStart");
// float elapsedTime = 0f;
// float duration = 1f;
// float startAlpha = 0f;
// float endAlpha = 1f;
// while (elapsedTime < duration)
// {
// Debug.Log(elapsedTime);
// float alpha = Mathf.Lerp(startAlpha, endAlpha, elapsedTime / duration);
// this.txtDeveloperName.color = new Color(1, 1, 1, alpha);
// elapsedTime += Time.deltaTime;
// yield return null;
// }
// Debug.Log("txtDeveloperName done");
// elapsedTime = 0f;
// while (elapsedTime < duration)
// {
// float alpha = Mathf.Lerp(startAlpha, endAlpha, elapsedTime / duration);
// this.imgTeamLogo.color = new Color(1, 1, 1, alpha);
// elapsedTime += Time.deltaTime;
// yield return null;
// }
// Debug.Log("imgTeamLogo done");
// elapsedTime = 0f;
// duration = 2f;
// Vector3 startPos = this.logoAndName.transform.localPosition;
// Vector3 endPos = new Vector3(startPos.x, startPos.y + 120f, startPos.z);
// while (elapsedTime < duration)
// {
// this.logoAndName.transform.localPosition = Vector3.Lerp(startPos, endPos, elapsedTime / duration);
// elapsedTime += Time.deltaTime;
// yield return null;
// }
// Debug.Log("logoAndName done");
// elapsedTime = 0f;
// duration = 1f;
// foreach (Text txtName in this.txtNames)
// {
// while (elapsedTime < duration)
// {
// float alpha = Mathf.Lerp(startAlpha, endAlpha, elapsedTime / duration);
// txtName.color = new Color(1, 1, 1, alpha);
// elapsedTime += Time.deltaTime;
// yield return null;
// }
// elapsedTime = 0f;
// }
// Debug.Log("txtNames done");
// yield break;
//}
public void StopAnim()
{
this.logoAndName.transform.GetComponent<RectTransform>().DOKill(); // Tween 객체 초기화
this.txtDeveloperName.DOKill(); // Tween 객체 초기화
this.imgTeamLogo.DOKill(); // Tween 객체 초기화
foreach (Text txtName in this.txtNames)
{
txtName.DOKill(); // Tween 객체 초기화
}
// 모든 코루틴 중지 및 객체 비활성화
this.StopAllCoroutines();
this.Init();
}
}
우선 코루틴을 이용해 닷트윈을 제어하여 yield return WaitForCompletion(); 메서드를 사용, 애니메이션이 끝나면 다음 애니메이션을 시작하는식으로 제어를 하였다.
하지만 문제는 여기서 발생했는데 어째서인지 코루틴이 돌지 않았다.
이유가 대체 뭘까 하고 한참을 보며 해본 삽질 목록이다.
1. 이벤트를 발생시켜주는 다른 스크립트에서의 참조가 잘못되었나? 아니었다. 할당도 제대로 되어있었다.
2. 이벤트 발생시 오브젝트를 다른 곳에서 참조 및 제어하나? 아니었다 외부 스크립트중 제어 가능한 스크립트는 하나 뿐 이었다.
3. 이니셜 라이징의 순서가 잘못되었나? 아니었다 이니셜라이징의 순서와 관계없이 잘 동작중이었다.
4. 그럼 닷트윈이 문제인가? 아니었다. 닷트윈은 다른 스크립트에서는 정말 문제없이 잘 돌아갔다.
5. 닷트윈을 두개 이상 돌리면 안되나? 말도 안되는 소리였다.
6. 닷트윈 플러그인 이상? 아니었다 다른 닷트윈들은 잘만 돌아가고 있었다.
6. 일반 코드로 제어해도 안되나? 안되었다.
여기까지 삽질을 번복하던중 중요한 사실을 하나 알게 되었는데 현재 코루틴을 돌릴때의 상태가 Time.timeScale 값이 0인 상태였다는 거다 (애초에 "Pause Director" 가 스크립트의 이름이었다... ㅠㅜ)
여기서 알게된 사항은 아래와 같다.
- 타임 스케일 값이 0일때는 코루틴이 돌지 않는다. 이는 즉 코드를 이용한다 하여도 돌지 않는다.
- 닷트윈은 .SetUpdate() 메서드를 제공하는데 해당 메서드를 이용하면 타임스케일과 관계없이 애니메이션의 제어가 가능했다.
- 혹 애니메이션 중간에 코루틴을 정지시킨다 하더라도 닷트윈은 계속 돌기 때문에 명시적으로 초기화 (알파값이나 위치값) 해주어도 한번 실행중이던 애니메이션은 완료가 된다. 이를 위해 초기화시 명시적으로 DOKill(); 메서드를 사용하여 애니메이션을 중지시켜주고 이후 초기화를 해주어야 한다
- 로컬 스케일로 움직이려고 하지 말고 월드 포지션으로 움직여 주자 ( 예상치 못한 방향으로 갈수 있기 때문)
이정도의 교훈을 얻을수 있었고 삽질과 뻘짓 끝에 닷트윈을 불신하고 탓한 내가 부끄러웠다 ㅎㅎ;;
암튼 생각한대로 애니메이션을 뽑을수 있었고 좀 더 다양한 애니메이션을 넣어 크레딧을 완성시킬 예정이다.
'프로젝트 > 건즈앤 레이첼스' 카테고리의 다른 글
| [ 유니티 프로젝트] 대화창 팝업 구조 잡기 및 데이터 연동 (0) | 2023.05.06 |
|---|---|
| [유니티 프로젝트] 디파짓 시스템 구현 (UI 업데이트 이전) (0) | 2023.05.04 |
| [유니티 프로젝트] 상자 아이템 제너레이터 구조 (0) | 2023.05.01 |
| [유니티 프로젝트] DOTween을 이용한 팝업 UI 애니메이션 (0) | 2023.05.01 |
| [유니티 프로젝트] 유저 가이드 화살표 ( 포탈 화살표 ) 제작 (1) | 2023.04.30 |