[개발일지] 7. 점토 클릭 시 애정 얻기 & 점토 스프라이트 변경

2025. 1. 10. 18:22·유니티 프로젝트/점토게임

0. 들어가기 전에

점토를 클릭할 때 레벨에 맞는 애정을 획득할 수 있도록 했다. 점토를 클릭하다 보면 레벨업을 하는데 최고 레벨에 도달하면 점토의 모습이 동물로 변하도록 했다.

 

레벨업을 할 때마다 점토의 크기가 커지도록 하기 위해서 각 레벨에 맞게 애니메이터를 할당해주었다.

 

점토가 다 자라서 동물이 되면 스프라이트 이미지 상 움직이는 방향에 맞게 이미지를 좌우반전시켰다.

 

 


 

 

1. 스크립트

이번에 만든 스크립트는 ClayController 이고, ClayMove 스크립트에 변동사항이 생겼다.

 

1.1 ClayController 스크립트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClayController : MonoBehaviour
{
    [Header("Clay Data")]
    public float[] loves; // 점토를 클릭했을 때 얻는 애정 수치(1~5 레벨)
    public int[] touchCnts; // 해당 요소만큼 클릭되면 레벨업
    public int clayLevel = 1; // 1레벨에서 시작(5레벨까지 있음)
    public int curTouchCnt = 0;

    [Header("Animation")]
    Animator anim; // 점토가 터치될 때 애니메이션 실행하기 위함
    public RuntimeAnimatorController[] animators;

    [Header("Sprites")]
    public Sprite clay; // 점토 모습
    public Sprite animal; // 다 자란 동물 모습


    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    // 점토가 터치되면 저절로 호출됨
    private void OnMouseDown()
    {
        Debug.Log("터치됨!");
        anim.SetTrigger("doTouch");
        GameManager.instance.GetLove(loves[clayLevel - 1]); // 레벨에 맞는 수치를 함수로 넘겨주기
        curTouchCnt++;

        // 이미 점토의 레벨이 최고 레벨에 도달했으면 밑으로 진입 안 하도록..
        if (clayLevel != 5)
        {
            if (curTouchCnt == touchCnts[clayLevel - 1])
            {
                clayLevel++; // 레벨 1 증가
                curTouchCnt = 0; // 초기화
                anim.runtimeAnimatorController = animators[clayLevel - 1]; // 레벨에 맞는 애니메이터로 바꿔주기

                if (clayLevel == 5)
                    gameObject.GetComponent<SpriteRenderer>().sprite = animal;
            }
        }
    }
}

 

1.2 ClayController 스크립트 설명

ClayController 스크립트에 대한 설명은 다음과 같다.

더보기
더보기

1. 변수

  • loves: 각 레벨마다 획득할 수 있는 애정의 수치가 다르도록 하기 위해서 선언했다.
  • touchCnts: 해당 요소만큼 클릭되면 레벨업 되도록 하기 위해 선언했다.
  • clayLevel: 현재 점토의 레벨을 나타내기 위한 변수이다.
  • curTouchCnt: 현재 레벨에서 점토를 클릭한 횟수를 나타내기 위한 변수이다.
  • anim: 점토가 터치될 때 애니메이션을 실행하도록 하기 위한 변수이다
  • animators: 각 레벨에 맞는 애니메이터를 할당해주기 위한 변수이다.
  • clay: 점토 모습 스프라이트
  • animal: 동물 모습 스프라이트
[Header("Clay Data")]
public float[] loves; // 점토를 클릭했을 때 얻는 애정 수치(1~5 레벨)
public int[] touchCnts; // 해당 요소만큼 클릭되면 레벨업
public int clayLevel = 1; // 1레벨에서 시작(5레벨까지 있음)
public int curTouchCnt = 0;

[Header("Animation")]
Animator anim; // 점토가 터치될 때 애니메이션 실행하기 위함
public RuntimeAnimatorController[] animators;

[Header("Sprites")]
public Sprite clay; // 점토 모습
public Sprite animal; // 다 자란 동물 모습

 

 

2. Awake()

anim 변수에 현재 게임 오브젝트의 Animator 컴포넌트를 할당했다.

private void Awake()
{
    anim = GetComponent<Animator>();
}

 

 

3. OnMouseDown()

이는 마우스로 게임 오브젝트를 터치했을 때 자동으로 호출되는 함수이다. 직접 호출할 필요가 없다.

 

터치 상태의 애니메이션을 실행하도록 하기 위해 anim.SetTrigger 메서드를 실행했다. 그리고 현재 점토 레벨에 맞는 애정을 얻게 하기 위해서 GetLove 메서드에 매개변수로 loves[clayLevel - 1] 값을 넣어주었다. 그 후, curTouchCnt 값을 +1 해주었다.

 

만약 점토의 레벨이 이미 최고 상태라면 더 이상 레벨업 할 수 없으므로 if (clayLevel != 5) 를 통해 걸러냈다. 만약 5레벨이 아니라면 진입할 수 있도록 했다.

 

