Ad Block 한번만 꺼주시면 안될까요..?
게임 개발/유니티

유니티) OnCollisionExit에서 접점을 구하는 방법.

UniCoti(유니코티) 2023. 10. 28.

일반적으로, 닿은 물체에 대한 Collision을 가지고 있다면

접점은 그냥 메서드를 통해서 한 번에 구해줄 수 있다.

 

point = other.GetContact(0);

하지만 문제점은, OnCollisionStayEnter는 닿아 있는 상태이기에

접점을 구할 수 있는데, Exit의 경우에는 떨어진 상태이기 때문에

접점을 구할 수 없고, 따라서 인덱스 오류가 나게 된다.

 

이걸 해결하는 방법을 소개하겠다.


1. 이론

사실, 별거 없다.

나의 경우에는 로직을 수정해서 해결했다.

 

먼저, 스크립트의 어떤 함수에서도 접근할 수 있도록 변수를 하나 만들어준다.

그 후, OnCollisionStay를 통해서 변수에 접점에 대한 정보를 계속 저장해 준다.

 

그리고, 최종적으로 떨어졌을 때. (OnCollisionExit가 실행될 때)

그때는 변수에 저장된 값을 사용하는 방식이다.


2. Code

아직은 무슨 말인지 이해하지 못해도 괜찮다.

직접 코드로 로직을 짜보자.

 

ContactPoint point;

앞서 말한 대로, 변수를 하나 짜준다.

여기서 타입은 ContactPoint인데, 이건 접점에 대한 정보를 저장할 수 있는 클래스이다.

 

private void OnCollisionStay(Collision other) { //닿아 있을때
    if(other.gameObject.CompareTag("TargetTag")) { //닿은 물체의 태그가 "TargetTag"라면
        point = other.GetContact(0); //point변수에 접점 정보 기록
    }
}

이번에도 앞서 말한 대로, OnCollisionStay를 통해 변수에 값을 넣어주자.

추가로, 대상의 태그로 분석해서 if문으로 추가하면 더 좋다.

 

private void OnCollisionExit(Collision other) { //떨어졌을때
   if(other.gameObject.CompareTag("TargetTag")) { //태그가 "TargetTag"라면
        Debug.Log(point.point); //접점의 위치 출력하기
    }   
}

마지막으로, 떨어졌을 때 (+태그가 "TargetTag"라면)

접점의 위치를 출력할 수 있다!


2-1. 오류가 나는 코드

private void OnCollisionExit(Collision other) {
    other.GetContact(0); //바로 접점을 가져오기
}

----> 오류 출력. (떨어졌을때라서 닿은 지점이 없음)

다시 한번 우리의 문제를 상기시켰으면 해서 넣어보았다.


여기서 법 선벡터에 관한 지식과 AddForce까지 활용하면 

젤다의 전설의 사당에 나오는 이러한 장치를 만들 수도 있다.

 

private void OnCollisionExit(Collision other) {
    if(other.gameObject.name == "CUBE") { //두 오브젝트의 이름이 같음 (임시적인 코드)
        GetComponent<Rigidbody>().AddForce(point.normal * speed, ForceMode.Impulse);
    }
}

마지막만 바꿔주면 된다.

 

전체 코드를 올려둘 테니 각각의 요소만 보고 이해가 안 된다면 활용하라. (아래줄 더 보기 클릭)

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

public class CannonBall : MonoBehaviour
{
    ContactPoint point;
    public float speed;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void OnCollisionStay(Collision other) {
        if(other.gameObject.name == "CUBE") {
            point = other.GetContact(0);
        }
        
    }

    private void OnCollisionExit(Collision other) {
        if(other.gameObject.name == "CUBE") {
            GetComponent<Rigidbody>().AddForce(point.normal * speed, ForceMode.Impulse);
        }
    }
}

여기까지 OnCollisionExit에서의 접점을 구할 수 없는 문제점을 해결해 봤다.

이걸 검색할 일이 많을지는 모르겠으나 도움이 되었으면 좋겠다.

한마디로 정리하면 떨어진 점 -> 떨어지기 전 마지막 점의 코드로 바꾼 격이다.

 

유니티 협력 링크(어필리에이트)


이상으로 도움이 되었길 바라며,

 

끝.

댓글

💲 추천 글