[개발일지] 34[완결]. 야생 UI 수정 & 메인 씬 기능 추가

2025. 1. 31. 21:31·유니티 프로젝트/점토게임

0. 들어가기 전에

이번엔 야생 UI 를 손봤다. 체력바에 현재 체력을 표시하도록 했고, 화면 상단에 타이머를 야생이 끝나기 까지 남은 시간으로 설정하도록 했다.

 

그리고 야생의 난이도가 어려워질수록 배경이 어두워지는데 타일맵의 색은 그대로라 위화감이 있어서 Light2D 를 이용했다. 일단 플레이어한테 빛을 넣어놨고, 맵에 global light 을 만들어놨다. 맵이 어려워질수록 global light 을 어둡게 해서 타일맵의 색도 어두워지도록 했다.

 

그리고 야생에서 새로운 점토를 잡아왔을 때 메인 씬에서 점토 구매 버튼 위에 별표가 뜨도록 했다. 새로 잡은 점토 페이지로 도달하기 전까지는 별표가 없어지지 않는다.

 

 


 

 

1. 게임 오브젝트

메인 씬과 야생 씬으로 파트를 나누어서 설명하려고 한다.

 

1.1 메인 씬

 

1.1.1 New Alam 

야생에서 새로운 점토를 잡아오면 사진과 같이 별표가 뜨도록 했다. 잡아온 점토의 페이지로 도달할 때까지 별표가 활성화되어 있도록 했다.

 

1.2 야생 씬

야생 씬에는 빛 오브젝트를 추가했고, 게임 클리어 판넬에 NewText 게임 오브젝트를 추가했다. 그리고 BGM 게임 오브젝트도 만들었다. 

 

1.2.1 NewText

이번에 잡은 점토가 처음 만나는 점토라면 알리기 위해서 NewText 를 만들었다. 애니메이션도 만들어서 위아래로 움직이도록 했다.

 

 

1.2.2 Light 2D, light

Light2D 는 게임 화면을 어둡게 만들기 위해서 만들었고, 플레이어 속 light 는 플레이어 주변을 밝히기 위해 만들었다.

 

예시 모습은 다음과 같다.

 

 

1.2.3 BGM

BGM 게임 오브젝트를 추가해서 배경음을 야생 난이도에 맞게 설정할 수 있도록 했다.

 

 


 

 

2. 스크립트

이번에 새로 만든 스크립트는 BGM 이다. 

 

2.1 BGM 스크립트

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BGM : MonoBehaviour
{
    [Header("Audio")]
    private AudioSource bgmAudio;
    public AudioClip easyClip;
    public AudioClip normalClip;
    public AudioClip hardClip;

    private void Awake()
    {
        bgmAudio = GetComponent<AudioSource>();
    }

    private void Start()
    {
        SetBGM();
    }

    private void SetBGM()
    {
        // 야생 난이도에 맞는 브금 틀도록
        if (GameManager.instance.worldLevel == 0)
            bgmAudio.clip = easyClip;
        else if (GameManager.instance.worldLevel == 1)
            bgmAudio.clip = normalClip;
        else 
            bgmAudio.clip = hardClip;

        bgmAudio.Play(); // 재생!
    }

    public void StopBGM()
    {
        bgmAudio?.Stop();
    }
}

 

2.2 BGM 스크립트 설명

더보기

1. 변수

야생 단계에 맞게 브금을 설정하기 위한 변수이다.

[Header("Audio")]
private AudioSource bgmAudio;
public AudioClip easyClip;
public AudioClip normalClip;
public AudioClip hardClip;

 

 

2. Awake()

할당해줬다.

private void Awake()
{
    bgmAudio = GetComponent<AudioSource>();
}

 

 

3. Start()

브금을 틀도록 했다.

private void Start()
{
    SetBGM();
}

 

 

4. SetBGM()

야생 난이도에 맞게 브금을 설정하고 실행하도록 했다.

private void SetBGM()
{
    // 야생 난이도에 맞는 브금 틀도록
    if (GameManager.instance.worldLevel == 0)
        bgmAudio.clip = easyClip;
    else if (GameManager.instance.worldLevel == 1)
        bgmAudio.clip = normalClip;
    else 
        bgmAudio.clip = hardClip;

    bgmAudio.Play(); // 재생!
}

 

 

5. StopBGM()

브금을 끄는 메서드이다. 다른 스크립트에서 호출해서 사용한다.

public void StopBGM()
{
    bgmAudio?.Stop();
}

 

2.3 Player 스크립트

