Version: 5.3
조인트 및 래그돌 안정성
스크립팅

WheelCollider 튜토리얼(WheelCollider Tutorial)

새 WheelCollider는 PhysX2에 비해 완전히 새로운 차량 시뮬레이션 라이브러리인 PhysX3 Vehicles SDK로 구동됩니다.

Unity 5.0에서 기본 기능만 있는 차량을 만드는 프로세스를 살펴보겠습니다.

Start by selecting GameObject -> 3D Object -> Plane. This is the ground the car is going to drive on. Make sure the ground has zero transform (Transform -> Reset) for simplicity. Scale it by putting something like 100 in Transform scale components.

Create a basic car skeleton:

  1. 먼저 게임 오브젝트를 차량 루트 오브젝트로 추가합니다(GameObject -> Create Empty). 이름을 car_root로 변경합니다.

  2. car_root에 Physics 3D Rigidbody 컴포넌트를 추가합니다. 기본 질량 1kg은 기본 서스펜션 설정으로 너무 가볍습니다. 1,500kg으로 변경합니다.

  3. 차량 바디 콜라이더를 만들고 car_root 아래 박스를 부모로 지정합니다(GameObject -> 3D Object -> Cube). 로컬 공간에서 완벽하게 정렬되도록 변환을 초기화합니다. 차량 방향이 Z축을 따를 것이므로 z 스케일링을 3으로 설정하여 Z축을 따라 박스를 스케일합니다.

  4. 휠 루트를 추가합니다. car_root와 GameObject -> Create Empty Child를 선택합니다. 이름을 wheels로 변경합니다. 변환을 초기화합니다. 이 노드는 필수는 아니지만, 나중에 편리한 미세 조정을 위해 사용합니다.

  5. 첫 번째 휠을 만듭니다. wheels 오브젝트, GameObject -> Create Empty Child를 선택하고 이름을 frontLeft로 지정합니다. 변환을 초기화합니다. 포지션을 (–1, 0, 1)로 설정합니다. Physics Component -> Wheel Collider를 휠에 추가합니다.

  6. frontLeft 오브젝트를 복제합니다(Cmd+D 또는 Ctrl+D). x 포지션을 1로 변경합니다. 이름을 frontRight로 변경합니다.

  7. frontLeftfrontRight 오브젝트를 모두 선택하고 복제합니다. 두 오브젝트의 z 포지션을 모두 –1로 변경합니다. 이름을 각각 rearLeftrearRight로 변경합니다.

  8. 마지막으로, car_root 오브젝트를 선택하고, 트랜스폼 조종기를 사용해 지면에서 약간 위로 올립니다.

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

 ![](../uploads/Main/WheelColliderTutorial.png)

To make this car actually drivable we need to write a controller for it. Let’s dive into some scripting:


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?
}

Just drop this snippet on the car_root object, tune the script parameters as shown below and kick off to play mode. Play around with the settings, Those shown below seem to work reasonably well:

You can have up to 20 wheels on a single vehicle instance with each of them applying steering, motor or braking torque.


Now we will move on to visual wheels. As can see, WheelCollider doesn’t apply the simulated wheel position and rotation back to WheelCollider’s transform. So adding visual wheel requires some tricks.

  1. 여기에는 휠 지오메트리가 몇 개 필요합니다. 실린더를 사용하여 간단한 휠 모양을 만들 수 있습니다.

  2. 비주얼 휠을 추가하는 두 가지 방법이 있습니다. 첫 번째는 스크립트 프로퍼티에서 비주얼 휠을 수동으로 할당하는 것이고, 두 번째는 약간의 로직을 작성하여 자동으로 해당 비주얼 휠을 찾도록 하는 것입니다. 여기서는 후자를 선택하겠습니다.

  3. 비주얼 휠을 휠 콜라이더 오브젝트에 부착합니다.

  4. 이제 컨트롤러 스크립트를 다음과 같이 변경합니다.

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);
        }
    }
}
        

One important parameter of WheelCollider component is forceAppPointDistance. This is the distance from the base of the resting wheel to the point where the wheel forces are applied at. The default value is 0, which means to apply the forces at the base of the resting wheel, but actually, it is wise to have this point located somewhere slightly below the car’s centre of mass.

조인트 및 래그돌 안정성
스크립팅