Version: 2023.1
언어: 한국어
연속 충돌 검사(CCD)
Physics Debug 창 레퍼런스

휠 콜라이더로 차량 생성

Wheel Collider 컴포넌트에는 PhysX 3 Vehicles SDK가 사용됩니다.

이 튜토리얼에서는 기본 기능만 있는 자동차를 만드는 절차를 설명합니다.

시작하려면 GameObject > 3D Object > Plane 을 선택합니다. 지금 선택되는 항목은 차를 운전할 지면입니다. 간단하게 유지하기 위해, 지면의 Transform이 0 인지 확인합니다(인스펙터 창의 Transform 컴포넌트에서 설정 톱니바퀴 아이콘을 클릭한 다음 Reset 을 클릭). Transform의 Scale 필드를 100 으로 높여 평면이 더 커지게 합니다.

기본 자동차 골격 생성

  1. 먼저 자동차 루트 역할을 할 게임 오브젝트를 추가합니다. 이렇게 하려면 GameObject > Create Empty 로 이동합니다. 게임 오브젝트의 이름을 car_root로 변경합니다.
  2. car_root에 Physics 3D Rigidbody 컴포넌트를 추가합니다. 기본 질량이 1kg로 설정되어 있는데, 기본 서스펜션 설정으로는 너무 가벼우므로 1,500kg으로 변경하여 훨씬 더 무겁게 설정합니다.
  3. 그런 다음, 바디 콜라이더를 만듭니다. GameObject > 3D Object > Cube 로 이동합니다. 이 큐브를 car_root 아래의 자식 게임 오브젝트로 만듭니다. 트랜스폼을 0 으로 초기화하여 로컬 공간에 정확히 맞춥니다. 자동차는 Z축을 향하므로, 트랜스폼의 Z Scale3 으로 설정합니다.
  4. 휠 루트를 추가합니다. car_rootGameObject > Create Empty Child 를 선택합니다. 이름을 wheels로 변경합니다. 해당 Transform을 초기화합니다. 이 게임 오브젝트는 필수는 아니지만 나중에 튜닝하고 디버깅하는 데 유용합니다.
  5. 첫 휠을 생성하려면 wheels 게임 오브젝트를 선택하고 GameObject > Create Empty Child 를 선택한 후 이름을 frontLeft로 지정합니다. Transform을 초기화한 후 Transform Position X 를 –1로, Y 를 0으로, Z 를 1로 설정합니다. 콜라이더를 휠에 추가하려면 Add component > Physics > Wheel Collider 를 선택합니다.
  6. frontLeft 게임 오브젝트를 복제합니다 TransformX 위치를 1로 변경합니다. 이름을 frontRight로 변경합니다.
  7. frontLeftfrontRight 게임 오브젝트를 모두 선택하고 복제합니다. 두 오브젝트의 Transform Z 위치를 모두 –1로 변경합니다. 이름을 각각 rearLeftrearRight로 변경합니다.
  8. 마지막으로, car_root 게임 오브젝트를 선택하고 이동 도구를 사용하여 지면에서 약간 위로 올립니다.

이제 다음과 같이 표시됩니다.

이 자동차를 실제로 운전할 수 있게 하려면 자동차 컨트롤러를 작성해야 합니다. 다음 코드 샘플이 컨트롤러로 작동합니다.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
    
public class SimpleCarController : MonoBehaviour {
    public List<AxleInfo> axleInfos; // the information about each individual axle
    public float maxMotorTorque; // maximum torque the motor can apply to wheel
    public float maxSteeringAngle; // maximum steer angle the wheel can have
        