더보기
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
    [Header("Player Info")]
    public int heart = 3; // 목숨 3개
    public float jumpPower = 500f; // 점프 힘

    public int jumpCount = 0; // 누적 점프 횟수(최대 두번 뛸 수 있도록)
    public bool isGrounded = false; // 바닥에 닿았는지 여부
    public bool isDead = false; // 사망 여부
    public bool isInvincibility = false; // 무적 여부

    public Rigidbody2D rigid; // 리지드바디 컴포넌트
    public Animator anim; // 애니메이터 컴포넌트
    public AudioSource playerAudio; // 사용할 오디오 소스 컴포넌트
    public SpriteRenderer spriteRenderer; // 스프라이트 렌더러

    public AudioClip deathClip; // 죽을 때 나는 소리
    public AudioClip jumpClip; // 점프할 때 나는 소리
    public AudioClip attackedClip; // 맞을 때 나는 소리
    public AudioClip gameClearClip; // 게임 성공할 때 나는 소리

    public float gamePlayTime = 30f; // 일단 1분으로..
    public float curTime = 0;


    [Header("World UI")]
    public BGM worldBGM;
    public Text time;
    public GameObject[] heartUIs;
    public Vector3[] heartUIsPos; // 애니메이션 수행하기 전 위치
    public int heartIdx;

    [Header("Light")]
    public Light2D playerLight;


    private void Start()
    {
        rigid = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        playerAudio = GetComponent<AudioSource>();
        spriteRenderer = GetComponent<SpriteRenderer>();


        for (int i=0; i<heartUIs.Length; i++)
        {
            // 위치 저장
            heartUIsPos[i] = heartUIs[i].transform.position;
        }

        time.gameObject.SetActive(false); // 게임 시작 전에 타이머 꺼놓기

        // 맵 레벨에 따라 설정
        if (GameManager.instance.worldLevel == 0)
            playerLight.gameObject.SetActive(false);

        if (GameManager.instance.worldLevel == 2)
            time.color = new Color(255, 255, 255, 255); // 텍스트 흰색으로 바꾸기..
    }

    private void Update()
    {
        // 아직 게임 시작 안 했으면 좀 기다리기..
        while (!GameManager.instance.isGameStart)
        {
            return;
        }

        time.gameObject.SetActive(true); // 게임 시작하면 활성화 켜기

        if (curTime >= gamePlayTime)
        {
            // 플레이 시간 지나면 더이상 진행하지 않음
            GameEnd();
        }

        if (isDead)
        {
            // 사망하면 더이상 진행하지 않음
            return;
        }

        if (Input.GetMouseButtonDown(0) && jumpCount < 2)
        {
            // 점프 횟수 증가
            jumpCount++;

            // 점프 직전에 속도를 0 으로 변경
            rigid.velocity = Vector3.zero;

            // 위쪽으로 힘주기
            rigid.AddForce(new Vector2(0, jumpPower));

            // 오디오 소스 재생
            PlaySound(jumpClip);
        }
        else if (Input.GetMouseButtonUp(0) && rigid.velocity.y > 0)
        {
            // 마우스 왼쪽 버튼에서 손을 떼는 순간 && 속도의 y 값이 양수(위로 상승 중)
            // 현재 속도를 절반으로 변경
            rigid.velocity = rigid.velocity * 0.5f;
        }

        // 애니메이터의 Grounded 파라미터를 isGrounded 값으로 갱신
        anim.SetBool("Grounded", isGrounded);

        curTime += Time.deltaTime; // 시간 더해주기

        // Time Text 에 시간 반영
        time.text = (int)(gamePlayTime - curTime + 1) + "s";
    }

    private void PlaySound(AudioClip clip)
    {
        playerAudio.clip = clip;
        playerAudio.Play();
    }

    public void GameEnd()
    {
        worldBGM.StopBGM(); // 스탑!

        // 오디오 소스 재생
        PlaySound(gameClearClip);

        rigid.simulated = false;

        // 여기서 게임 매니저 게임 종료(성공) 메서드 호출
        GameManager.instance.WorldGameClear();
    }

    public void Die()
    {
        worldBGM.StopBGM(); // 스탑!

        // 오디오 소스 재생
        PlaySound(deathClip);

        for (int i=heartIdx; i<heartUIs.Length; i++)
        {
            SetHeartUI(i); // 설정해용~~
        }

        StartCoroutine(DieCoroutine());
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        // Collider 를 통해 다른 객체가 경계를 통과했을 때 자동으로 호출되는 메서드
        // 두 객체 중 적어도 하나에 Collider 가 있고, Is Trigger 옵션이 활성화 되어 있어야함.


        // 체력 깎이는 부분은 무적 상태라면 수행 안 하고 걍 빠져나가기..
        if (isInvincibility) return;

        // 만약 플레이어가 체력 깎이는 바닥을 통과했을 때
        if (collision.tag == "AttackGround")
        {
            Die(); // 죽어
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            // 충돌한 가장 낮은 지점 확인
            ContactPoint2D contact = collision.contacts[0];

            // 플레이어의 발보다 높은 곳에서 충돌했다면 무시
            if (contact.point.y > transform.position.y) return;

            isGrounded = true; // 땅에 닿았음 표시
            jumpCount = 0; // 리셋
        }
        else if (collision.gameObject.tag == "Attack")
        {
            if (isInvincibility) return; // 무적 상태면 그냥 나가기..

            // 장애물에 닿았으면 heart 값 -1 해주기..

            Attacked();
        }
        else if (collision.gameObject.tag == "Monster")
        {
            if (isInvincibility) return; // 무적 상태면 그냥 나가기..

            // 충돌한 가장 낮은 지점 확인
            ContactPoint2D contact = collision.contacts[0];

            // 만약 플레이어가 몬스터보다 위에 있고, y 축의 속도가 감소하는 중이라면 몬스터를 밟은 거임
            if (transform.position.y >= contact.point.y /*&& rigid.velocity.y <= 0*/)
            {
                // 몬스터 머리 밟으면 다시 이단 점프 가능하도록..
                isGrounded = true; // 땅에 닿았음 표시
                jumpCount = 0; // 리셋

                // 몬스터의 Die 메서드 호출
                collision.transform.GetComponent<Monster>().Die();
            }
            else
            {
                Attacked();
            }
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            isGrounded = false;
        }
    }

    private void Attacked()
    {
        // 오디오 소스 재생
        PlaySound(attackedClip);

        // 피 깎기
        heart--;
        SetHeartUI(heartIdx);
        heartIdx++;

        if (heart == 0)
        {
            Die(); // 죽어
            return;
        }

        // 잠시 무적 상태로..
        StartCoroutine(Invincibility());
    }

    private void SetHeartUI(int idx)
    {
        heartUIs[idx].GetComponent<Animator>().Play("Idle", 0, 0f); // 특정 애니메이션 초기화
        heartUIs[idx].GetComponent<Animator>().enabled = false;
        heartUIs[idx].transform.position = heartUIsPos[idx]; // 위치 바꿩
        heartUIs[idx].GetComponent<Image>().color = new Color32(255, 255, 255, 40);
    }

    private IEnumerator Invincibility()
    {
        isInvincibility = true;
        spriteRenderer.color = new Color32(255, 0, 0, 180); // 반투명하게..(빨갛게)
        gameObject.layer = 9; // PlayerDamaged 레이어는 9번임
        anim.SetTrigger("Hit"); // 애니메이션 수행

        yield return new WaitForSeconds(2f); // 2초 동안 무적

        gameObject.layer = 8; // Player 레이어는 8번임
        spriteRenderer.color = new Color32(255, 255, 255, 255); // 원래 상태로..
        isInvincibility = false; // 다시 false 로 바꾸고 빠져나가기..
    }

    private IEnumerator DieCoroutine()
    {
        // 여기서 게임 종료(실패) 로직 수행할거임
        GameManager.instance.WorldGameFail(); // 게임 실패 정보 세팅

        // 애니메이터의 Die 트리거 파라미터를 세팅함
        anim.SetTrigger("Die");

        // 오디오 소스 클릅을 deathClip 으로 변경
        playerAudio.clip = deathClip;

        // 오디오 실행
        playerAudio.Play();

        // 속도를 제로로 변경
        rigid.velocity = Vector2.zero;

        // 사망 상태 true 로
        isDead = true;

        yield return new WaitForSeconds(3f);

        gameObject.SetActive(false); // 비활성화
    }
}

 

