일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 미로 탈출 명령어
- 프로그래머스
- Ainimation Blending
- 백준 c++ 9375번
- 플레이어 이동
- dfs
- 플레이어 방향전환
- 양과 늑대
- Animation State Machine
- dp 알고리즘
- LayerMark
- 충돌위험 찾기
- 오브젝트 풀링
- Blend Type
- C#
- CSharp #자료구조
- Unity
- 2D슈팅게임
- pccp 기출문제 3번
- Lv2
- Lv.3
- pccp 기출문제 2번
- Back Tracking
- pccp 기출문제 1번
- 9375번
- Algorithm
- 연속 펄스 부분 수열의 합
- 유니티
- Hp바
- heap tree
- Today
- Total
주녘공부일지
[Unity3D] Physics.Raycast (+LayerMask) 본문
Physics.Raycast란?
충돌을 Collider로 감지하는 레이저 광선 ( Ray )
- UnityEngine에 선언되어 있는 구조체 Physics
Raycasting은 상당히 무거운 작업(부하를 많이 줌)이므로 최적화를 하는 것이 중요
- 인스펙터에서 Layer를 추가해 LayerMask를 활용하여 영역을 나누어 연산 최적화 ( 글 하단 4, 5번 )
- 매쉬 콜라이더가 너무 복잡할 경우엔 충돌 연산용 매쉬 콜라이더를 만들어 사용
1. 3D 플레이어가 바라보는 방향의 물체 감지 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRaycast : MonoBehaviour
{
void Update()
{
Vector3 look = transform.TransformDirection(Vector3.forward); // Local -> World
Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);
RaycastHit hit;
if (Physics.Raycast(transform.position + Vector3.up, Vector3.forward, out hit, 10))
{
// Ray에 충돌이 감지되면 충돌된 오브젝트의 이름을 출력
Debug.Log($"Raycast : {hit.collider.gameobject.name}");
}
}
}
Physics.Raycast() : Ray를 발사, 첫번째 닿는 타겟만 감지
Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )
RaycastHit : UnityEngine에 선언되어 있는 구조체
위의 로직에서 DrawRay()와 Raycast()는 같은 영역
+ Vector3.up을 해준 이유는 3D플레이어의 중앙부분에서 레이저 광선을 쏘기 위함
Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩
1-1) 3D 플레이어가 바라보는 방향의 물체들 감지 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestRaycast : MonoBehaviour
{
void Update()
{
Vector3 look = transform.TransformDirection(Vector3.forward); // world -> local
Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);
RaycastHit[] hits; // 배열로 선언
hits = Physics.RaycastAll(transform.position + Vector3.up, look, 10);
foreach(RaycastHit hit in hits)
{
// Ray에 충돌이 감지되면 충돌된 오브젝트들의 이름을 출력
Debug.Log($"Raycast {hit.collider.gameObject.name}!");
}
}
}
Physics.RaycastAll() : Ray를 발사, Ray에 닿는 모든 타겟을 감지
Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )
RaycastHit : UnityEngine에 선언되어 있는 구조체
위의 로직에서 DrawRay()와 RaycastAll() 은 같은 영역
+ Vector3.up을 해준 이유는 3D플레이어의 중앙부분에서 레이저 광선을 쏘기 위함
Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩
2. Unity3D의 Main Camera
Near : 메인 카메라 원점과 가장 가까운 절두체 윗면(직사각형)의 거리
Far : 메인 카메라 원점과 가장 먼 절두체 밑면(직사각형)의 거리
https://docs.unity3d.com/kr/2018.4/Manual/class-Camera.html
1) Screen 좌표계 : 화면 좌표계로 화면의 좌측 하단 끝을 원점으로 하는 평면 절대 좌표계
2) Viewport 좌표계 : 화면의 좌측 하단 끝을 원점으로 하는 평면 상대 좌표계 // 우측 하단 끝 좌표 - (1, 1)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCollision : MonoBehaviour
{
void Update()
{
Debug.Log(Input.mousePosition); // 1) Screen
Debug.Log(Camera.main.ScreenToViewportPoint(Input.mousePosition)); // 2) Viewport
}
}
2-1) 카메라를 스크린의 클릭한 물체를 감지하는 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCollision : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0)) // 왼쪽 마우스 클릭
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(
Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
Vector3 dir = mousePos - Camera.main.transform.position; // 카메라 위치와 절두체의 가장 가까운 포인트
dir = dir.normalized; // 0~1로 정규화
Debug.DrawRay(Camera.main.transform.position, dir * 100f, Color.red, 1.0f);
RaycastHit hit;
if (Physics.Raycast(Camera.main.transform.position, dir, out hit, 100f))
{
Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
}
}
}
}
Physics.Raycast() : Ray를 발사, 첫번째 닿는 타겟만 감지
Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )
RaycastHit : UnityEngine에 선언되어 있는 구조체로 raycast로부터 정보를 얻기 위해 사용
+ 위의 로직에서 DrawRay()와 Raycast()는 같은 영역
+ Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩
2-2) 위와 같은 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCollision : MonoBehaviour
{
void Update()
{
if(Input.GetMouseButtonDown(0)) // 왼쪽 마우스
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(Camera.main.transform.position, ray.direction * 100f, Color.red, 1.0f);
// ray.direction : 정규화 된 정보
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f, 0))
{
Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
}
}
}
}
- 위 두 예제는 같은 기능을 하는 로직으로, 게임상에서 마우스가 클릭되면 클릭한 좌표로 Ray가 발사되며 (DrawRay로 씬에 표시됨) Ray에 콜라이더를 가진 물체가 닿을 시에 콘솔에 닿은 콜라이더를 가진 오브젝트의 이름을 찍는 예제
Camera.main.ScreenPointToRay() : 카메라로 부터의 스크린의 점을 통해 레이를 반환
3. Tags & Layers 세팅 (예제)
- 비활성화되어 있는 Builtin Layer는 Unity가 이미 점유하고 있는 상태
3-1) LayerMark를 활용한 예제 ( 2-2 확장 )
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCollision : MonoBehaviour
{
void Update()
{
if(Input.GetMouseButtonDown(0)) // 왼쪽 마우스
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(Camera.main.transform.position, ray.direction * 100f, Color.red, 1.0f);
LayerMask mask = LayerMask.GetMask("Monster") | LayerMask.GetMask("Wall");
// int mask = (1 << 6) | (1 << 7);// int형으로 32비트인 Layer를 제어 (위와 같은 로직)
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f, mask))
{
Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
}
}
}
}
- LayerMark를 활용하여 특정 아이들만 레이캐스팅하는 것으로 최적화
'GameDevelopment > [Unity] Class' 카테고리의 다른 글
[Unity] StateMachineBehaviour (0) | 2022.03.23 |
---|---|
[Unity3D] Camera (0) | 2022.03.01 |
[Unity3D] Collision (충돌) (0) | 2022.02.23 |
[Unity3D] Rotation (회전) (0) | 2022.02.21 |
[Unity3D] Vector3 (0) | 2022.02.21 |