[개발일지] 8. 점토 드래그 기능

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

0. 들어가기 전에

왼쪽 마우스로 점토를 꾹 누르면 점토 드래그 기능이 수행되도록 만들었다.

 

나중에 다 자란 점토를 가져다 팔기 위해서 꼭 필요한 기능이다. 주머니에 다 자란 점토를 드래그&드롭 하면 팔리도록 할 것이다.

 

 


 

 

1. 게임 오브젝트

점토를 바닥에 내려놓는 장소가 불가능 구역이라면 드래그 하기 전 위치로 돌아갈 수 있도록 하려고 했다.

 

이를 위해서는 불가능 구역을 지정해야 하는데 나는 빈 게임 오브젝트를 두 개 만들어서 x, y 좌표를 가지고 불가능 구역을 판단했다.

 

즉, 왼쪽 상단의 노란색 게임 오브젝트의 x 축보다 작거나 y 축보다 크거나, 오른쪽 상단의 노란색 게임 오브젝트의 x 축보다 크거나 y 축보다 작거나를 기준으로 불가능 구역을 판단했다.

 

 


 

 

2. 스크립트

이번에 새로 만든 스크립트는 없고 기존의 ClayController 스크립트를 수정했다.

 

2.1 ClayController 스크립트

using System.Collections;
using System.Collections.Generic;
using TreeEditor;
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; // 다 자란 동물 모습

    [Header("Drag Clay")]
    public float targetTime = 1; // 드래그 시작할 수 있는 시간
    public float curTime; // 현재 시간
    public Vector3 prevPos; // 점토를 드래그 하기 전 위치


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

    // 점토가 터치되면 저절로 호출됨
    private void OnMouseDown()
    {
        prevPos = transform.position; // 드래그 하기 전 위치 저장

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

    // 점토 드래그할 때 호출되는 함수
    private void OnMouseDrag()
    {
        curTime += Time.deltaTime;

        // 만약 현재 시간이 targetTime 보다 크거나 같다면 점토가 마우스를 따라오도록 하기..
        if (curTime >= targetTime)
        {
            // 마우스 위치를 가져온 후 Z 축을 카메라와의 거리로 설정한다
            Vector3 mousePosition = Input.mousePosition;
            mousePosition.z = Camera.main.WorldToScreenPoint(transform.position).z;

            // 스크린 좌표를 월드 좌표로 변환
            Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition);

            // 오브젝트의 위치를 마우스의 월드 좌표로 이동
            transform.position = worldPosition;

            // 이 경우에는 UI 보다도 앞에 갈 수 있도록..
            gameObject.GetComponent<SpriteRenderer>().sortingOrder = 10;
        }
    }

    // 점토 내려놓을 때 호출되는 함수
    private void OnMouseUp()
    {
        curTime = 0;

        if (transform.position.x < -6.5 || transform.position.x > 6.5 || transform.position.y < -3 || transform.position.y > 0.6)
            transform.position = prevPos;

        // 다시 UI 보다 아래로 가도록..
        gameObject.GetComponent<SpriteRenderer>().sortingOrder = 1;
    }
}

 

2.2 ClayController 스크립트 변경 사항 설명

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

더보기

1. 변수

마우스 왼쪽 버튼으로 점토를 계속 누르고 있다가 일정 시간에 도달하면 점토가 마우스를 따라오도록 하기 위해 targetTime 과 curTime 변수를 선언했다. curTime 의 값이 targetTime 보다 크거나 같아지면 점토가 마우스를 따라오도록 했다.

[Header("Drag Clay")]
public float targetTime = 1; // 드래그 시작할 수 있는 시간
public float curTime; // 현재 시간
public Vector3 prevPos; // 점토를 드래그 하기 전 위치

 

2. OnMouseDown() 

OnMouseDown() 메서드는 왼쪽 마우스가 클릭(눌릴 때) 될 때 호출되는 메서드이다. 메서드에 진입하자마자 점토의 현재 위치를 prevPos 변수에 저장하도록 했다. 만약 점토를 불가능 영역에 내려놓으면 이 위치로 포지션을 설정하기 위함이다.

prevPos = transform.position; // 드래그 하기 전 위치 저장

 

 

3. OnMouseDrag()

이 메서드는 왼쪽 마우스 버튼을 클릭하고 손을 떼지 않는 중에 호출되는 메서드이다.

 

curTime 에 계속해서 시간을 더하는데 이 값이 targetTime 보다 크거나 같아지면 점토의 위치가 마우스의 위치랑 같아지도록 한다.

 

Input.mousePosition 은 스크린 좌표이다. 이를 점토가 돌아다니는 세상인 월드 좌표로 변환해야 점토가 화면상에서 마우스를 따라다니는 것처럼 보이게 할 수 있다.

 