2.4 Player 스크립트 변경 사항 설명

더보기

1. 변수

야생의 체력바 UI 를 관리할 수 있도록 변수를 선언했다. 그리고 플레이어의 자식 오브젝트인 light 를 관리하기 위한 변수도 선언했다.

[Header("World UI")]
public BGM worldBGM;
public Text time;
public GameObject[] heartUIs;
public Vector3[] heartUIsPos; // 애니메이션 수행하기 전 위치
public int heartIdx;

[Header("Light")]
public Light2D playerLight;

 

 

2. Start()

애니메이션을 수행하기 전의 체력바 위치를 저장하도록 했다. 체력이 까이면 해당 체력바가 더이상 애니메이션을 수행하지 않도록 해야한다. 그때 위치가 잘못 설정될 수 있어서 애니메이션을 멈춘 후 따로 위치를 다시 설정해주기 위해 필요하다.

 

그리고 게임 시작 전엔 time 게임 오브젝트를 꺼서 보이지 않도록 했다.

private void Start()
{
    rigid = GetComponent<Rigidbody2D>();
    anim = GetComponent<Animator>();
    playerAudio = GetComponent<AudioSource>();
    spriteRenderer = GetComponent<SpriteRenderer>();


    for (int i=0; i<heartUIs.Length; i++)
    {
        // 위치 저장
        heartUIsPos[i] = heartUIs[i].transform.position;
    }

    time.gameObject.SetActive(false); // 게임 시작 전에 타이머 꺼놓기

    // 맵 레벨에 따라 설정
    if (GameManager.instance.worldLevel == 0)
        playerLight.gameObject.SetActive(false);

    if (GameManager.instance.worldLevel == 2)
        time.color = new Color(255, 255, 255, 255); // 텍스트 흰색으로 바꾸기..
}

 

 

3. Update()

야생 클리어까지 남은 시간을 표시하기 위해 Update 문에서 time 변수의 텍스트를 조정해줬다.

private void Update()
{
    // 아직 게임 시작 안 했으면 좀 기다리기..
    while (!GameManager.instance.isGameStart)
    {
        return;
    }

    time.gameObject.SetActive(true); // 게임 시작하면 활성화 켜기

    if (curTime >= gamePlayTime)
    {
        // 플레이 시간 지나면 더이상 진행하지 않음
        GameEnd();
    }

    if (isDead)
    {
        // 사망하면 더이상 진행하지 않음
        return;
    }

    if (Input.GetMouseButtonDown(0) && jumpCount < 2)
    {
        // 점프 횟수 증가
        jumpCount++;

        // 점프 직전에 속도를 0 으로 변경
        rigid.velocity = Vector3.zero;

        // 위쪽으로 힘주기
        rigid.AddForce(new Vector2(0, jumpPower));

        // 오디오 소스 재생
        PlaySound(jumpClip);
    }
    else if (Input.GetMouseButtonUp(0) && rigid.velocity.y > 0)
    {
        // 마우스 왼쪽 버튼에서 손을 떼는 순간 && 속도의 y 값이 양수(위로 상승 중)
        // 현재 속도를 절반으로 변경
        rigid.velocity = rigid.velocity * 0.5f;
    }

    // 애니메이터의 Grounded 파라미터를 isGrounded 값으로 갱신
    anim.SetBool("Grounded", isGrounded);

    curTime += Time.deltaTime; // 시간 더해주기

    // Time Text 에 시간 반영
    time.text = (int)(gamePlayTime - curTime + 1) + "s";
}

 

 

4. GameEnd()

게임이 종료(성공)될 때 브금을 멈추고 효과음을 재생시켰다. 

public void GameEnd()
{
    worldBGM.StopBGM(); // 스탑!

    // 오디오 소스 재생
    PlaySound(gameClearClip);

    rigid.simulated = false;

    // 여기서 게임 매니저 게임 종료(성공) 메서드 호출
    GameManager.instance.WorldGameClear();
}

 

 

5. Die()

플레이어가 죽을 때 브금을 종료하고, 게임 실패 효과음을 재생시켰다. 그리고 현재 남아있던 체력 UI 를 모두 까인 모습으로 설정해줬다.

public void Die()
{
    worldBGM.StopBGM(); // 스탑!

    // 오디오 소스 재생
    PlaySound(deathClip);

    for (int i=heartIdx; i<heartUIs.Length; i++)
    {
        SetHeartUI(i); // 설정해용~~
    }

    StartCoroutine(DieCoroutine());
}

 

 

6. Attacked()

피가 깎인 걸 UI 에 반영하도록 했다. SetHeartUI 메서드를 호출했다.

private void Attacked()
{
    // 오디오 소스 재생
    PlaySound(attackedClip);

    // 피 깎기
    heart--;
    SetHeartUI(heartIdx);
    heartIdx++;

    if (heart == 0)
    {
        Die(); // 죽어
        return;
    }

    // 잠시 무적 상태로..
    StartCoroutine(Invincibility());
}

 

 

7. SetHeartUI(int idx)

체력바 UI 를 설정하는 메서드이다. 체력이 까이면 호출된다.

private void SetHeartUI(int idx)
{
    heartUIs[idx].GetComponent<Animator>().Play("Idle", 0, 0f); // 특정 애니메이션 초기화
    heartUIs[idx].GetComponent<Animator>().enabled = false;
    heartUIs[idx].transform.position = heartUIsPos[idx]; // 위치 바꿩
    heartUIs[idx].GetComponent<Image>().color = new Color32(255, 255, 255, 40);
}

 

2.5 GameManager 스크립트

더보기
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using static UnityEditor.Experimental.GraphView.Port;

public class GameManager : MonoBehaviour
{
    [Header("Game Data")]
    public float love; // 애정
    public float gold; // 골드
    public bool[] unLockedClays; // 점토들의 해금 여부
    public bool[] catchedClays; // 야생에서 잡아왔는지 확인용
    public int clayHouseLevel = 1; // 점토 아파트 레벨
    public int clayClickLevel = 1; // 점토 클릭 레벨
    public int[] clayHouseLoveList; // 업그레이드 비용 
    public int[] clayClickLoveList; // 업그레이드 비용
    public int curPossibleClayNum = 1; // 최대로 키울 수 있는 점토의 개수(1레벨은 1마리, 2레벨은 2마리...)

