본문 바로가기
유니티

Day 30 - Rigidbody ForceMode 와 Raycast

by shin0707 2024. 5. 24.
728x90

  • 주제

>>Rigidbody ForceMode

(개념 및 4가지 종류)

(오브젝트에 힘 가하기)

 

>>Raycast

(개념)

(오브젝트 감지)

 

>>ForceMode, Raycast 둘 다 활용한 예제

(플레이어가 총알을 발사, 타겟에 부딪히면 타겟과 총알 제거)


  • 공부내용

1. ForceMode란?

Rigidbody에 힘을 가할 때, 어떤 방식으로 힘을 적용할 것인지를 정하는 옵션이다.

방식에는 다음 4가지가 있다.

 

- Force: 매 프레임마다 일정한 힘을 가함(예: 지속적으로 힘을 가하고 싶을 때 사용)

같은 힘이라도 물체의 질량에 따라 가속도가 다르게 적용된다.

ex) A질량 1kg / B질량 10kg / 힘 10 ---> A가 B보다 더 빠르게 이동

Rigidbody.AddForce(Vector3 force, ForceMode.Force);

 

- Acceleration: Force와 비슷하지만, 질량의 영향을 받지 않고 가속도를 적용

ex) A질량 1kg / B질량 10kg / 힘 10 ---> A와 B가 같은 속도로 이동

Rigidbody.AddForce(Vector3 force, ForceMode.Acceleration);

 

- Impulse: 짧은 시간 동안 강한 힘을 가함(예: 순간적인 충격이나 힘을 표현하고 싶을 때 사용)

Rigidbody.AddForce(Vector3 force, ForceMode.Impulse);

 

- VelocityChange: 질량의 영향을 받지 않고 속도를 즉시 변경

Rigidbody.AddForce(Vector3 force, ForceMode.VelocityChange);

 

예제: 오브젝트에 힘 가하기

using UnityEngine;

public class ApplyForce : MonoBehaviour
{
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        // ForceMode.Impulse를 사용해 위쪽으로 500의 힘을 가함(오브젝트가 위로 튀어오름)
        rb.AddForce(new Vector3(0, 500, 0), ForceMode.Impulse);
    }
}

 

2. Raycast란?

레이저 광선을 쏴서 물체와의 충돌을 감지하는 역할을 한다.

구체적으로는 시작 위치에서 특정 방향으로 레이저를 쏴서,

경로에 있는 모든 오브젝트를 감지한다.

주로 발사체, 시야 확인, 거리 측정 등에 사용된다.

 

Ray ray = new Ray(transform.position, transform.forward); // 오브젝트

Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); // 카메라 중심

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 마우스

 

RaycastHit.point - 레이캐스트가 충돌한 지점의 좌표

ex) 충돌한 지점에 파티클 효과를 생성

그 지점으로 게임 오브젝트를 이동시키는 경우

 

RaycastHit.distance - Ray기준으로 원점에서 충돌 지점까지의 거리

ex) 플레이어가 발사한 레이저의 도달 거리에 따라 피해량을 계산

플레이어가 조준한 대상까지의 거리를 화면에 출력하는 경우

플레이어가 던진 물체가 특정 거리를 넘어가면 특정 행동을 트리거할 경우

 

RaycastHit.transform - 충돌 객체의 transform에 대한 참조

ex) 충돌한 객체의 위치, 회전, 크기 등을 변경

충돌한 객체의 부모-자식 관계를 설정

충돌한 객체를 다른 위치로 이동시키는 경우

 

예제: 오브젝트 감지

using UnityEngine;

public class RaycastExample : MonoBehaviour
{
    void Update()
    {
        // 오브젝트를 기준으로 Ray를 정의
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;

        // 게임 오브젝트 위치에서 앞으로 100 유닛 거리까지 Ray를 쏴서, 충돌한 오브젝트의 정보를 콘솔에 출력
        if (Physics.Raycast(ray, out hit, 100.0f))
        {
            Debug.Log("Hit: " + hit.collider.name);
            Debug.Log("Hit Point: " + hit.point);
            Debug.Log("Distance: " + hit.distance);
            Debug.Log("Hit Object Transform: " + hit.transform);
        }
    }
}

 

 

3. ForceMode, Raycast 둘 다 활용

 

예제: 플레이어가 총알을 발사, 타겟에 부딪히면 타겟과 총알 제거

 

-> 총알 스크립트(Bullet.cs)에 ForceMode, Raycast 사용

using UnityEngine;

public class Bullet : MonoBehaviour
{
    public float speed = 20f; // 총알 속도 설정
    public Rigidbody rb; // 중력 저장
    public ForceMode forceMode = ForceMode.Impulse; // ForceMode 설정

    void Start()
    {
        rb = GetComponent<Rigidbody>(); 
        rb.AddForce(transform.forward * speed, forceMode); // 설정된 ForceMode로 힘을 가함
    }

    void Update()
    {
        // Raycast를 사용하여 총알의 진행 방향에 물체가 있는지 확인
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;
        
        // 만약 Ray가 물체와 충돌하면
        if (Physics.Raycast(ray, out hit, speed * Time.deltaTime))
        {
            // 충돌한 물체의 이름을 콘솔에 출력
            Debug.Log("Hit: " + hit.collider.name);

            // 충돌한 오브젝트가 특정 태그를 가질 경우, 추가적인 행동을 수행
            if (hit.collider.CompareTag("Target"))
            {
                // 충돌한 오브젝트를 제거
                Destroy(hit.collider.gameObject);
            }

            // 총알 제거
            Destroy(gameObject);
        }
    }
}

 

 

-> 플레이어 스크립트(PlayerShoot.cs)

using UnityEngine;

public class PlayerShoot : MonoBehaviour
{
    public GameObject bulletPrefab; // 발사할 총알 프리팹을 지정
    public Transform bulletSpawn; // 총알이 생성될 위치와 회전을 지정

    void Update()
    {
        // Fire1 버튼(기본적으로 마우스 왼쪽 버튼)이 눌렸는지 확인
        if (Input.GetButtonDown("Fire1"))
        {
            Shoot(); // Fire1 버튼이 눌리면 Shoot 메서드를 호출
        }
    }

    void Shoot()
    {
        // bulletPrefab을 bulletSpawn 위치와 회전으로 인스턴스화(생성)
        Instantiate(bulletPrefab, bulletSpawn.position, bulletSpawn.rotation);
    }
}
728x90
반응형