본문 바로가기
C#

[C#][Unity] 더블클릭 이벤트로 오브젝트 변경하기

by teamnova 2023. 8. 8.

오늘은 이전에 만든 오브젝트를 생성위치 제한하기 예제에서 오브젝트를 배치 가능한 구역을 제한하는 예제를 만들어 보겠습니다.

 

구현할 로직은 간단합니다.

- 생성된 Cube 오브젝트를 더블클릭할 경우 Sphere 오브젝트로 변경해준다

- Sphere 오브젝트를 더블클릭하면 Cube 오브젝트로 변경해준다

 

아래 링크는 이전 예제입니다.

https://stickode.tistory.com/874

 

 

먼저  Cube를 더블클릭하면 변경해줄 Sphere 오브젝트를 만들어 Prefab으로 만들어 줍니다.

좌측 Hierarchy창에서 마우스 우클릭 -> 3D Object -> Sphere를 만듭니다.

그 뒤 우측 Inspector 창에서 Sphere의 position을 0, 0.5, 0으로 변경해줍니다.

 

 

그리고 하단 Project 창에서 이전 예제처럼 Material을 만들고 원하는 색을 입혀줍니다.

그 다음 방금 만든 Material을 드래그해 Sphere 오브젝트로 가져다 놓으면 색이  Sphere에 입혀집니다.

 

 

이제 다시 Project 창에서 마우스 우클릭 -> Create -> C# script로 SphereObject라는 스크립트를 만든 뒤 아래와 같이 작성해줍니다.

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

public class SphereObject : MonoBehaviour
{

    float interval = 0.25f; // 더블클릭을 인식하는 기준 시간 크기 ex. 클릭 후 0.25초 안에 클릭하면 더블 클릭으로 인식된다
    float clickedTime; // 마지막으로 클릭한 시간
    public Transform cube; // 더블클릭 시 변경할 cube 오브젝트
    
    // 마지막으로 클릭한 시간
    void Awake() {
        clickedTime = -1.0f; // 클릭한 시간 -1.0f으로 초기화
    }

    void Update()
    {
        // 마우스 좌클릭을 했을 때 if문 내 코드 실행
        if(Input.GetMouseButtonDown(0)){
            RaycastHit hit = CastRay();

            if(hit.transform == transform){
                // 지금 시간에서 이전에 클릭했던 시간을 빼고 남은 시간의 크기가 0.25초 보다 작으면 더블클릭으로 인식해 if문 내 코드 실행
                if((Time.time - clickedTime) < interval){
                    
                    // 현재 위치를 기준으로 Cube 오브젝트를 생성
                    Instantiate(cube, transform.position, Quaternion.identity);
                    // 현재 Sphere 오브젝트 제거
                    Destroy(this.gameObject);

                }else{ // 더블클릭으로 인식되지 않은 경우 현재 시간을 저장한다
                    clickedTime = Time.time;
                }
            }
        }
    }

    // DragObject 스크립트에서 사용한 함수를 그대로 가져옵니다.
    private RaycastHit CastRay(){
        Vector3 screenMousePosFar = new Vector3(
            Input.mousePosition.x,
            Input.mousePosition.y,
            Camera.main.farClipPlane);

        Vector3 screenMousePosNear = new Vector3(
            Input.mousePosition.x,
            Input.mousePosition.y,
            Camera.main.nearClipPlane);

        Vector3 worldMousePosFar = Camera.main.ScreenToWorldPoint(screenMousePosFar);
        Vector3 worldMousePosNear = Camera.main.ScreenToWorldPoint(screenMousePosNear);

        RaycastHit hit;
        Physics.Raycast(worldMousePosNear, worldMousePosFar-worldMousePosNear, out hit);

        return hit;
    }
}

 

 

작성한 스크립트를 Sphere 오브젝트를 선택한 뒤 Inspector 창으로 옮겨줍니다.

그리고 SphereObject 스크립트의 cube에 Cube 프리팹을 넣어서 오브젝트를 완성해줍니다.

 

 

이제 왼쪽 Hierarchy창에서 Sphere를 드래그해 하단 Project 창에 있는 Prefabs 폴더로 옮겨 프리팹으로 만들어줍니다.

그리고 Scene에 존재하는 Sphere 오브젝트를 삭제해주세요.

 

 

이제 다시 DragObject 스크립트를 아래와 같이 수정해줍니다.

주석이 달려있는 부분이 이전 스크립트에서 추가 또는 수정된 부분입니다.

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

public class DragObject : MonoBehaviour
{

    float interval = 0.25f; // 더블클릭을 인식하는 기준 시간 크기 ex. 클릭 후 0.25초 안에 클릭하면 더블 클릭으로 인정된다
    float clickedTime; // 마지막으로 클릭한 시간
    public Transform sphere; // 더블클릭 시 변경할 cube 오브젝트

    public bool setable;
    public bool draggable;
    public CreateCube createCube;

    ObjectGround objectGround;
    BoxCollider bc;
    Vector3 cube_extents;
    public Vector3 cube_right;
    public Vector3 cube_left;
    public Vector3 cube_forward;
    public Vector3 cube_back;
    public Material[] mat = new Material[2];

    // 마지막으로 클릭한 시간
    void Awake() {
        clickedTime = -1.0f; // 클릭한 시간 -1.0f으로 초기화
        setable = true; // setable 변수 true로 초기화
    }

    void Start(){
        GameObject ground = GameObject.Find("Plane");
        objectGround = ground.GetComponent<ObjectGround>();

        bc = GetComponent<BoxCollider>();

        cube_extents = bc.bounds.extents;
    }

    void Update()
    {
        if(Input.GetMouseButtonDown(0)){
            RaycastHit hit = CastRay();

            if(hit.transform == transform){
                // 지금 시간에서 이전에 클릭했던 시간을 빼고 남은 시간의 크기가 0.25초 보다 작으면 더블클릭으로 인식해 if문 내 코드 실행
                if((Time.time - clickedTime) < interval){
                    
                    // 현재 위치를 기준으로 Sphere 오브젝트를 생성
                    Instantiate(sphere, transform.position, Quaternion.identity);
                    // 현재 Cube 오브젝트 제거
                    Destroy(this.gameObject);

                }else{ // 더블클릭으로 인식되지 않은 경우 현재 시간을 저장한다
                    clickedTime = Time.time;
                }

                draggable = true;
            }
        }

        if(Input.GetMouseButtonUp(0)){

            if(createCube != null){
                createCube.cube = null;
                createCube = null;
            }

            if(setable){
                draggable = false;
            }else{
                Destroy(this.gameObject);
            }
        }

        
        if(draggable){
            Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.WorldToScreenPoint(transform.position).z);
            Vector3 worldPosition = Camera.main.ScreenToWorldPoint(position);
            transform.position = new Vector3(worldPosition.x, 0.5f, worldPosition.z);

            if(CheckSetable()){
                setable = true;
                GetComponent<MeshRenderer>().material = mat[0];
            }else{
                setable = false;
                GetComponent<MeshRenderer>().material = mat[1];
            }
        }
    }

    bool CheckSetable(){
        cube_right = bc.bounds.center +  new Vector3(cube_extents.x, 0, 0);
        cube_left = bc.bounds.center + new Vector3(-cube_extents.x, 0, 0);
        cube_forward = bc.bounds.center + new Vector3(0, 0, cube_extents.z);
        cube_back = bc.bounds.center + new Vector3(0, 0, -cube_extents.z);

        if(!(objectGround.ground_right.x >= cube_right.x)){
            return false;
        }
        if(!(objectGround.ground_left.x <= cube_left.x)){
            return false;
        }
        if(!(objectGround.ground_forward.z >= cube_forward.z)){
            return false;
        }
        if(!(objectGround.ground_back.z <= cube_back.z)){
            return false;
        }

        return true;
    }


    private RaycastHit CastRay(){
        Vector3 screenMousePosFar = new Vector3(
            Input.mousePosition.x,
            Input.mousePosition.y,
            Camera.main.farClipPlane);

        Vector3 screenMousePosNear = new Vector3(
            Input.mousePosition.x,
            Input.mousePosition.y,
            Camera.main.nearClipPlane);

        Vector3 worldMousePosFar = Camera.main.ScreenToWorldPoint(screenMousePosFar);
        Vector3 worldMousePosNear = Camera.main.ScreenToWorldPoint(screenMousePosNear);

        RaycastHit hit;
        Physics.Raycast(worldMousePosNear, worldMousePosFar-worldMousePosNear, out hit);

        return hit;
    }

    
}

 

 

마지막으로 Cube 프리팹 내 DragObject 스크립트의 sphere에 Sphere 프리팹을 넣어줍니다.

 

 

이제 씬을 실행하고 Cube를 생성한 뒤 더블클릭하면 Sphere로 변경되고 다시 더블클릭하면 Cube로 변경되는 것을 확인할 수 있습니다.

감사합니다~