    [Header("Game Manager")]
    public static GameManager instance; // 싱글톤 이용하기 위함
    public string curScene;
    public bool isInitialized = false; // 데이터 초기화 완료 여부
    private Coroutine dataSetCoroutine; // 데이터 초기화 코루틴 저장

    [Header("GameDataUI")]
    public GameDataUIController gameDataUI;
    public delegate void SetInfoPanelHandler(string text); // 델리게이트 선언 
    public event SetInfoPanelHandler OnSetInfoPanel;

    [Header("Pool Manager")]
    public PoolManager poolManager;

    [Header("Coroutine")]
    public Coroutine updateTextUICoroutine;

    [Header("Game Exit")]
    public Button gameExitButton;

    [Header("Effect")]
    // 0: 점토 레벨업, 1: 점토 판매, 2: 점토 해금, 3: 업그레이드
    public ParticleSystem[] effectsPrefabs; // 프리팹 넣어놓기
    public ParticleSystem[] effects; // 관리용 변수
    public string[] effectGameObjectNames;

    [Header("Toy Control")]
    public int curToyIdx = -1; // 현재 선택된 장난감
    public RuntimeAnimatorController[] clayToyAnimators; // 가구랑 상호작용하는 애니메이터
    public string[] toyInfo; // 가구를 클릭하면 안내 판넬에 띄울 내용
    public delegate void SetClayHouseLevel(int houseLevel, int clickLevel);
    public SetClayHouseLevel OnSetClayHouseInfo;

    // Light & UI Control
    public delegate void SetLightHandler(bool flag);
    public event SetLightHandler OnSetLightHandler; // 여기에 빛 관리하는 메서드 연결해놓을 것(점토의 드래그 시작되면 이 델리게이트에 연결된 메서드를 호출하도록..)


    // 야생 콘텐츠 관련
    [Header("World Manager")]
    // 게임 시작 종료 여부
    public bool isGameStart = false; 
    public bool isGameEnd = false;
    public bool isGameClear = false;
    public int worldLevel = 0; // 월드 게임 난이도(0: 쉬움, 1: 보통, 2: 어려움)
    public int getClayIdx; // 얻은 점토 인덱스(이 값으로 새로운 점토를 소환할 것!) 씬 로드할 때 하면 될 듯?
    public int isFirst = -1; // 잡은 점토가 처음이면 isFirst 가 해당 점토으 인덱스로.. 처음 잡힌게 아니면 걍 -1임

    [Header("New Alam")]
    public GameObject newAlam;

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // 여기서 데이터 세팅하기
        // DataManager 준비될 때까지 기다려!
        if (dataSetCoroutine != null)
            StopCoroutine(dataSetCoroutine); // 이미 시작한 코루틴 있으면 끝내고 다시 시작

