본문 바로가기

Unity3D/C#

유니티 진동 울리기 · 진동 끄기 설정 (Handheld.Vibrate)

반응형

VIBRATE Handheld.Vibrate

 

유니티에서 휴대폰 진동을 한 번 울리려면 Handheld.Vibrate() 를 부릅니다. 진동 길이는 기기(OS)가 정하고, 설정에서 진동을 끈 사용자를 위해 켜짐/꺼짐 값을 저장해 두었다가 부르기 전에 확인합니다.

 

#if UNITY_ANDROID || UNITY_IOS
Handheld.Vibrate();                      // 휴대폰을 한 번 울림
#endif

 

모바일 게임에서 캐릭터가 맞거나 보스가 쓰러질 때 휴대폰이 「드르륵」 울리면 손으로 느끼는 손맛이 생깁니다. 다만 진동을 싫어하는 사람도 많아서 대부분의 게임은 설정 화면에 진동 켜기/끄기를 둡니다. Unity 에서는 Handheld.Vibrate 한 줄로 진동을 울릴 수 있지만, 길이를 정할 수 없고 연달아 부르면 계속 울려서 성가실 수 있습니다. 이번 글에서는 설정의 진동 토글을 PlayerPrefs 에 저장하고, 꺼져 있으면 울리지 않으며, 너무 자주 부르면 건너뛰는 진동 함수를 만들겠습니다. 진동을 켜는 순간에는 한 번 울려서 켜졌다는 것을 알려 주겠습니다.

 

C# (UNITY 3D)

 

 

「맞았다!」 를 누르면 진동이 울리고, 1.5초 안에 다시 누르면 건너뜁니다. 1.5초가 지나면 다시 울립니다. 설정에서 진동을 끄면 눌러도 울리지 않고, 다시 켜는 순간 한 번 울립니다.

 

1. 준비 — 토글 하나와 시험용 버튼 하나

 

Hierarchy 에서 UI (Canvas) > Toggle 로 진동 토글을, UI (Canvas) > Button - TextMeshPro 로 시험용 버튼을 만듭니다. VibrationSetting 은 빈 오브젝트에 붙이고 toggle_vibration · button_hit 칸에 끌어다 넣습니다. 실제 게임에서는 버튼 대신 맞았을 때 부르는 코드에서 Vibrate() 를 부르면 됩니다.

 

using UnityEngine;
using UnityEngine.UI;

 

Toggle 과 Button 을 쓰기 위해 UnityEngine.UI 를 사용합니다. Handheld 는 UnityEngine 에 들어 있습니다.

 

2. 진동 설정 코드

 

using UnityEngine;
using UnityEngine.UI;

//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public class VibrationSetting : MonoBehaviour
{
    public Toggle toggle_vibration;      // 설정 화면의 진동 켜기/끄기
    public Button button_hit;            // 시험용 — 맞았을 때 진동

    const string KEY_VIBRATION = "settings.vibration";
    const float MIN_INTERVAL = 1.5f;     // 이 시간 안에 또 부르면 건너뜀

    float time_last = -10f;              // 마지막으로 울린 때

    void Start()
    {
        if (toggle_vibration != null)
        {
            toggle_vibration.SetIsOnWithoutNotify(Is_On());
            toggle_vibration.onValueChanged.RemoveAllListeners();
            toggle_vibration.onValueChanged.AddListener(Change_Vibration);
        }
        if (button_hit != null)
        {
            button_hit.onClick.RemoveAllListeners();
            button_hit.onClick.AddListener(() => Vibrate());
        }
    }

    bool Is_On()
    {
        return PlayerPrefs.GetInt(KEY_VIBRATION, 1) == 1;                // 처음에는 켜짐
    }

    void Change_Vibration(bool is_on)
    {
        PlayerPrefs.SetInt(KEY_VIBRATION, is_on ? 1 : 0);
        PlayerPrefs.Save();
        if (is_on)
            Vibrate(true);                                               // 켜면 한 번 울려서 알려 줌
    }

    public bool Vibrate(bool force = false)
    {
        if (!Is_On())
            return false;                                                // 설정에서 껐으면 안 울림
        if (!force && Time.unscaledTime - time_last < MIN_INTERVAL)
            return false;                                                // 너무 잦으면 건너뜀

        time_last = Time.unscaledTime;
#if UNITY_ANDROID || UNITY_IOS
        Handheld.Vibrate();                                              // 길이는 기기(OS)가 정함
#endif
        return true;
    }
}

 

