
오늘 알게 된 것
animator.GetCurrentAnimatorStateInfo(0).IsName("Move");
이 코드는 "Move"라는 이름의 애니메이션이 현재 Animator의 첫 번째 레이어(0번 레이어)에서
재생 중인지 아닌지를 확인하는 코드.
레이어는 Animator Controller를 의미하고 생성된 순서대로 레이어 순서가 정해짐.
GetCurrentAnimatorStateInfo(0):
Animator의 첫 번째 레이어(기본 레이어)에 대한 현재 상태 정보를 가져옴.
IsName("Move"):
가져온 현재 상태의 이름이 "Move"인지 확인.
따라서, 이 코드는 "Move" 애니메이션을 실행시켜 달라는 명령이 아니라,
"Move" 애니메이션이 현재 실행 중인지 여부를 묻는 조건문으로 사용.
예를 들어, if (animator.GetCurrentAnimatorStateInfo(0).IsName("Move")) { ... } 와
같이 사용하여 "Move" 애니메이션이 재생 중일 때 특정 동작을 수행하도록 할 수 있음.
이렇게 사용했음.
const string ActivateIdleString = "ActivateIdle";
public bool GetCurrentAnimStateInfo()
{
if (animator == null)
{
LogHelper.LogError("Animator is null", this);
return false;
}
return animator.GetCurrentAnimatorStateInfo(0).IsName(ActivateIdleString);
}
==============================================
public void Interaction() // 플레이어와 상호작용
{
if (saveNodeAnimation.isActivate == false) // 세이브 노드 비활성화일 때
{
SetInteractionTextActive(false); // 상호작용 텍스트("F") 비활성화
Invoke("SaveNodeActiveSfx", 0.5f); // 활성화가 되었다는 효과음
saveNodeAnimation.ChangeAnimation(); // 활성화 애니메이션 작동
StartCoroutine(InteractionTexCoroutine()); // 상호작용 텍스트("F") 활성화
return;
}
if (saveNodeAnimation.GetCurrentAnimStateInfo()) //////////// <- 여기
{
if (saveNodeUI != null)
{
saveNodeUI.SetActive(true); // 세이브 노드UI 활성화
}
UIManager.Instance.Close<BattleUI>();
// UIManager.Instance.Open<SaveNodeUI>();
if (interactionText != null)
{
SetInteractionTextActive(false);
}
}
}
using System.Collections;
using UnityEngine;
public class SaveNode : MonoBehaviour, IInteraction
{
[SerializeField] private GameObject saveNodeUI;
[SerializeField] private GameObject interactionText;
[SerializeField] private SaveNodeAnimation saveNodeAnimation;
const string SaveNodeUIString = "SaveNodeUI";
const string InteractionString = "Canvas - Interaction"; // InteractionTextBGString을 사용하면 지우기
const string InteractionTextBGString = "InteractionTextBG";
const string SaveNodeActiveSoundString = "세이브_노드_활성화.wav";
private void Reset()
{
saveNodeUI = GameObject.Find(SaveNodeUIString);
interactionText = this.TryFindChild(InteractionTextBGString);
saveNodeAnimation = this.TryGetChildComponent<SaveNodeAnimation>();
}
public void Interaction() // 플레이어와 상호작용
{
if (saveNodeAnimation.isActivate == false) // 세이브 노드 비활성화일 때
{
SetInteractionTextActive(false); // 상호작용 텍스트("F") 비활성화
Invoke("SaveNodeActiveSfx", 0.5f); // 활성화가 되었다는 효과음
saveNodeAnimation.ChangeAnimation(); // 활성화 애니메이션 작동
StartCoroutine(InteractionTexCoroutine()); // 상호작용 텍스트("F") 활성화
return;
}
if (saveNodeAnimation.GetCurrentAnimStateInfo())
{
if (saveNodeUI != null)
{
saveNodeUI.SetActive(true); // 세이브 노드UI 활성화
}
UIManager.Instance.Close<BattleUI>();
// UIManager.Instance.Open<SaveNodeUI>();
if (interactionText != null)
{
SetInteractionTextActive(false);
}
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.layer == LayerHelper.OriginLayerValue(LayerHelper.PlayerLayer))
{
SetInteractionTextActive(true);
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.layer == LayerHelper.OriginLayerValue(LayerHelper.PlayerLayer))
{
SetInteractionTextActive(false);
}
}
public void SetInteractionTextActive(bool isActive) // 상호작용 텍스트("F") 활성화
{
if (interactionText != null)
{
interactionText.SetActive(isActive);
}
}
private IEnumerator InteractionTexCoroutine()
{
yield return CoroutineHelper.WaitTime(1f);;
interactionText.SetActive(true);
}
private void SaveNodeActiveSfx() // 세이브 노드 활성화 되었다는 효과음
{
SoundManager.Instance.PlaySound(transform, SaveNodeActiveSoundString);
}
public void Rest() // 휴식하기 선택 시 체력/스테미나 회복, 리페어 프로토콜 횟수를 충전시킨다.
{
LogHelper.Log("회복");
}
public void OpenUpgradeUI() // 전술 코어 업그레이드 UI를 출력한다.
{
// 전술 코어 업그레이드 UI가 활성화 되었을 때 세이브 노드 UI는 전술 코어 UI와 겹치지 않게 한다.
LogHelper.Log("업그레이드UI 표시");
}
}
========
using System.Collections;
using DG.Tweening;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class SaveNodeUI : UIBase
{
[SerializeField] private CanvasGroup saveNodeUICanvasGroup; // 페이드 효과를 주기 위한 캔버스 그룹
[SerializeField] private Image fadeImage; // 페이드 효과에 사용할 이미지
[SerializeField] private GameObject saveNodePanel; // 세이브 노드UI 패널 오브젝트
[SerializeField] private SaveNodeUIController saveNodeUIController;
[SerializeField] private SaveNode saveNode;
const string SaveNodePanelString = "Panel";
const string FadeImageString = "Image - Fade";
private void Reset()
{
saveNodeUICanvasGroup = this.TryGetChildComponent<CanvasGroup>();
fadeImage = this.TryGetChildComponent<Image>(FadeImageString);
saveNodePanel = this.TryFindChild(SaveNodePanelString);
saveNodeUIController = GetComponent<SaveNodeUIController>();
saveNode = FindFirstObjectByType<SaveNode>();
}
private void OnEnable()
{
Init();
}
private void Start()
{
UIManager.Instance.Add<SaveNodeUI>(this);
}
public override void Init() // 초기화
{
saveNodeUICanvasGroup.alpha = 1f;
PlayerInputEnabled(false); // 플레이어 인풋 비활성화
}
public void SaveNodeUIFadeOut()
{
saveNodeUICanvasGroup.DOKill();
UIManager.Instance.Close<BattleUI>(); // 배틀 UI 비활성화
saveNodeUICanvasGroup.DOFade(1, 0.5f).SetEase(Ease.InQuad); // 0.5초에 걸쳐 점점 나타남
}
public override void OffUI() // 세이브 노드 UI 종료
{
saveNodeUICanvasGroup.DOKill();
UIManager.Instance.Open<BattleUI>(); // 배틀 UI 다시 활성화
saveNodeUICanvasGroup.DOFade(0, 0.5f).SetEase(Ease.OutQuad)
.OnComplete(() => { StartCoroutine(PlayerInputEnableCoroutine()); }); // 0.5초에 걸쳐 점점 사라짐
}
private void FadeOut() // 휴식하기 누르면 연출되는 페이드 아웃
{
fadeImage.DOKill();
saveNodePanel.gameObject.SetActive(false);
fadeImage.DOFade(1, 2f).SetEase(Ease.OutQuad); // 2초에 걸쳐 점점 어두워짐
}
private void FadeIn() // 휴식하기 누르면 페이드 아웃 후 연출되는 페이드 인
{
fadeImage.DOKill();
fadeImage.DOFade(0, 2f).SetEase(Ease.InQuad)
.OnComplete(() => { saveNodePanel.gameObject.SetActive(true); }); // 2초에 걸쳐 점점 밝아짐
saveNodePanel.gameObject.SetActive(true);
}
public IEnumerator FadeCoroutine() // 페이드 코루틴
{
saveNodeUIController.SetMenuInputEnabled(false);
FadeOut();
yield return CoroutineHelper.WaitTime(3f); // 1초 뒤에 FadeIn()발동
FadeIn();
yield return CoroutineHelper.WaitTime(3f); // FadeIn() 다음에 1초 후 입력 가능
saveNodeUIController.SetMenuInputEnabled(true);
}
private void PlayerInputEnabled(bool enabled) // 플레이어 인풋을 활성화 / 비활성화 시킴
{
if (Player.Instance != null && Player.Instance.TryGetComponent<PlayerInput>(out PlayerInput playerInput))
{
if (enabled)
{
playerInput.ActivateInput();
LogHelper.Log("플레이어 인풋 활성화");
}
else
{
playerInput.DeactivateInput();
LogHelper.Log("플레이어 인풋 비활성화");
}
}
}
private IEnumerator PlayerInputEnableCoroutine() // 플레이어 인풋 활성화 코루틴
{
yield return CoroutineHelper.WaitTime(1f); // 1초뒤에 플레이어가 움직일 수 있게 해야함
PlayerInputEnabled(true);
saveNode.SetInteractionTextActive(true);
gameObject.SetActive(false);
}
}
======
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class SaveNodeUIController : MonoBehaviour
{
[SerializeField] private SaveNode saveNode;
[SerializeField] private SaveNodeUI saveNodeUI;
private TextMeshProUGUI restText;
private TextMeshProUGUI coreUpgradeText;
private TextMeshProUGUI backText;
public List<TMP_Text> selectMenuList; // 선택 가능한 메뉴 리스트
public float changeFontSize = 1.2f; // 선택 중인 메뉴 텍스트는 1.2배 커짐
private List<float> originalFontSize = new List<float>(); // 원래 폰트 사이즈 리스트
private int currentIndex; // 현재 선택 중인 메뉴 인덱스
private bool isMenuInputDisabled = false; // 세이브 노드UI 메뉴 입력 방지
const string RestTextString = "Text - Rest";
const string CoreUpgradeTextString = "Text - CoreUpgrade";
const string BackTextString = "Text - Back";
private void Reset()
{
saveNode = FindFirstObjectByType<SaveNode>();
saveNodeUI = GetComponent<SaveNodeUI>();
if (selectMenuList == null)
{
selectMenuList = new List<TMP_Text>();
}
else
{
selectMenuList.Clear();
}
restText = this.TryFindChild(RestTextString).GetComponent<TextMeshProUGUI>();
coreUpgradeText = this.TryFindChild(CoreUpgradeTextString).GetComponent<TextMeshProUGUI>();
backText = this.TryFindChild(BackTextString).GetComponent<TextMeshProUGUI>();
selectMenuList.Add(restText);
selectMenuList.Add(coreUpgradeText);
selectMenuList.Add(backText);
}
private void OnEnable()
{
InitMenu();
}
public void InitMenu() // 메뉴 초기화
{
isMenuInputDisabled = false;
currentIndex = 0;
foreach (TMP_Text menu in selectMenuList) // 메뉴 텍스트 기존 폰트 사이즈 추가
{
originalFontSize.Add(menu.fontSize);
}
UpdateSelectFont();
}
private void Update()
{
if (isMenuInputDisabled) return;
SelectMenu();
}
private void SelectMenu() // 메뉴 선택
{
if (Input.GetKeyDown(KeyCode.W)) // 위로 이동
{
currentIndex--;
// 첫 인덱스에서 위로 이동하면 마지막 인덱스로 이동
if (currentIndex < 0)
{
currentIndex = selectMenuList.Count - 1;
}
UpdateSelectFont();
}
else if (Input.GetKeyDown(KeyCode.S)) // 아래로 이동
{
currentIndex++;
// 마지막 인덱스에서 아래로 이동하면 첫 인덱스로 이동
if (currentIndex >= selectMenuList.Count)
{
currentIndex = 0;
}
UpdateSelectFont();
}
else if (Input.GetKeyDown(KeyCode.Escape))
{
if (saveNodeUI != null)
{
saveNodeUI.OffUI(); // 세이브노드UI 비활성화
}
}
else if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.G))
{
EnterMenu(currentIndex); // 해당 메뉴 기능 실행
}
}
private void UpdateSelectFont() // 선택 중인 메뉴 폰트 업데이트
{
for (int i = 0; i < selectMenuList.Count; i++)
{
if (i == currentIndex) // 현재 인덱스의 글자 크기를 키움
{
selectMenuList[i].fontSize = originalFontSize[i] * changeFontSize;
}
else // 선택중인 인덱스가 아니면 기존 글자 크기로 돌아옴
{
selectMenuList[i].fontSize = originalFontSize[i];
}
}
}
private void EnterMenu(int index) // 메뉴 선택
{
switch (index)
{
case 0:
if (saveNode != null)
{
saveNode.Rest(); // 휴식기능
StartCoroutine(saveNodeUI.FadeCoroutine()); // 페이드 효과
}
break;
case 1:
if (saveNode != null)
{
saveNode.OpenUpgradeUI(); // 업그레이드 UI 활성화
}
break;
case 2:
if (saveNodeUI != null)
{
saveNodeUI.OffUI(); // 세이브 노드UI 종료
}
break;
}
}
/// <summary>
/// 휴식하기 중에 다른 입력이 되지 않도록 방지
/// </summary>
/// <param name="enabled">enabled가 false면 입력되지 않음, true면 입력 가능</param>
public void SetMenuInputEnabled(bool enabled)
{
isMenuInputDisabled = !enabled;
}
}
=====
using UnityEngine;
public class SaveNodeAnimation : MonoBehaviour
{
[SerializeField] private Animator animator;
public bool isActivate = false;
const string IsActivateString = "IsActivate";
const string ActivateIdleString = "ActivateIdle";
private void Reset()
{
animator = GetComponent<Animator>();
}
public void ChangeAnimation()
{
if (animator == null)
{
LogHelper.LogError("Animator is null", this);
}
animator.SetBool(IsActivateString, true);
isActivate = true;
}
public bool GetCurrentAnimStateInfo()
{
if (animator == null)
{
LogHelper.LogError("Animator is null", this);
return false;
}
return animator.GetCurrentAnimatorStateInfo(0).IsName(ActivateIdleString);
}
}