    public void FixedUpdate()
    {
        float motor = maxMotorTorque * Input.GetAxis("Vertical");
        float steering = maxSteeringAngle * Input.GetAxis("Horizontal");
            
        foreach (AxleInfo axleInfo in axleInfos) {
            if (axleInfo.steering) {
                axleInfo.leftWheel.steerAngle = steering;
                axleInfo.rightWheel.steerAngle = steering;
            }
            if (axleInfo.motor) {
                axleInfo.leftWheel.motorTorque = motor;
                axleInfo.rightWheel.motorTorque = motor;
            }
        }
    }
}
    
[System.Serializable]
public class AxleInfo {
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor; // is this wheel attached to motor?
    public bool steering; // does this wheel apply steer angle?
}

새 C# 스크립트(Add Component > New Script)를 생성하고 car_root 게임 오브젝트에서 이 샘플을 스크립트 파일로 복사한 후 저장합니다. 아래 그림과 같이 스크립트 파라미터를 조정할 수 있습니다. 설정을 다양하게 해서 실험해보고 재생 모드로 전환하여 결과를 테스트합니다.

자동차 컨트롤러로는 다음 설정이 매우 효과적입니다.

힌트: AxleInfosize를 증가시켜야 합니다.

자동차 인스턴스 하나에 스티어링, 모터, 제동 토크를 가하는 휠을 20개까지 포함할 수 있습니다.

다음으로, 비주얼 휠로 넘어갑니다. 그림에서 볼 수 있듯이, 휠 콜라이더는 시뮬레이션된 휠 포지션과 회전을 휠 콜라이더의 트랜스폼에 다시 적용하지 않으므로 비주얼 휠을 추가하려면 몇 가지 팁을 활용해야 합니다.

우선 휠 지오메트리가 필요합니다. 원기둥으로 간단한 휠 모양을 만들 수 있습니다. 스트립트 프로퍼티에서 비주얼 휠을 수동으로 할당하거나, 대응되는 비주얼 휠을 자동으로 찾는 로직을 작성하는 등의 몇 가지 방법으로 비주얼 휠을 추가할 수 있습니다. 이 튜토리얼에서는 두 번째 방법을 사용합니다. 비주얼 휠을 휠 콜라이더 게임 오브젝트에 부착합니다.

다음으로, 컨트롤러 스크립트를 다음과 같이 변경합니다.

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

[System.Serializable]
public class AxleInfo {
    public WheelCollider leftWheel;
    public WheelCollider rightWheel;
    public bool motor;
    public bool steering;
}
     
public class SimpleCarController : MonoBehaviour {
    public List<AxleInfo> axleInfos; 
    public float maxMotorTorque;
    public float maxSteeringAngle;
     
    // finds the corresponding visual wheel
    // correctly applies the transform
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0) {
            return;
        }
     
        Transform visualWheel = collider.transform.GetChild(0);
     
        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);
     
        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }
     
    public void FixedUpdate()
    {
        float motor = maxMotorTorque * Input.GetAxis("Vertical");
        float steering = maxSteeringAngle * Input.GetAxis("Horizontal");
     
        foreach (AxleInfo axleInfo in axleInfos) {
            if (axleInfo.steering) {
                axleInfo.leftWheel.steerAngle = steering;
                axleInfo.rightWheel.steerAngle = steering;
            }
            if (axleInfo.motor) {
                axleInfo.leftWheel.motorTorque = motor;
                axleInfo.rightWheel.motorTorque = motor;
            }
            ApplyLocalPositionToVisuals(axleInfo.leftWheel);
            ApplyLocalPositionToVisuals(axleInfo.rightWheel);
        }
    }
}

Wheel Collider 컴포넌트의 중요한 파라미터 중 하나는 정지된 휠의 베이스에서 휠의 힘이 가해지는 점까지의 거리인 Force App Point Distance 입니다. 기본값은 0으로, 정지된 휠의 베이스에 힘을 가하도록 설정되어 있는데 실제로는 이 점을 자동차의 무게 중심보다 약간 낮은 위치로 지정하는 것이 좋습니다.

연속 충돌 검사(CCD)
Physics Debug 창 레퍼런스