10/10 TIL 3D FPS

Cheorii·2024년 10월 10일

오늘 내용

  • 오늘 내용은 크게 CollisionFlags, RayCast에 관련된 내용을 정리해보려고 한다.

CollisionFlags

  • CollisionFlags는 Unity에서 CharacterController 컴포넌트가 이동 중 충돌했을 때 그 충돌 상태를 나타내는 열거형(enum)
  • 이를 통해 캐릭터가 아래, 위, 옆에 있는 충돌체와의 상호작용 여부를 알 수 있음
// 중력
verticalSpeed -= gravity * Time.deltaTime;  // 속도 = 가속도 * 시간
if (verticalSpeed < -terminalSpeed)         // -terminalSpeed보다 떨어지는 속도가 낮은 값을 가지고 있으면
{
    verticalSpeed = -terminalSpeed;         // 떨어지는 속도를 -terminalSpeed로 고정
}
Vector3 verticalMove = new Vector3(0, verticalSpeed, 0);      // 하강하는 Vector에 delta.Time적용
verticalMove *= Time.deltaTime;                               

CollisionFlags flag = characterController.Move(verticalMove); // 캐릭터가 어디에 부딪혔는지 확인하는 부분

//캐릭터가 바닥에 닿으면(CollisionFlags.Below), verticalSpeed를 0으로 하여 낙하를 멈춥니다.
if ((flag & CollisionFlags.Below) != 0)                       
{
    verticalSpeed = 0;
}   

CollisionFlags.Below

  • 캐릭터가 바닥에 닿아있을 때 이 플래그가 설정됩니다.
    즉, 캐릭터가 지면 위에 있거나 아래에 무언가가 있을 때, 충돌 정보를 통해 이를 감지할 수 있습니다.
  • 이 값은 flag & CollisionFlags.Below != 0을 통해 확인할 수 있으며, 이를 통해 캐릭터가 땅에 닿았는지 여부를 판단해 중력을 초기화하거나, 더 이상 낙하하지 않도록 처리할 수 있습니다.

CollisionFlags.Above

  • 캐릭터가 머리 위에 무언가에 부딪힐 때 이 플래그가 설정됩니다.
  • 이를 통해 캐릭터가 천장에 닿았는지 여부를 판단할 수 있습니다.

CollisionFlags.Sides

  • 캐릭터가 좌우 또는 앞뒤로 벽이나 장애물에 부딪힐 때 설정됩니다.
  • 벽에 닿아 움직이지 못하는 상황을 감지하는 데 유용합니다.

TerminalSpeed

  • 빗물이 떨어질때 계속 빨라지는게 아니라 어느정도 값이 되면 일정한 값을 가진다.
    종단 속도 라고 생각하면 됨(추락할때 속도가 더이상 안빨라 지는 지점)

    -> 실제 게임에서 낙하할때도 낙하속도가 계속 무한대로 빨라지지 않음.
    -> 일정 속도 이상으로 빨라지지 않게 하기 위해서 만든 장치

코요테 타임

  • 캐릭터가 절벽으로 달려나가 두 발이 더 이상 땅에 닿지 않더라도
    아주 짧은 시간 동안 점프할 수 있는 잠깐의 시간을 뜻합니다.
  • 간단히 말하면 바닥에서 떨어진 이후 잠시동안 점프가 가능한걸 말함 일종의 프레임 보정

RayCast

Ray 와 RayCast의미

Ray

  • Ray는 직선 경로를 나타내는 데이터 구조로, 시작점(origin)과 방향(direction)을 가진 직선
  • 물리적 충돌 계산을 위한 가상의 선

RayCast

  • Raycast는 이 직선을 사용하여 물체와의 충돌을 감지하는 과정
  • 지정된 점에서 특정 방향으로 Ray를 발사하고, 충돌이 생기면 충돌정보(RayCastHit)를 반환
    주로 시야 검사, 총알 발사, 거리 측정에 사용됨

RayCast 사용 방법

기본적인 Raycast 사용 Physics.Raycast 함수는 Ray 객체를 사용하여 광선을 발사하고, 충돌한 경우 충돌 정보를 반환

RaycastHit hit;
Ray ray = new Ray(origin, direction);
// 여기서 사용된 out hit는 hit에서 값을 받아온다는 말
if (Physics.Raycast(ray, out hit, maxDistance))
{
    // 충돌된 오브젝트에 대한 처리
    Debug.Log("Hit: " + hit.collider.name);
}```
위 코드에서는 Ray를 시작점과 방향으로 정의하고, Raycast를 통해 충돌 여부를 확인 
충돌이 발생하면, 충돌 정보가 RaycastHit 객체에 저장

Parameters

  • origin: Ray의 시작점(광선을 발사할 위치)
  • direction: Ray가 나아갈 방향(일반적으로 Vector3.forward나 오브젝트의 - Transform.forward 사용).
  • maxDistance: 광선의 최대 사거리. 이 값 내에서만 충돌을 감지
  • layerMask (optional): 충돌을 감지할 레이어를 선택해 특정 오브젝트만 감지할 수 있음
Physics.Raycast(origin, direction, out hit, maxDistance, layerMask);

RaycastHit

  • RaycastHit는 Raycast가 충돌한 객체에 대한 세부 정보를 담고 있는 구조체
    (충돌한 지점이나 오브젝트의 정보에 접근할 수 있음)
  • hit.collider : 충돌된 오브젝트의 콜라이더
  • hit.point : 충돌한 지점의 좌표
  • hit.normal : 충돌 지점에서의 표면 법선 벡터
  • hit.distance : Ray의 시작점에서 충돌 지점까지의 거리

아래에 내용은 RayCast를 활용해 총기 발사시 Ray를 발사하도록 제작했다.



void RayCastFire()
{
    Camera cam = Camera.main;

    RaycastHit hit;
    // 카메라 정가운데 빛을 만들어서 가지고 온다 
    Ray r = cam.ViewportPointToRay(Vector3.one / 2); //0.5,0.5

    Vector3 hitPosition = r.origin + r.direction * 200;

    if(Physics.Raycast(r,out hit,1000))     // 어딘가 빛이 부딪히면 true, 아니면 false
    {
        hitPosition = hit.point;            // 충돌한 지점 좌표값 
    }

    GameObject go = Instantiate(trailPrefab);   // trailPrefab오브젝트 생성
    Vector3[] pos = new Vector3[] { firingPosition.position, hitPosition }; // 점 위치 저장
    // Positions에 배열을 넣으면 그걸 이어서 직선을그림
    // 프리팹 좌표 지정
    go.GetComponent<LineRenderer>().SetPositions(pos);  
}
  • 이 부분에서 왜 배열을 사용했나?
    - LineRender 컴포넌트가 여러 지점을 연결해 선을 그리는 기능을 하기 때문
    - LineRender는 점들의 좌표 배열을 입력받고, 그걸 연결시켜서 렌더링한다
    - LineRender는 점을 기반으로 선을 그리기 때문에 최소 두개이상의 좌표가 필요
    결론
    - 발사 시작점과 충돌 지점이라는 두 좌표LineRenderer에 전달하기 위해서
profile
코딩테스트는 진짜 못하겠어요 ㅠㅠ

0개의 댓글