        dataSetCoroutine = StartCoroutine(OnSceneLoadedSetting()); // 정보 세팅
    }

    private void Awake()
    {
        // 싱글톤 이용
        if (instance != null && instance != this)
        {
            // 만약 이미 존재하면 그냥 없애
            Destroy(gameObject);
            return;
        }

        instance = this;
        DontDestroyOnLoad(gameObject); // 얘는 다른 씬으로 전환되어도 안 없앨 거임
    }

    private void OnEnable()
    {
        // 씬이 로드될 때마다 알아서 호출될 수 있도록..
        SceneManager.sceneLoaded += OnSceneLoaded; // 이벤트에 메서드 연결
    }

    private void OnDisable()
    {
        // 게임 오브젝트가 비활성화 될 때 이벤트에 연결해놓은 메서드 없애기
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }


    // 씬 로드될 때 수행되어야 하는 로직 모음집..
    private IEnumerator OnSceneLoadedSetting()
    {
        // 데이터 매니저 준비될 때까지 기다려!!!
        // DataManager 초기화 완료 기다리기
        while (!DataManager.instance.isInitialized)
        {
            yield return null;
        }

        Debug.Log("음 이제 DataManager 이용할 수 있어용~");


        curScene = SceneManager.GetActiveScene().name; // 씬 이름 가져오기


        // 씬에 따라 정보 세팅 다르게..
        if (curScene == "ClayHouse")
        {
            // 현재 씬이 클레이 하우스인 경우에만 호출 되도록..
            poolManager = GameObject.Find("PoolManager").GetComponent<PoolManager>(); // 풀매니저 찾아서 할당
            gameDataUI = GameObject.Find("GameDataUIController").GetComponent<GameDataUIController>(); // 게임 데이터 UI 찾아서 할당

            for (int i = 0; i < effectsPrefabs.Length; i++)
            {
                // 이펙트 생성해서 넣어놓기
                effects[i] = Instantiate(effectsPrefabs[i], GameObject.Find(effectGameObjectNames[i]).transform);
                effects[i].gameObject.SetActive(false); // 비활성화
            }

            gameExitButton = GameObject.Find("OptionPanelParent").transform.Find("Option Panel").transform.Find("Image").transform.Find("Exit Button").GetComponent<Button>();
            gameExitButton.onClick.AddListener(DataManager.instance.SaveGameData); // 게임 데이터 저장 메서드 연결
            gameExitButton.onClick.AddListener(GameExit); // 게임 종료 메서드 연결

            newAlam = GameObject.Find("CanvasParent").transform.Find("Canvas1").transform.Find("Left Button").transform.Find("Clay Button").transform.Find("NewAlam").gameObject;


            // 메서드 연결하기
            DataManager.instance.OnSave -= SetSaveData; // 중복 방지하기 위해 먼저 빼줌
            DataManager.instance.OnSave += SetSaveData;

            LoadDataSet(); // 데이터 반영
        }

        isInitialized = true; // 데이터 반영 완료
    }


    private void LoadDataSet()
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        // 저장된 게임 데이터가 있는 경우 데이터 가져와서 반영
        if (DataManager.instance.data.unlockClays != null)
        {
            // 저장된 데이터 반영해서 가져오기
            for (int i = 0; i < unLockedClays.Length; i++)
            {
                unLockedClays[i] = DataManager.instance.data.unlockClays[i];
                catchedClays[i] = DataManager.instance.data.catchClays[i];
            }
        }

        // 저장된 게임 수치 데이터가 있는 경우 데이터 가져와서 반영
        if (DataManager.instance.data.valueDatas != null)
        {
            // 저장된 데이터 반영해서 가져오기
            gold = DataManager.instance.data.valueDatas.gold;
            love = DataManager.instance.data.valueDatas.love;
            clayHouseLevel = DataManager.instance.data.valueDatas.clayHouseLevel;
            clayClickLevel = DataManager.instance.data.valueDatas.clayClickLevel;
            curPossibleClayNum = DataManager.instance.data.valueDatas.curPossibleClayNum;

            SetGoldLove(); // 로드한 데이터 반영해서 데이터 UI 업데이트..
            SetUpgradePanel(); // 델리게이트 호출
        }
    }

    public void SetUpgradePanel()
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        OnSetClayHouseInfo?.Invoke(clayHouseLevel, clayClickLevel); // UpgradePanel 클래스의 SetUpgardePanel() 메서드 호출
    }

    public void SetGoldLove()
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        // 로드한 데이터에 맞게 데이터 UI 변경할 수 있도록..

        // 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함. 
        if (updateTextUICoroutine != null)
        {
            StopCoroutine(updateTextUICoroutine);
        }

        updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("gold", gold, gold));
        updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("love", love, love));
    }

    // 재화 얻는 함수
    public void GetGold(float capacity)
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        // 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함. 
        if (updateTextUICoroutine != null)
        {
            StopCoroutine(updateTextUICoroutine);
        }

        updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("gold", gold + capacity, gold));
        gold += capacity;

        //PlayerPrefs.SetFloat("Gold", gold); // 데이터 저장
    }

    public void GetLove(float capacity)
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        // 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함. 
        if (updateTextUICoroutine != null)
        {
            StopCoroutine(updateTextUICoroutine);
        }

        updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("love", love + capacity, love));
        love += capacity;

        //PlayerPrefs.SetFloat("Love", love); // 데이터 저장
    }

    public void SetSaveData()
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        int size = unLockedClays.Length;

        DataManager.instance.data.unlockClays = new List<bool>();
        DataManager.instance.data.catchClays = new List<bool>();

        for (int i = 0; i < size; i++)
        {
            DataManager.instance.data.unlockClays.Add(unLockedClays[i]); // 해금 여부 저장
            DataManager.instance.data.catchClays.Add(catchedClays[i]); // 포획 여부 저장
        }

        // 수치 데이터 저장
        DataManager.instance.data.valueDatas = new ValueDatas();
        DataManager.instance.data.valueDatas.gold = gold;
        DataManager.instance.data.valueDatas.love = love;
        DataManager.instance.data.valueDatas.clayHouseLevel = clayHouseLevel;
        DataManager.instance.data.valueDatas.clayClickLevel = clayClickLevel;
        DataManager.instance.data.valueDatas.curPossibleClayNum = curPossibleClayNum;
    }


    public void GameExit()
    {
        // 게임 종료
        Application.Quit();
    }

    
    public void StartInfoPanel(string text)
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        // 연결된 메서드 실행시키기
        OnSetInfoPanel?.Invoke(text);
    }

    public void SetLightAndUI(bool flag)
    {
        if (curScene == "World") return; // 만약 현재 씬이 야생이면 그냥 빠져나가도록..

        OnSetLightHandler?.Invoke(flag); // flag 값을 전달해서 델리게이트에 연결된 메서드 호출 
    }

    public void MoveScene()
    {
        // 게임 매니저와 데이터 매니저의 isInitailized 값을 다시 false 로 바꿔주기
        isInitialized = false; // 다시 false 로..
        DataManager.instance.isInitialized = false;

        if (curScene == "ClayHouse")
        {
            DataManager.instance.SaveGameData(); // 씬 전환 하기 전 데이터 저장!

            
            ResetWorldGame(); // 월드 게임 정보 초기화


            curScene = "World"; // 씬 이름 바꿔주깅
            // 현재가 점토 집인 경우에는 World 씬으로 이동
            SceneManager.LoadScene("World");
        }
        else if (curScene == "World")
        {
            // 야생일 때는 딱히 저장할 데이터 없음

            curScene = "ClayHouse";
            // 현재 World 씬인 경우 점토 집 씬으로 이동 
            SceneManager.LoadScene("ClayHouse");
        }
    }

    public void ResetWorldGame()
    {
        // 야생으로 넘어갈 때 호출되는 메서드
        isGameStart = false;
        isGameEnd = false;
        isGameClear = false;
    }

    public void WorldGameClear()
    {
        // 야생에 성공했을 때 호출되는 메서드
        isGameStart = false;
        isGameEnd = true;
        isGameClear = true;
    }

    public void WorldGameFail()
    {
        // 야생에 성공했을 때 호출되는 메서드
        isGameStart = false;
        isGameEnd = true;
        isGameClear = false;
    }
}

 

2.6 GameManager 스크립트 변경 사항 설명

더보기

1. 변수

다음과 같은 변수가 추가됐다. isFirst 는 현재 잡은 점토가 처음인지 아닌지 판단하기 위해 선언했다. 만약 처음 잡힌 점토라면 newAlam 게임 오브젝트를 활성화 하도록 했다.

public int isFirst = -1; // 잡은 점토가 처음이면 isFirst 가 해당 점토으 인덱스로.. 처음 잡힌게 아니면 걍 -1임

[Header("New Alam")]
public GameObject newAlam;

 

2.7 UIController 스크립트

더보기
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor.SearchService;
using UnityEngine;
using UnityEngine.UI;

public class UIController : MonoBehaviour
{
    [Header("Heart UI")]
    public GameObject[] hearts;

    // 게임 시작, 종료 판넬
    [Header("GamePanel")]
    public GameObject gameStartPanel;
    public Button gameStartButton;

    public GameObject gameOverPanel;
    public Button gameOverButton;
    public Animator gameOverAnim;

    public GameObject gameClearPanel;
    public Button gameClearButton;
    public Animator gameClearAnim;
    public GameObject rewardClay;
    public Sprite[] clayImages;
    public GameObject newText; // 점토가 처음 잡힌 애면 newText 뜨도록!

    private void Awake()
    {
        // 버튼 정보 세팅하는 메서드 호출
        SetGameStartButton();
        SetGameEndButton();


        // 게임 시작 판넬 띄우도록
        gameStartPanel.SetActive(true);
    }

    private IEnumerator Start()
    {
        // 아직 게임 시작 안 했으면 좀 기다리기..
        while (!GameManager.instance.isGameStart)
        {
            yield return null;
        }

        for (int i=0; i<hearts.Length; i++)
        {
            // 하트 애니메이션 수행
            hearts[i].GetComponent<Animator>().Play("Move", -1, i*0.2f);
        }

        StartCoroutine(OpenGameEndPanel()); // 게임 종료 판넬 띄우는 코루틴 시작
    }

