Unity3D Car/Skid Sound

Car Skid Sound effect in Unity

Soul-Learner 2015. 4. 6. 18:47

유니티에서 자동차 바퀴가 지면 위에서 미끄러질 때 나는 소음(Skid Sound) 출력 예


앞선 내용 참조 : http://micropilot.tistory.com/category/Unity3D%20Car/Friction%20%26%20Slip


사용된 사운드 파일


자동차 바퀴가 옆으로 미끄러지려는 힘이 일정한 수준에 도달할 때 스키드 사운드가 출력되게 하는 예이다.

특정 조건에서 사운드가 출력되고 또 출력을 멈추어야 하므로 스키드 사운드가 Prefab 으로 등록되어 있어야 필요가 있다

Prefab 으로 등록된 게임 오브젝트는 스크립트 안에서 필요할 때 인스턴스를 생성하면 얼마든지 자주 그리고 여러번 사용할 수 있게 된다.

여기서는 SkidSound 라는 EmptyObject 에 Audio Source 콤포넌트를 추가하고 그 Audio Source에 스키드 사운드 클립을 할당하고 SkidSound 오브젝트를 Prefab 에 등록하고 자동차의 바퀴의 sidewaysFriction이 일정한 수준에 도달하면 SkidSound 인스턴스를 생성하고 사운드를 출력하는 예제를 작성하려고 한다



[Prefab 을 준비하기 위해 EmptyObject 에 Audio Source 콤포넌트를 추가하고 사운드 파일을 할당하는 절차]



[위에서 생성한 SkidSound 오브젝트를  Prefab 으로 등록하는 절차]


위와 같은 절차를 마치면 생성된 SkidSound 프리팹이 파란 육면체 모양의 아이콘으로 표시되며스크립트 안에서 인스턴스를 생성할 수 있게 된다


다음과 같이 프리팹 오브젝트의 인스턴스를 동적으로 생성하고 사운드를 출력하는 스크립트를 작성하고 Hierarchy 뷰에 있는 4개의 WheelCollider 에 각각 할당해준다. 참고로, 프리팹 인스턴스를 생성하려면 먼저 원래 프리팹 오브젝트가 있어야 가능하므로 아래의 코드가 실행되기전에 Project 뷰의 프리팹을 드래그하여 아래 코드의 skidSound 변수에 할당해 주어야 한다. 물론 Inspector 뷰에 있는 skidSound 변수에 할당하면 된다


[기본적인 스키드 사운드 출력 기능을 가진 코드]

using UnityEngine;

using System.Collections;


public class SkidSound : MonoBehaviour {


public float currentFrictionValue;

public GameObject skidSound;       // Project 뷰에 있는 SkidSound 프리팹을 드래그하여 할당


void Start () {

}


void Update () {

WheelHit hit;

transform.GetComponent<WheelCollider>().GetGroundHit(out hit);

currentFrictionValue = hit.sidewaysSlip;

currentFrictionValue = Mathf.Abs (currentFrictionValue);

if (currentFrictionValue >= 1.5f) {

Instantiate(skidSound, hit.point, Quaternion.identity);

}

}

}



[위에서 작성한 SkidSound.cs 를 드래그하여 할당]



[스크립트에서 프리팹 인스턴스를 생성하려면 원본 프리팹 오브젝트가 필요하므로 아래처럼 드래그하여 변수에 할당]


위의 절차를 마치고 실행해보면 주행 방향전환을 할 때 스키드 사운드가 출력되는 것을 확인할 수 있다.

그러나 너무 자주 사운드가 출력되고 중복해서 많은 인스턴스가 생성되기 때문에 메모리 사용량이 급격히 늘고 자동차의 움직임이 자연스럽지 못하게 되는 것을 볼 수가 있는데, 프리팹 인스턴스를 생성하고 출력할 때 많은 리소스가 사용되어 성능이 떨어지는 원인이 되는 것도 알 수 있다.


위의 문제를 해결하기 위해서는 코드를 약간 변경하여 아래의 코드처럼 프리팹 인스턴스 생성 간격을 좀더 충분하게 설정해주면 될 것이다


[사운드 출력 간격을 조정하여 리소스 사용량을 줄이기 위한 코드]

using UnityEngine;

using System.Collections;


public class SkidSound : MonoBehaviour {


public float currentFrictionValue;

public GameObject skidSound;

private float waitTime = 0.1f;


void Start () {

}


void Update () {

WheelHit hit;

transform.GetComponent<WheelCollider>().GetGroundHit(out hit);

currentFrictionValue = hit.sidewaysSlip;

currentFrictionValue = Mathf.Abs (currentFrictionValue);

if (currentFrictionValue >= 1.5f && waitTime>=0.1f) {

Instantiate(skidSound, hit.point, Quaternion.identity);

waitTime = 0f;

}else{

waitTime += Time.deltaTime;

}

}

}



또 한가지 문제점은 위의 코드에서 생성된 프리팹 인스턴스는 사용된 후에도 메모리에 남아 있으므로 이들 인스턴스를 재활용하지 않으려면 메모리에서 제거해 주어야 메모리 공간을 재활용할 수 있다는 것이다.


아래와 같은 코드를 작성하여 Project 뷰의 SkidSound 프리팹의 콤포넌트로 추가하면 된다


[사용하지 않는 프리팹 인스턴스를 메모리에서 제거하는 스크립트]

using UnityEngine;

using System.Collections;


public class SkidSoundDestroy : MonoBehaviour {


private float destroyTime;


void Start () {

}


void Update () {

if(destroyTime>=2f) {

print ("스키드사운드 오브젝트 삭제됨");

Destroy(gameObject);

}else {

destroyTime += Time.deltaTime;

}

}

}