진입하면 점토의 레벨이 1 증가하고, curTouchCnt 값은 다시 0이 되고, 게임 오브젝트의 애니메이터가 레벨에 맞는 애니메이터로 변경될 수 있도록 했다.

 

최고레벨이 되면 점토의 스프라이트를 동물 모습으로 변경해주어서 다 자랐음을 표현하도록 했다.

// 점토가 터치되면 저절로 호출됨
private void OnMouseDown()
{
    Debug.Log("터치됨!");
    anim.SetTrigger("doTouch");
    GameManager.instance.GetLove(loves[clayLevel - 1]); // 레벨에 맞는 수치를 함수로 넘겨주기
    curTouchCnt++;

    // 이미 점토의 레벨이 최고 레벨에 도달했으면 밑으로 진입 안 하도록..
    if (clayLevel != 5)
    {
        if (curTouchCnt == touchCnts[clayLevel - 1])
        {
            clayLevel++; // 레벨 1 증가
            curTouchCnt = 0; // 초기화
            anim.runtimeAnimatorController = animators[clayLevel - 1]; // 레벨에 맞는 애니메이터로 바꿔주기

            if (clayLevel == 5)
                gameObject.GetComponent<SpriteRenderer>().sprite = animal;
        }
    }
}

 

1.3 ClayMove 스크립트

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public enum MoveDirection
{
    Minus = -1, Plus = 1, Idle = 0 
}

public class ClayMove : MonoBehaviour
{
    [Header("ClayMovement")]
    public float moveSpeed; // 움직이는 속도

    public MoveDirection moveDirX; // x 축 방향
    public MoveDirection moveDirY; // y 축 방향

    public bool isMoving; // 돌아다니는지 여부 확인
    public bool isReturning; // 중점으로 돌아가는 중인지 여부 확인

    public GameObject targetPosObj; // 중점에 있는 게임 오브젝트 할당해주기

    private Coroutine randomMoveCoroutine;

    [Header("Animation")]
    public Animator anim;


    void Start()
    {
        // 코루틴의 핸들을 저장하고 이를 통해 중단하는 것이 좋음
        randomMoveCoroutine = StartCoroutine(RandomMove());

        anim = GetComponent<Animator>();
    }

    void Update()
    {
        if (!isReturning)
        {
            // Time.deltaTime 을 곱해주는 이유는 게임 오브젝트가 순간이동 하는 것을 막기 위함.
            transform.Translate(moveSpeed * Time.deltaTime * new Vector2((int)moveDirX, (int)moveDirY));

            // x 축 이동 방향이 오른쪽이면 sprite 를 뒤집도록..
            if (moveDirX == MoveDirection.Plus)
                gameObject.GetComponent<SpriteRenderer>().flipX = true;
            else if (moveDirX == MoveDirection.Minus)
                gameObject.GetComponent<SpriteRenderer>().flipX = false;
        }

        // Idle 상태가 아니라면 walk 애니메이션 수행하도록
        if (moveDirX != 0 || moveDirY != 0)
        {
            anim.SetBool("isWalk", true);
        }
        else
        {
            anim.SetBool("isWalk", false);
        }
    }

    // 3초에 한 번씩 이동 방향 바꾸도록 하는 코루틴..
    // 코루틴은 IEnumerator 를 반환함
    private IEnumerator RandomMove()
    {
        while (true)
        {
            // 방향 랜덤으로 설정
            moveDirX = (MoveDirection)Random.Range(-1, 2);
            moveDirY = (MoveDirection)Random.Range(-1, 2);

            yield return new WaitForSeconds(3f); // 3초 동안 기다령 
        }
    }

    private IEnumerator ReturnToCenter()
    {
        isReturning = true;

        float curTime = 0f;
        float duration = 5f; // 중점으로 돌아가는 시간 5초 만큼 줄 것..

        Vector2 targetPos = targetPosObj.transform.position; // 중점에 있는 오브젝트의 위치 할당

        while (curTime < duration)
        {
            // 현재 점토의 위치가 목표 지점보다 왼쪽에 있으면 오른쪽을 보도록..
            if (targetPos.x > transform.position.x)
                gameObject.GetComponent<SpriteRenderer>().flipX = true;
            else if (targetPos.x < transform.position.x)
                gameObject.GetComponent<SpriteRenderer>().flipX = false;

            transform.position = Vector2.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime * 1.5f);
            curTime += Time.deltaTime;

            yield return null; // 다음 프레임까지 대기
        }

