카메라에 붙여서 사용할 수 있는 코드입니다.

카메라가 보는 방향으로 이동 할 수 있게 만들었고

( transform.forward * vertical + transform.right * horizontal )

 

마우스 오른쪽 클릭을 통해 회전을 할 수 있는 코드입니다.

회전은 마우스 가로 움직임이 세로축에 영향을 주고

마우스 세로 움직임이 가로축에 영향을 줍니다.

MouseX => rotation.y에 영향

MouseY => rotation.x에 영향

( Quaternion.Euler(transform.rotation.x - mouseY, transform.rotation.y + mouseX, 0.0f) )

 

private new Transform transform; 를 선언하고 transform = GetComponent<Transform> 를 해주었는데

transform을 캐싱하여 성능을 높일 수 있다고 해서 사용했습니다! ㅎㅎ

using UnityEngine;

public class CameraController : MonoBehaviour
{
    public float rotateSpeed = 5.0f;
    public float moveSpeed = 3.5f;
    public float limitAngle = 70.0f;

    private new Transform transform;
    private bool isRotate;
    private float mouseX;
    private float mouseY;

    private void Start()
    {
        transform = GetComponent<Transform>();

        mouseX = transform.rotation.eulerAngles.y;  //마우스 가로(x)는 세로축(y) 이 중심
        mouseY = -transform.rotation.eulerAngles.x; //마우스 세로(y)는 가로축(-x) 이 중심
    }

    private void Update()
    {
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

        //카메라를 기준으로 앞, 옆으로 이동시킵니다.
        Vector3 movement = transform.forward * vertical + transform.right * horizontal;
        movement = movement.normalized * (Time.deltaTime * moveSpeed);
        transform.position += movement;

        //마우스 오른쪽 클릭 시 회전시킴
        if (Input.GetMouseButtonDown(1))
        {
            isRotate = true;
        }
        if (Input.GetMouseButtonUp(1))
        {
            isRotate = false;
        }

        if (isRotate)
        {
            Rotation();
        }
    }

    public void Rotation()
    {
        mouseX += Input.GetAxis("Mouse X") * rotateSpeed; // AxisX = Mouse Y
        mouseY = Mathf.Clamp(mouseY + Input.GetAxis("Mouse Y") * rotateSpeed, -limitAngle, limitAngle);

        //mouseX (가로 움직임) 은 Y축에 영향을 줌
        //mouseY (세로 움직임) 은 X축에 영향을 줌
        transform.rotation = Quaternion.Euler(transform.rotation.x - mouseY, transform.rotation.y + mouseX, 0.0f);
    }
}

 

1. Box Collider

박스 콜라이더는 위와 같이 x좌표, y좌표가 박스 내부에 있는지 판별을 하게 됩니다.

x좌표와 y좌표 모두 내부에 속해있으면 충돌로 판정하게 됩니다.

(만약 3차원이라면 z좌표까지도 내부인지 확인해주면 되겠습니다.)

public bool IsBoxInner ()
{
    float x = clickPosition.x;
    float y = clickPosition.y;

    return xMin <= x && x <= xMax &&
            yMin <= y && y <= yMax;
}

 

2. Circle Collider

원형 콜라이더는 거리를 구해서 반지름 값보다 같거나 작은지를 확인하면 됩니다.

간단한 계산 덕분에 가장 빠른 충돌체 처리로 알려져 있습니다.

피타고라스 정리를 이용하여 거리를 계산합니다.

가로^2 + 세로^2 = 빗변^2

위와 같이 빗변을 구하고 루트를 씌워주면 원하는 빗변값을 구할 수 있고,

빗변이 원의 반지름 이내라면 원과 접촉했다고 판별할 수 있습니다.

최적화는 빗변에 루트를 씌우지 않고 반지름을 제곱해주어 판별하면 되겠습니다.

//방법1
public bool IsCircleInner ()
{
    float distance = 
    Mathf.Sqrt((clickPosition.x - colliderPosition.x) * (clickPosition.x - colliderPosition.x)
             + (clickPosition.y - colliderPosition.y) * (clickPosition.y - colliderPosition.y));
    
    //float distance = Vector2.Distance(colliderPosition, clickPosition);

    return distance <= circleRadius;
}

//방법2
public bool IsCircleInner ()
{
    float distance = 
               (clickPosition.x - colliderPosition.x) * (clickPosition.x - colliderPosition.x)
             + (clickPosition.y - colliderPosition.y) * (clickPosition.y - colliderPosition.y);
    
    return distance <= circleRadius * circleRadius;
}

 

3. Triangle Collider

예전에 프로그래밍 고수형이 넥슨 회사 면접 볼 때 나왔던 문제라고 저한테 풀어보라고 했었습니다.

점이 삼각형 내부(충돌)인지 아닌지 아닌지 어떻게 판별을 해야될까요?