스크린 좌표를 월드 좌표로 변환하기 위해서는 Camera.main.ScreenToWorldPoint 메서드를, 반대의 경우에는 Camera.main.WorldToScreenPoint 메서드를 이용한다.

 

게임 오브젝트의 sortingOrder 값을 10으로 올렸는데 이유는 점토를 마우스로 드래그 하는 순간에는 UI 보다 앞으로 나오면 좋겠다고 생각했기 때문이다. 이렇게 하지 않으면 UI 에 점토가 가려져서 마음에 들지 않았다.

// 점토 드래그할 때 호출되는 함수
private void OnMouseDrag()
{
    curTime += Time.deltaTime;

    // 만약 현재 시간이 targetTime 보다 크거나 같다면 점토가 마우스를 따라오도록 하기..
    if (curTime >= targetTime)
    {
        // 마우스 위치를 가져온 후 Z 축을 카메라와의 거리로 설정한다
        Vector3 mousePosition = Input.mousePosition;
        mousePosition.z = Camera.main.WorldToScreenPoint(transform.position).z;

        // 스크린 좌표를 월드 좌표로 변환
        Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition);

        // 오브젝트의 위치를 마우스의 월드 좌표로 이동
        transform.position = worldPosition;

        // 이 경우에는 UI 보다도 앞에 갈 수 있도록..
        gameObject.GetComponent<SpriteRenderer>().sortingOrder = 10;
    }
}

 

 

4. OnMouseUp()

왼쪽 마우스에서 손가락을 떼면 호출되는 메서드이다.

 

이 메서드에 진입하면 curTime 변수의 값을 0으로 만든다. 불가능 영역에 도달했음은 조건문을 통해 판단했고, 조건이 만족되면 위치를 prevPos 로 설정해줬다.

 

그리고 sortingOrder 의 값을 다시 원상태로 되돌려서 UI 보다 뒤로 갈 수 있도록 했다.

// 점토 내려놓을 때 호출되는 함수
private void OnMouseUp()
{
    curTime = 0;

    if (transform.position.x < -6.5 || transform.position.x > 6.5 || transform.position.y < -3 || transform.position.y > 0.6)
        transform.position = prevPos;

    // 다시 UI 보다 아래로 가도록..
    gameObject.GetComponent<SpriteRenderer>().sortingOrder = 1;
}

 

 


 

 

3. 결과물

 

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

 

 


 

 

4. 참고자료

오늘 이용한 개념에 대해 설명해놓은 글들을 가져와봤다.

 

4.1 ScreenToWorldPoint

Unity - Scripting API: Camera.ScreenToWorldPoint

 

Unity - Scripting API: Camera.ScreenToWorldPoint

World space coordinates can still be calculated even when provided as an off-screen coordinate, for example for instantiating an off-screen object near a specific corner of the screen. To make sure the world space point is part of the camera's view volume,

docs.unity3d.com

 

4.2 OnMouse 함수들

유니티 마우스, 터치 관련 함수

 

유니티 마우스, 터치 관련 함수

사용하기 위해서는 해당 오브젝트에 Collider 컴포넌트 필수 1) void OnMouseDown() : 해당 오브젝트에서 마우스클릭이 될때 실행 2) void OnMouseUp() : 해당 오브젝트에서 마우스클릭이 해제 될때 실행 3) void

sshoreng.tistory.com

 

 

 

'유니티 프로젝트/점토게임' 카테고리의 다른 글
  • [개발일지] 10. 점토 판매 기능
  • [개발일지] 9. 풀 매니저 & 점토 데이터 저장&불러오기
  • [개발일지] 7. 점토 클릭 시 애정 얻기 & 점토 스프라이트 변경
  • [개발일지] 6. 재화, 점토 판매 UI
dubu0721
dubu0721
dubu0721 님의 블로그 입니다.
  • dubu0721
    dubu0721 님의 블로그
    dubu0721
  • 전체
    오늘
    어제
    • 분류 전체보기 (334) N
      • 컴퓨터네트워크 정리 (5)
      • 알고리즘&자료구조 공부 (64)
        • it 취업을 위한 알고리즘 문제풀이 입문 강의 (60)
        • 학교 알고리즘 수업 (3)
        • 실전프로젝트I (0)
      • 백준 문제 (193) N
        • 이분탐색 (7)
        • 투포인트 (10)
        • 그래프 (7)
        • 그리디 (24) N
        • DP (25)
        • BFS (15) N
        • 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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dubu0721
[개발일지] 8. 점토 드래그 기능
상단으로

티스토리툴바