        isReturning = false; // 랜덤 이동 재개
        randomMoveCoroutine = StartCoroutine(RandomMove()); // 다시 시작시키기
    }


    // 콜라이더 컴포넌트를 가진 게임 오브젝트랑 부딪히면 이 함수로 진입
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (isReturning) return; // 만약 이미 돌아가고 있는 중에 또 부딪히면 걍 나가라..

        // 부딪힌 게임 오브젝트의 태그가 Target 이면 ReturnToCenter 코루틴 호출하도록
        if (collision.gameObject.CompareTag("Wall"))
        {
            // 랜덤 이동 코루틴은 중단시키기
            StopCoroutine(randomMoveCoroutine);

            // 중앙 복귀 코루틴 호출
            StartCoroutine(ReturnToCenter());
        }
    }
}

 

 

1.4 ClayMove 스크립트 변경 사항 설명

더보기
더보기

1. Update()

x 축 이동 방향이 오른쪽이면 sprite 를 뒤집도록 하는 로직을 추가했다. 점토가 다 자라서 동물이 되면 방향이 구분된다. 이때 동물이 쳐다보는 방향과 이동 방향이 다르면 이상하기 때문에 이를 위해 추가했다.

// x 축 이동 방향이 오른쪽이면 sprite 를 뒤집도록..
if (moveDirX == MoveDirection.Plus)
    gameObject.GetComponent<SpriteRenderer>().flipX = true;
else if (moveDirX == MoveDirection.Minus)
    gameObject.GetComponent<SpriteRenderer>().flipX = false;

 

 

2. ReturnToCenter()

점토가 벽에 닿아서 중앙으로 돌아갈 때 스프라이트의 방향을 조정하기 위해 추가한 구문이다. 만약 점토가 중앙보다 왼쪽에 위치한다면 오른쪽을 쳐다보도록, 오른쪽에 위치한다면 왼쪽을 쳐다보도록 했다.

// 현재 점토의 위치가 목표 지점보다 왼쪽에 있으면 오른쪽을 보도록..
if (targetPos.x > transform.position.x)
    gameObject.GetComponent<SpriteRenderer>().flipX = true;
else if (targetPos.x < transform.position.x)
    gameObject.GetComponent<SpriteRenderer>().flipX = false;

 

 


 

 

2. 결과물

 

정상적으로 작동하는 모습을 확인할 수 있다.

 

 


 

 

3. 참고자료

RuntimeAnimatorContoller 에 대해 설명해놓은 글이 있길래 가져왔다.

 

3.1 RuntimeAnimatorController

유니티 기본기 : 애니메이터(Animator) 2편. 애니메이터 기초 | by Supercent.official | Supercent Blog 슈퍼센트 블로그 | Medium

 

유니티 기본기 : 애니메이터(Animator) 2편

애니메이터 기초

medium.com

 

 

 

 

 

 

 

'유니티 프로젝트/점토게임' 카테고리의 다른 글
  • [개발일지] 9. 풀 매니저 & 점토 데이터 저장&불러오기
  • [개발일지] 8. 점토 드래그 기능
  • [개발일지] 6. 재화, 점토 판매 UI
  • [개발일지] 5. 점토 구매, 집 업그레이드, 야생 UI 버튼 & 애니메이션
dubu0721
dubu0721
dubu0721 님의 블로그 입니다.
  • dubu0721
    dubu0721 님의 블로그
    dubu0721
  • 전체
    오늘
    어제
    • 분류 전체보기 (545) N
      • 연구 (104) N
        • 강의 (17)
        • 논문 읽기 (36) N
        • episodic-memory (51)
      • 백준 문제 (261)
        • 이분탐색 (7)
        • 투포인트 (13)
        • 그래프 (11)
        • 그리디 (27)
        • DP (26)
        • BFS (35)
        • MST (8)
        • KMP (4)
        • Dijkstra (3)
        • Disjoints Set (11)
        • Bellman-Ford (2)
        • 플로이드-워셜 (1)
        • 시뮬레이션 (3)
        • 백트래킹 (24)
        • 위상정렬 (9)
        • 자료구조 (30)
        • 기하학 (1)
        • 정렬 (11)
        • 구현 (13)
        • 재귀 (8)
        • 수학 (11)
        • 트리 (1)
      • ROS 2 공부 (1)
      • 알고리즘&자료구조 공부 (64)
        • it 취업을 위한 알고리즘 문제풀이 입문 강의 (60)
        • 학교 알고리즘 수업 (3)
        • 실전프로젝트I (0)
      • 유니티 공부 (11)
        • 레트로의 유니티 게임 프로그래밍 에센스 (11)
      • 유니티 프로젝트 (48)
        • 케이크게임 (13)
        • 점토게임 (35)
      • 언리얼 공부 (10)
        • 이득우의 언리얼 프로그래밍 (10)
      • 학교 수업 정리 (41)
        • 컴퓨터네트워크 정리 (5)
        • 프로그래밍언어론 정리 (5)
        • 음성및오디오인식 (6)
        • 운영체제의실제 (18)
        • 인공지능 (7)
      • 진로 (1)
      • 노트북환경설정 (1)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dubu0721
[개발일지] 7. 점토 클릭 시 애정 얻기 & 점토 스프라이트 변경
상단으로

티스토리툴바