이 예제의 Vibrate 는 설정과 간격 검사를 통과하면 true, 꺼져 있거나 건너뛰면 false 를 돌려줍니다. true 는 실제 기기 진동 여부를 확인한 값이 아닙니다. 간격은 Time.unscaledTime 으로 재서 일시정지로 Time.timeScale 을 0 으로 만들어도 그대로 흐릅니다. force 를 true 로 넘기면 간격은 무시하지만, 설정에서 꺼 둔 것은 force 여도 지킵니다.

이 스크립트는 Unity 6000.6.3f1 에서 컴파일 오류 없이 들어갔고, 배치 모드에서 함수를 직접 불러 보니 처음 true, 바로 다시 false, 1.4초 뒤 false, 1.5초 뒤 true 였고, 토글을 끄면 force 여도 false 가 나왔습니다. 에디터는 PC(Windows) 대상이라 #if 안의 Handheld.Vibrate 까지는 가지 않으며, 실제 진동은 휴대폰에서 울려 봐야 합니다.

 

변수(variable)
toggle_vibration(Toggle) : 설정 화면의 진동 켜기/끄기
button_hit(Button) : 시험용으로 진동을 부르는 버튼
KEY_VIBRATION(string) : PlayerPrefs 에 저장할 이름
MIN_INTERVAL(float) : 다시 울리기까지 쉬는 시간(초)
time_last(float) : 마지막으로 울린 때

 

함수(function)
Is_On : 저장된 진동 설정을 읽습니다(처음이면 켜짐).
Change_Vibration : 토글이 바뀌면 저장하고, 켰을 때는 한 번 울립니다.
Vibrate : 켜져 있고 간격이 지났으면 모바일 빌드에서 진동을 요청하고 true 를 돌려줍니다.

 

3. 다른 스크립트에서 부르기

 

if (vibration != null)
    vibration.Vibrate();                 // 꺼져 있거나 1.5초 안이면 그냥 넘어감

 

플레이어나 적 스크립트에 public VibrationSetting vibration; 칸을 하나 만들고 끌어다 넣은 뒤, 맞았을 때 이렇게 부릅니다. 켜짐 확인과 간격 확인을 Vibrate 안에서 모두 하므로 부르는 쪽은 조건 없이 한 줄이면 됩니다.

 

4. 진동이 안 울리거나 너무 울릴 때 — 자주 하는 실수

 

Vibrate 를 불러 본 결과 — 처음은 울림, 바로 다시는 건너뜀, force 는 울림, 1.5초 뒤 울림, 꺼져 있으면 force 여도 안 울림

 

에디터에서는 아무 느낌이 없다
진동은 휴대폰에서만 확인할 수 있습니다. 이 글의 코드는 #if UNITY_ANDROID || UNITY_IOS 로 휴대폰 빌드에서만 Handheld.Vibrate 를 부르게 했습니다. 이 글을 확인한 PC 대상 프로젝트에서는 #if 없이 Handheld.Vibrate 를 써도 컴파일은 되었지만, PC 에서 불렀을 때 무슨 일이 일어나는지는 확인하지 않았으므로 휴대폰에서만 부르는 편이 안전합니다.

 

진동 길이를 바꾸고 싶다
Unity 문서에 따르면 Handheld.Vibrate 의 진동 길이는 기기의 OS 가 정하고, 길이 · 세기 같은 세부 설정은 플랫폼별 라이브러리를 써야 합니다. 이 함수에는 길이나 간격을 정하는 값이 없으므로, 「짧게 두 번」 같은 진동 패턴이 필요하면 플랫폼별 라이브러리를 씁니다.

 

Update 에서 불러 계속 울린다
체력이 낮은 동안 Update 에서 매 프레임 진동을 부르면 휴대폰이 멈추지 않고 울립니다. 2절의 MIN_INTERVAL 처럼 마지막으로 울린 때를 기억해 두고 간격 안이면 건너뜁니다. 꼭 울려야 하는 순간(보스 처치 등)만 force 로 부릅니다.

 

함께 보기: 진동 켜기/끄기처럼 켜짐 · 꺼짐 상태를 다루는 토글은 유니티 Toggle 켜기/끄기 · ToggleGroup 하나만 고르기 에 있습니다.

 

Handheld.Vibrate 동작은 Unity 공식 문서 Handheld.Vibrate 와 Unity 6000.6.3f1 에디터(Windows)에서 함수를 직접 불러 본 결과를 기준으로 적었습니다.

 

설정에서 진동을 끄고 켜는 스위치와 1.5초 안에 또 부르면 건너뛰는 방식은 제가 잰드케이로 만들고 있는 대전 게임 Farm Rumble(아직 출시 전)의 설정 화면에서 실제로 쓰고 있습니다.

 

 

반응형

Google Play 및 Google Play 로고는 Google LLC의 상표입니다.