Unity

RayCast(Ray방식)

sungmin08 2024. 10. 22. 14:08

RayCasting 정의

Ray 방식 : Projectile 방식과는 달리 눈에 보이지 않는 광선(Ray)를 쏘아서 해당 광선에 맞은 물체가 적인지 여부를 판단한 뒤 여러가지 후처리를 하는 방식

 

VR에서는 마우스와 같은 표준 입력X, 컨트롤러를 사용하므로 RayCasting 필수

 

 

●DrawRay

 - RayCast는 Scene View에서 시각적으로 표시되지 않음. 개발 할 땐 DrawRay 함수를 이용해 시각적으로 표시하며 개발 해야 함

- (광선) RayCast가 어떤 객체를 감지(충돌)하기 위해서는 콜라이더 컴포넌트가 있어야 함.

void Update()
{
    //Debug.DrawRay(firepos.position, firepos.forward * 10.0f, Color.green);
}

DrawRay

 

●RayCast / RaycastHit

- Ray를 쏘아서 어떤 게임 오브젝트에 맞았을 때 맞은 게임 오브젝트의 정보를 반환 받을 변수 RaycastHit 타입으로 선언해야 함

 

관련 함수 : Phyiscs.Raycast()

private RaycastHit hit; //Raycast 결과값을 저장하기 위한 구조체 선언


void Update()
{
Phyiscs.Raycast(   // 어떤 Collider와 충돌 했으면 true 반환
firePos.position,  //Ray의 Start Point
firePos.forward,   //Ray의 방향
out hit,           //충돌한 객체의 대한 자세한 정보 return
10.0f);            //Max Distance
}

 

 

● RaycastHit 구조체

collider 맞은 게임 오브젝트의 Collider 반환
transform 맞은 게임오브젝트의 Transform 반환
point 맞은 위치의 월드 좌푯 값 반환(Vector3)
distance 발사위치와 맞은 위치 사이의 거리
normal Ray가 맞은 표면의 법선 벡터

 

●SendMessage() 함수

- Raycast 방식은 자동적인 충돌 이벤트 함수를 일으키지 않음

- 예로 MonsterCtrl 코드와 총알 FireCtrl 코드가 있다면 MonsterCtrl에서 RayCast를 사용해 데미지를 입히는 함수를 작성 후 FireCtrl에서 hit 구조체로부터 Monster 게임 오브젝트의 정보를 가져와야 한다.

void OnDamage()
{
//피격 리액션
//혈흔 효과 회전 값 정보
//혈흔효과생성함수
//등등
}

MonsterCtrl 코드

void Update()
{
hit.transfom.GetComponent<MonsterCtrl>()?.OnDamage(hit.point, hit.normal);
}

FireCtrl코드

 

●레이저 빔 구현

Meterial 준비

 

Line Renderer 컴포넌트 추가 후 메테리얼 할당

 

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

public class LaserBeam : MonoBehaviour
{
    private Transform tr;
    private LineRenderer line;
    //광선에 충돌한 게임오브젝트의 정보를 받아올 변수
    private RaycastHit hit;

    private void Start()
    {
        tr=GetComponent<Transform>();
        line=GetComponent<LineRenderer>();

        //로컬좌표로 기준으로 변경
        line.useWorldSpace = false;
        //초기 비활성화
        line.enabled = false;
        //라인이 시작점과 종료점 설정
        line.SetWidth(0.3f, 0.01f);
    }
    private void Update()
    {
        //광선 미리 생성
        Ray ray = new Ray(tr.position + (Vector3.up * 0.01f), tr.forward);

        //광선이 눈에 보이게 설정
        Debug.DrawRay(ray.origin, ray.direction * 100, Color.blue);

        if(Input.GetMouseButton(0))
        {
            //Line Renderer의 첫번째 점의 위치 설정
            line.SetPosition(0, tr.InverseTransformPoint(ray.origin));

            //어떤 물체에 광선이 맞았을 때의 위치를 Line Renderer의 끝 점으로 설정
            if(Physics.Raycast(ray,out hit, 100.0f))
            {
                line.SetPosition(1, tr.InverseTransformPoint(hit.point));
            }
            else
            {
                line.SetPosition(1, tr.InverseTransformPoint(ray.GetPoint(100.0f)));
            }

            //광선을 표시하는 코루틴 함수 호출
            StartCoroutine(this.ShowLaserBeam());
        }
    }

    IEnumerator ShowLaserBeam()
    {
        line.enabled = true;
        yield return new WaitForSeconds(Random.Range(0.01f, 0.2f));
        line.enabled = false;
    }
}