72.내일배움캠프 64일차 TIL <Unity Unity 2D 팀프로젝트- MartialGod:Reborn - 13일차> 07/09

정광훈(Unity_9기)·2025년 7월 9일

TIL (Today I Learned)

목록 보기
73/110
post-thumbnail

오늘 알게 된 것

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);
    }
}

0개의 댓글