처음엔 삼각형의 기울기를 생각했었는데 선형대수학에 나오는 벡터의 외적을 이용하면 쉽게 풀 수 있습니다.

2차원 좌표이기에 외적을 구해보면 z값에 대해서만 변화가 있게 됩니다.

이 z값이 양수인지 음수인지를 따져보면 현재 위치에서 방향을 알 수 있게 됩니다.

먼저 상대적인 좌표로 만들어줍니다. 기준점 (-2, -2)으로부터의 거리로 만들어주고

두 점의 외적을 구해봅니다. 노란 화살표가 기준이 되고, 보라색 화살표가 왼쪽인지 오른쪽인지 판별을 합니다.

이렇게 3개의 꼭지점을 기준으로 위치를 판별해줍니다.

결과는 왼쪽, 오른쪽, 왼쪽 이 나왔고 점은 밖에 있다는 것이 판별되었습니다.

삼각형 내부에 있는 경우는 모두 동일한 방향에 있는 경우입니다.

아래는 이미 포지션 값을 정해놓고, 시뮬레이션 단계마다 판별을 하는 코드입니다.

전체 코드는 깃허브에 유니티 프로젝트와 함께 올려두었습니다.

private void DeterminePosition ()
{
    Vector3[] positions = triangle_clickPoint.GetTrianglePositions();

    Vector3 startPosition = positions[simulationStep - 1]; //기준 위치
    Vector3 endPosition = positions[simulationStep];       //기준 라인
    Vector3 basePoint = endPosition - startPosition;       //1번 화살표 구하기
        
    endPosition = triangle_clickPoint.GetClickPosition();  //(노란점)클릭 위치
    Vector3 clickPoint = endPosition - startPosition;      //2번 화살표 구하기

    //벡터의 외적을 통해 z값을 구합니다. 아래코드와 동일합니다.
    //float cross = Vector3.Cross(basePoint, clickPoint).z;
    
    float cross = basePoint.x * clickPoint.y - basePoint.y * clickPoint.x;
    
    if (cross >= 0)
    {
        //Is Left
    }
    else
    {
        //Is Right
    }
}

전체 코드와 유니티 프로젝트는 깃허브에 따로 올려두겠습니다!

https://github.com/dlaehdeod/Practice

 

GitHub - dlaehdeod/Practice: Play File and Sources

Play File and Sources. Contribute to dlaehdeod/Practice development by creating an account on GitHub.

github.com

 

버튼을 누르면 무언가 동작을 하게 해봅시다.

2가지 방법으로 연결이 가능합니다.

 

1. 코드로 연결하기

using UnityEngine;
using UnityEngine.UI;

public class UI_Script : MonoBehaviour
{
    public Button testButton;

    private void Start()
    {
        //방법1. 무명 메소드 람다식을 통해 적용
        testButton.onClick.AddListener(() => TestButtonDown());
        
        //방법2. delegate를 이용해 적용
        testButton.onClick.AddListener(delegate { TestButtonDown(); });
        
        //방법3. (방법1 에서 UnityAction으로 함수를 갖고 있는 방법입니다.)
        UnityEngine.Events.UnityAction action = () => TestButtonDown();
        testButton.onClick.AddListener(action);
        
        //방법4. (방법2 에서 UnityAction으로 함수를 갖고 있는 방법입니다.)
        UnityEngine.Events.UnityAction action2 = (delegate { TestButtonDown(); });
        testButton.onClick.AddListener(action2);
    }

    public void TestButtonDown ()
    {
        print("Button Down!");
    }
}

방법1~4 중에 편한 방법으로 써주면 되겠습니당. (모두 동일한 기능을 합니다.)

버튼이 많거나 동적으로 생성해서 사용해줄 때 AddListener를 이용하여 메소드를 등록해줄 수 있습니다.

(또는 버튼을 누른 다음에 다른 메소드로 변경하는데도 사용될 수 있겠죠?)

 

2. 화면에서 적용시켜주기.

  먼저 스크립트가 있어야 하고, 스크립트 내부에 public으로 선언 된 함수가 있어야 됩니다.

  UI_Script 이름의 스크립트를 생성해줍니다.

using UnityEngine;

public class UI_Script : MonoBehaviour
{
    public void TestButtonDown ()
    {
        print("Button Down!");
    }
}

 

 이제 게임오브젝트를 하나 생성해주고 UI_Script를 갖고 있게 해줍니다.

오브젝트 이름도 동일하게 UI_Script 로 해주겠습니다.

 

 

버튼을 생성해줍니다. 그러면 버튼에 옵션이 나오게 되고 스크립트를 On Click () 으로 넣어줍니다.

 

빨간 네모 부분을 눌러주면 메뉴들이 나옵니다.

UI_Script -> TestButtonDown

을 찾아서 연결해주면 버튼이 눌렸을 때 해당 함수가 호출이 됩니다.

 

+ Recent posts