    public void CloseSelf(GameObject obj)
    {
        // 오브젝트 비활성화
        obj.SetActive(false);
    }

    public void GameStart()
    {
        // 게임 시작 신호 주기
        GameManager.instance.isGameStart = true;
    }

    public void SetGameStartButton()
    {
        // 게임 시작 버튼에 연결
        gameStartButton.onClick.AddListener(() => CloseSelf(gameStartPanel));
        gameStartButton.onClick.AddListener(GameStart);
    }

    public void SetGameEndButton()
    {
        // 집에 돌아가야행~~

        gameOverButton.onClick.AddListener(() => CloseSelf(gameOverPanel));
        gameClearButton.onClick.AddListener(() => CloseSelf(gameClearPanel));

        gameOverButton.onClick.AddListener(GameManager.instance.MoveScene);
        gameClearButton.onClick.AddListener(GameManager.instance.MoveScene);
    }

    public IEnumerator OpenGameEndPanel()
    {
        // 게임이 종료될 때까지 기다려
        while (!GameManager.instance.isGameEnd)
        {
            yield return null;
        }

        // 게임 성공 여부에 따라 판넬 띄우기
        if (GameManager.instance.isGameClear)
        {
            gameClearPanel.SetActive(true);

            // 보상 점토 이미지 설정
            rewardClay.GetComponent<Image>().sprite = clayImages[GameManager.instance.getClayIdx];
            rewardClay.GetComponent<Image>().SetNativeSize(); // UI 갱신
            Canvas.ForceUpdateCanvases();

            gameClearAnim.SetTrigger("Show"); // 애니메이션 수행

            // 처음으로 잡힌 점토면 new Text
            if (GameManager.instance.catchedClays[GameManager.instance.getClayIdx] == false)
            {
                newText.SetActive(true); // 활성화!
                GameManager.instance.isFirst = GameManager.instance.getClayIdx;
            }    
        }
        else if (!GameManager.instance.isGameClear)
        {
            gameOverPanel.SetActive(true);
            gameOverAnim.SetTrigger("Show"); // 애니메이션 수행
        }
    }
}

 

2.8 UIController 스크립트 변경 사항 설명

더보기

1. 변수

다음과 같은 변수를 추가했다.

 

rewardClay 는 게임 클리어 판넬에 현재 얻은 점토의 이미지를 띄우기 위해서 선언했다. clayImages 는 띄울 점토의 이미지를 가져오기 위해서 선언했다. 마지막으로 newText 는 만약 현재 잡은 점토가 처음 잡은 점토라면 new! 글자를 뜨게 하기 위해 선언했다.

public GameObject rewardClay;
public Sprite[] clayImages;
public GameObject newText; // 점토가 처음 잡힌 애면 newText 뜨도록!

 

 

2. OpenGameEndPanel()

처음으로 잡힌 점톤지 확인하고 그에 맞게 게임 클리어 판넬을 설정하는 로직을 추가했다.

public IEnumerator OpenGameEndPanel()
{
    // 게임이 종료될 때까지 기다려
    while (!GameManager.instance.isGameEnd)
    {
        yield return null;
    }

    // 게임 성공 여부에 따라 판넬 띄우기
    if (GameManager.instance.isGameClear)
    {
        gameClearPanel.SetActive(true);

        // 보상 점토 이미지 설정
        rewardClay.GetComponent<Image>().sprite = clayImages[GameManager.instance.getClayIdx];
        rewardClay.GetComponent<Image>().SetNativeSize(); // UI 갱신
        Canvas.ForceUpdateCanvases();

        gameClearAnim.SetTrigger("Show"); // 애니메이션 수행

        // 처음으로 잡힌 점토면 new Text
        if (GameManager.instance.catchedClays[GameManager.instance.getClayIdx] == false)
        {
            newText.SetActive(true); // 활성화!
            GameManager.instance.isFirst = GameManager.instance.getClayIdx;
        }    
    }
    else if (!GameManager.instance.isGameClear)
    {
        gameOverPanel.SetActive(true);
        gameOverAnim.SetTrigger("Show"); // 애니메이션 수행
    }
}

 

2.9 MapSpawner 스크립트

맵 난이도에 맞게 야생 씬의 global light 색을 바꾸는 로직을 추가했다. 단순해서 딱히 설명은 길게 하지 않는다.

더보기
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering.Universal;

public class MapSpawner : MonoBehaviour
{
    [Header("Map Contoller")]
    public GameObject[] mapPrefabs; // 현재 맵 프리팹
    public GameObject[] easyMapPrefabs;
    public GameObject[] normalMapPrefabs;
    public GameObject[] hardMapPrefabs;
    public List<GameObject>[] pool;


    public GameObject easyBackground; // 쉬움 단계 배경
    public GameObject normalBackground; // 보통 단계 배경
    public GameObject hardBackground; // 어려움 단계 배경


    public float curTime = 0;
    public float targetTime = 0.5f; // targetTime 마다 맵 생성
    public int mapCount;
    public int mapLevel; // 0: 쉬움, 1: 보통, 2: 어려움
    
    private Coroutine mapCoroutine;

    [Header("Light")]
    public Light2D mapLight; // 맵 난이도에 따라 배경 빛 색깔 다르도록..

    private void Awake()
    {
        mapLevel = GameManager.instance.worldLevel; // 게임 매니저의 맵 레벨로 설정해주기
        Color32 col = new Color32(255, 255, 255, 255); // 디폴트값

        // 맵 난이도에 맞게 mapCount 설정..
        if (mapLevel == 0)
        {
            easyBackground.SetActive(true); // 배경 활성화 
            mapPrefabs = easyMapPrefabs; // 현재 팹 프리팹을 이지맵으로 설정
        }
        else if (mapLevel == 1)
        {
            normalBackground.SetActive(true); // 배경 활성화 
            mapPrefabs = normalMapPrefabs; // 현재 팹 프리팹을 노멀맵으로 설정
            col = new Color32(150, 150, 150, 150);
        }
        else if (mapLevel == 2)
        {
            hardBackground.SetActive(true); // 배경 활성화 
            mapPrefabs = hardMapPrefabs; // 현재 팹 프리팹을 하드맵으로 설정
            col = new Color32(120, 120, 120, 120);
        }

        mapLight.color = col; // 색 설정
        mapCount = mapPrefabs.Length; // 크기 설정

        pool = new List<GameObject>[mapCount]; // 배열 만들기
        for (int i=0; i<mapCount; i++)
        {
            pool[i] = new List<GameObject>(); // 리스트 새로 만들기
        }
    }

    private IEnumerator Start()
    {
        // 무한 루프..
        // 야생 게임이 시작될 때까지 기다리기..
        while (!GameManager.instance.isGameStart)
        {
            yield return null;
        }

        mapCoroutine = StartCoroutine(SpawnMap()); // 맵 생성 코루틴 시작   
        StartCoroutine(GameEnd()); // 게임 종료 코루틴 시작
    }


    private IEnumerator SpawnMap()
    {
        while (true)
        {
            int mapIdx = Random.Range(0, mapCount);
            GameObject select = null;

            foreach (GameObject map in pool[mapIdx])
            {
                // 만약 놀고 있는 맵 게임 오브젝트를 발견하면 그거 활성화
                if (map.activeSelf == false)
                {
                    select = map;
                    map.SetActive(true); // 맵 활성화
                    break;
                }
            }

            // 발견 못 하면 새로 생성
            if (select == null)
            {
                select = Instantiate(mapPrefabs[mapIdx], transform);
                pool[mapIdx].Add(select); // 새로 생성한 게임 오브젝트를 풀에 넣기
            }

            yield return new WaitForSeconds(targetTime); // targetTime 만큼 기다리기
        }
    }

    private IEnumerator GameEnd()
    {
        while (!GameManager.instance.isGameEnd)
            yield return null;

        StopCoroutine(mapCoroutine); // 게임 끝났으니까 종료!
    }
}

 

2.10 ClayPanel 스크립트

더보기
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class ClayPanel : MonoBehaviour
{
    [Header("UI")]
    public Button pageLeftButton; // 페이지 왼쪽 버튼
    public Button pageRightButton; // 페이지 오른쪽 버튼
    public Button buyClayButton; // 점토 구매 버튼
    public Button unlockClayButton; // 점토 해금 버튼

    public Image lockedImage; // 잠금된 점토 이미지
    public Image clayImage; // 점토 이미지
    public Text clayName; // 점토 이름
    public Text buyPrice; // 점토 가격

    public Button closeButton;
    public GameObject lockedPage; // 잠금 페이지
   

    [Header("Control")]
    public int pageIdx = 0; // 페이지 인덱스
    public int maxIdx;
    public int minIdx = 0;

    [Header("Effect")]
    public int effectIdx = 2;

    [Header("Audio")]
    private AudioSource clayPanelAudio;
    public AudioClip unlockClip;
    public AudioClip buyClip;
    public AudioClip failClip;
    public AudioClip showClip;


    private void Awake()
    {
        clayPanelAudio = GetComponent<AudioSource>();
    }

    private IEnumerator Start()
    {
        // 게임 매니저가 준비 될 때까지 기다령~~
        while (!GameManager.instance.isInitialized)
            yield return null;

        maxIdx = GameManager.instance.poolManager.clayPrefabs.Length;

        pageLeftButton.onClick.AddListener(DownPageIdx);
        pageLeftButton.onClick.AddListener(SetClayPanel);

        pageRightButton.onClick.AddListener(UpPageIdx);
        pageRightButton.onClick.AddListener(SetClayPanel);

        // 잡아온 점토가 처음으로 잡힌 애면 별표 켜지도록..
        if (GameManager.instance.isFirst != -1)
            GameManager.instance.newAlam.SetActive(true);
    }

    private void OnEnable()
    {
        // 활성화 될 때 호출되는 함수

        ResetClayPanel();
    }

    public void ResetClayPanel()
    {
        pageIdx = 0;
        SetButtonInfo(); // 버튼 설정해주기
    }

    public void SetClayPanel()
    {
        // 새로 잡아온 점토 페이지를 확인하면 점토 구매 버튼 위 별표 비활성화
        if (GameManager.instance.isFirst == pageIdx)
        {
            GameManager.instance.newAlam.SetActive(false);
        }

        Clay clay = GameManager.instance.poolManager.clayPrefabs[pageIdx].GetComponent<Clay>();
        if (GameManager.instance.unLockedClays[pageIdx] == false)
        {
            lockedPage.SetActive(true); // 해금이 안된 경우엔 잠금 판넬 활성화..
        }
        else
        {
            lockedPage.SetActive(false); // 해금된 경우엔 잠금 판넬 비활성화..
        }

        // 페이지 인덱스에 맞게 설정
        lockedImage.sprite = clay.clay; // 점토의 이미지 가져오기
        clayImage.sprite = clay.clay; 
        clayName.text = clay.clayName; // 점토 이름 가져오기
        buyPrice.text = clay.buyPrice + ""; // 점토 가격 가져오기      
    }

    public void UpPageIdx()
    {
        if (pageIdx >= maxIdx - 1) {
            GameManager.instance.StartInfoPanel("마지막 페이지입니다.");
            PlaySound(failClip); // 효과음
            return; // 빠져나가기..
        }
        pageIdx++;

        SetButtonInfo();
        PlaySound(showClip); // 효과음
    }
    public void DownPageIdx()
    {
        if (pageIdx <= 0) {
            GameManager.instance.StartInfoPanel("처음 페이지입니다.");
            PlaySound(failClip); // 효과음
            return; // 빠져나가기..
        }
        pageIdx--;
        SetButtonInfo();
        PlaySound(showClip); // 효과음
    }

    private void SetButtonInfo()
    {
        ColorBlock col = unlockClayButton.colors;

        // 만약 야생에서 점토를 잡아왔으면 해금하기 버튼 노란색으로 바꿔주기
        if (GameManager.instance.catchedClays[pageIdx])
        {
            col.normalColor = new Color32(255, 220, 90, 255); // 노란색
            col.highlightedColor = new Color32(255, 220, 90, 255); // 노란색

            unlockClayButton.colors = col; // 색 만들어 놓은거 할당해주기
        }
        else
        {
            col.normalColor = new Color32(255, 255, 255, 255); // 흰색
            col.highlightedColor = new Color32(255, 255, 255, 255); // 흰색

            unlockClayButton.colors = col; // 색 만들어 놓은거 할당해주기
        }

        unlockClayButton.onClick.RemoveAllListeners(); // 일단 다 지웡
        unlockClayButton.onClick.AddListener(() => Unlock(pageIdx)); // Unlock 메서드 추가

        buyClayButton.onClick.RemoveAllListeners(); // 일단 다 지웡
        buyClayButton.onClick.AddListener(() => BuyClay(pageIdx)); // BuyClay 메서드 추가
    }

    public void Unlock(int idx)
    {
        // 야생에서 아직 안 잡았으면 해금 못하도록..
        if (!GameManager.instance.catchedClays[pageIdx])
        {
            // 안내 판넬 띄우기
            GameManager.instance.StartInfoPanel("야생에서 잡아와야 해요!");
            PlaySound(failClip); // 효과음
            return;
        }

        GameManager.instance.unLockedClays[idx] = true;
        PlayEffect(effectIdx); // 이펙트 소환
        SetClayPanel();
        PlaySound(unlockClip); // 효과음
    }

    public void PlayEffect(int idx)
    {
        if (GameManager.instance.effects[idx].gameObject.activeSelf == false)
            GameManager.instance.effects[idx].gameObject.SetActive(true); // 활성화하기
        GameManager.instance.effects[idx].Play();
    }

    public void BuyClay(int idx)
    {
        int price = GameManager.instance.poolManager.clayPrefabs[idx].GetComponent<Clay>().buyPrice;

        // 돈이 충분하고 공간이 있으면 점토 구매
        if (GameManager.instance.gold >= price && (GameManager.instance.curPossibleClayNum > GameManager.instance.poolManager.curClayNum))
        {
            GameManager.instance.GetGold(-price);
            GameManager.instance.poolManager.GetGameObject(idx); // 동물 get!
            GameManager.instance.poolManager.curClayNum++; // 점토 개수 증가
            
            
            PlaySound(buyClip); // 효과음
        }
        else if (GameManager.instance.gold < price)
        {
            // 안내 판넬 띄우기
            GameManager.instance.StartInfoPanel("돈이 부족해요 ㅠ_ㅠ");
            PlaySound(failClip); // 효과음
            return;
        }
        else if (GameManager.instance.curPossibleClayNum <= GameManager.instance.poolManager.curClayNum) {
            // 안내 판넬 띄우기
            GameManager.instance.StartInfoPanel("집이 너무 좁아요 ㅠ_ㅠ");
            PlaySound(failClip); // 효과음
            return;
        }  
    }

    public void ClosePanel()
    {
        gameObject.SetActive(false); // 활성화 끄기..
    }

    private void PlaySound(AudioClip clip)
    {
        clayPanelAudio.clip = clip;
        clayPanelAudio.Play();
    }
}

 

2.11 ClayPanel 스크립트 변경 사항 설명

더보기

1. SetClayPanel()

새로 잡아온 점토 페이지를 확인하면 점토 구매 버튼 위 별표를 비활성화 하는 로직을 추가했다.

public void SetClayPanel()
{
    // 새로 잡아온 점토 페이지를 확인하면 점토 구매 버튼 위 별표 비활성화
    if (GameManager.instance.isFirst == pageIdx)
    {
        GameManager.instance.newAlam.SetActive(false);
    }

    Clay clay = GameManager.instance.poolManager.clayPrefabs[pageIdx].GetComponent<Clay>();
    if (GameManager.instance.unLockedClays[pageIdx] == false)
    {
        lockedPage.SetActive(true); // 해금이 안된 경우엔 잠금 판넬 활성화..
    }
    else
    {
        lockedPage.SetActive(false); // 해금된 경우엔 잠금 판넬 비활성화..
    }

    // 페이지 인덱스에 맞게 설정
    lockedImage.sprite = clay.clay; // 점토의 이미지 가져오기
    clayImage.sprite = clay.clay; 
    clayName.text = clay.clayName; // 점토 이름 가져오기
    buyPrice.text = clay.buyPrice + ""; // 점토 가격 가져오기      
}

 

 


 

 

3. 결과물

 

 

 

 

'유니티 프로젝트/점토게임' 카테고리의 다른 글
  • [개발일지] 33. 메인 씬 오디오 적용 & UI 뒤쪽 게임 오브젝트 클릭 방지
  • [개발일지] 32. 야생에서 잡아온 점토 생성
  • [개발일지] 32. 씬 전환시 데이터 저장&적용
  • [개발일지] 31. 야생 판넬 제작 & 체력바 애니메이션 적용 & 씬 이동
dubu0721
dubu0721
dubu0721 님의 블로그 입니다.
  • dubu0721
    dubu0721 님의 블로그
    dubu0721
  • 전체
    오늘
    어제
    • 분류 전체보기 (334)
      • 프로그래밍언어론 정리 (0)
      • 컴퓨터네트워크 정리 (5)
      • 알고리즘&자료구조 공부 (64)
        • it 취업을 위한 알고리즘 문제풀이 입문 강의 (60)
        • 학교 알고리즘 수업 (3)
        • 실전프로젝트I (0)
      • 백준 문제 (193)
        • 이분탐색 (7)
        • 투포인트 (10)
        • 그래프 (7)
        • 그리디 (24)
        • DP (25)
        • BFS (15)
        • MST (7)
        • KMP (4)
        • Dijkstra (3)
        • Disjoints Set (4)
        • Bellman-Ford (2)
        • 시뮬레이션 (3)
        • 백트래킹 (15)
        • 위상정렬 (5)
        • 자료구조 (25)
        • 기하학 (1)
        • 정렬 (11)
        • 구현 (8)
        • 재귀 (8)
        • 수학 (8)
      • 유니티 공부 (11)
        • 레트로의 유니티 게임 프로그래밍 에센스 (11)
        • 유니티 스터디 자료 (0)
        • C# 공부 (0)
      • 유니티 프로젝트 (48)
        • 케이크게임 (13)
        • 점토게임 (35)
      • 언리얼 공부 (10)
        • 이득우의 언리얼 프로그래밍 (10)
      • 진로 (1)
      • 논문 읽기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    dp
    그래프
    우선순위큐
    투포인터
    유니티
    유니티 공부 정리
    정렬
    스택
    레트로의 유니티 프로그래밍
    티스토리챌린지
    BFS
    C#
    시뮬레이션
    해시
    백트래킹
    맵
    큐
    이벤트 트리거
    유니티 프로젝트
    자료구조
    이득우
    이분탐색
    바킹독
    언리얼
    그리디
    오블완
    수학
    골드메탈
    백준
    재귀
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dubu0721
[개발일지] 34[완결]. 야생 UI 수정 & 메인 씬 기능 추가
상단으로

티스토리툴바