This document is about: FUSION 1
SWITCH TO

수정중인 페이지 입니다.

Metaverse Music


Available in the Industries Circle
Circle

개요

Music 씬을 통해 플레이어는 소리와 음악을 트리거하고 조명 쇼를 제어할 수 있는 패드로 DJ 기술을 테스트할 수 있습니다. 여기에서는 네트워크를 통해 오디오 트랙 또는 조명을 동기화하는 방법을 보여 줍니다. 씬에는 여러 개의 DJ 패드가 포함됩니다. 어떤 것은 음악을 통제하고 다른 것은 조명을 통제합니다.

데스크톱 모드에서는 마우스로 UI를 더 잘 제어할 수 있도록 각 패드의 하단에 있는 확대/축소 아이콘을 사용하여 전체 화면으로 표시할 수 있습니다.

fusion metaverse music

뮤직 패드

각 뮤직 패드는 하나 이상의 버튼으로 구성되어 있습니다. 각 버튼은 오디오 소스와 사운드에 해당합니다. 사운드를 루프로 설정할 수 있습니다. 뮤직 패드에는 볼륨을 변경하기 위한 슬라이더가 포함되어 있습니다.

fusion metaverse music

DJ 패드는 3개 클래스에 의해 관리됩니다:

  • DJPadVolumeSlider : 패드의 볼륨을 관리합니다
  • DJPadTouch : 사운드 버튼을 관리합니다
  • DJPadManager : 패드의 전반적인 기능을 관리합니다

DJPadVolumeSlider

플레이어가 슬라이더를 터치하여 볼륨을 변경하면 DJPadVolumeSliderDJPadManager ChangeVolume 메서드를 호출합니다.

C#

void RequestVolumeChange(float volume)
{
    padManager.ChangeVolume(volume);
}

public async void ChangeVolume(float volume)
{
    // We use an attribute, so if another volume is requested while taking the authority, the last volume request is the one executed
    lastVolumeRequest = volume;
    if (!Object.HasStateAuthority)
    {
        await Object.WaitForStateAuthority();
    }
    MasterVolume = lastVolumeRequest;
}

그런 다음 DJPadManager의 네트워크 변수 MasterVolume이 네트워크를 통해 동기화됩니다.

C#

[Networked(OnChanged = nameof(OnMasterVolumeChanged))]
public float MasterVolume { get; set; } = 1;

static void OnMasterVolumeChanged(Changed<DJPadManager> changed)
{
    changed.Behaviour.OnMasterVolumeChanged();
}

void OnMasterVolumeChanged()
{
    if(volumeManager != null) volumeManager.OnVolumeChanged(this, MasterVolume);
}

모든 사용자가 로컬 볼륨을 업데이트할 수 있도록 합니다.

C#

public void OnVolumeChanged(DJPadManager bPMClipsPlayer, float volume)
{
    ChangeSliderValue(volume);
}

DJPadTouch

각 버튼은 인덱스를 참조하므로 DJPadManager 는 각 오디오 소스를 제어하는 버튼을 알고 오디오 소스 상태가 변경될 때 알림을 받아야 하는 버튼을 알 수 있습니다. 그래서 사용자가 버튼을 누르면 DJPadTouchUpdatePadStatus() 메소드를 호출합니다. 그러면 UpdatePadStatus()DJPadManager에게 새 상태를 알립니다.

C#

public void UpdatePadStatus()
{
    if (audioSource.clip)
    { 
        isPlaying = !isPlaying;
        padManager.ChangeAudioSourceState(this, isPlaying);
    }
}

또한 버튼이 터치되면 DJPadManagerDJPadTouchOnAudioSourceStatusChanged 메소드를 호출하여 새로운 상태에 따라 버튼 색상을 업데이트하도록 요청합니다.

DJPadManager

각 버튼의 상태는 PadsStatus라는 네트워크 사전 덕분에 동기화됩니다.

C#

[Networked]
Capacity(50)]
public NetworkDictionary<int, NetworkBool> PadsStatus { get; }

처음에 DJPadManager는 모든 버튼을 audioSourceManagers 딕셔너리에 저장합니다(모든 DJPadTouchIAudioSourceManager 인터페이스를 구현합니다).

C#

foreach (var manager in GetComponentsInChildren<IAudioSourceManager>(true))
{
    audioSourceManagers[manager.AudioSourceIndex] = manager;
}

DJPadManagerChangeAudioSourceState()로 표시된 새 버튼 상태를 수신하면 상태 요청시 권한이 아직 없는 경우 권한을 부여한 다음 모든 원격 사용자가 업데이트를 받을 수 있도록 네트워크 딕셔너리를 업데이트합니다.

C#

public async void ChangeAudioSourceState(IAudioSourceManager audioSourceManager, bool isPlaying)
{
    if (!Object.HasStateAuthority)
    {
        await Object.WaitForStateAuthority();
    }
    PadsStatus.Set(audioSourceManager.AudioSourceIndex, isPlaying);
}

RefreshPads(), SyncAudioSource() & OnAudioStatusChanged() 메소드는 다음의 역할을 합니다 :

  • 볼륨 슬라이더 값에 따라 각 버튼(DJPadTouch)의 오디오 소스를 업데이트합니다
  • 버튼 상태가 변경된 경우(예: 오디오 클립이 완료된 경우) 패드 네트워크 사전 업데이트
  • 네트워크 사전에 따라 각 버튼의 오디오 소스(플레이/정지)를 동기화
  • 버튼 색상을 업데이트하기 위해 상태가 변경되었음을 버튼에 알립니다

네트워크 된 딕셔너리가 변경되는 즉시 이러한 업데이트를 수행하는 대신 사전 정의된 BPM 매개 변수를 기반으로 정기적으로 수행됩니다 (AudioLoop() 메소드).

라이트 패드

라이트 패드는 4개의 조명을 제어합니다. 각 조명에 대해 패드를 사용하면 다음 작업을 수행할 수 있습니다:

  • 전등 켬/끔
  • 전등 움직임 켬/끔
  • 광도 변경

라이트 패드 구조는 뮤직 패드와 매우 유사합니다. 조명은 다음 클래스에 의해 관리됩니다:

  • LightPadManager : 패드의 전반적인 기능을 관리
  • LightPadTouch : 조명 버튼 관리
  • LightSystem : 조명 상태 관리
  • LightIntensitySlider : 빛의 강도를 관리
  • LightDirectionControler : 빛의 회전을 관리

LightIntensitySlider

LightIntensitySliderDJPadVolumeSlider와 매우 유사합니다. 플레이어가 슬라이더를 터치하여 강도를 변경하면 RequestIntensityChangeLightPadManager ChangeIntensity() 메소드를 호출합니다.

반대로 원격 플레이어가 강도를 변경된 경우 LightPadManagerOnLightStatusChanged 메소드를 호출해 슬라이더 위치를 업데이트합니다.

LightPadTouch

LightPadTouch는 라이트 버튼을 관리합니다. LightPadManager에 정의된 바와 같이 3가지 종류의 라이트 버튼이 있습니다:

C#

public enum LightManagerType
    {
        OnOff,              // switch on/off the light
        Movement,           // switch on/off the movement
        Intensity           // slider to change the intensity
    }

각 버튼은 라이트 인덱스를 참조하므로 LightPadManager는 각 라이트를 제어하는 버튼을 알고 조명 상태가 변경될 때 어떤 버튼을 통지해야 하는지를 알 수 있습니다.

UpdatePadStatus()는 플레이어가 버튼을 누르면 호출됩니다. 상태가 바뀌어야 한다는 것을 PadManager에게 알립니다. OnLightStatusChanged()는 상태가 변경되면 PadManager에 의해 호출되므로 버튼 UI를 업데이트해야 합니다.

LightSystem

LightSystem 클래스는 추상 클래스 EffectSystem에서 상속됩니다. LightSystemChangeState 메소드로 수신된 파라미터에 따라 조명 상태를 변경합니다:

LightDirectionControler

LightDirectionControler 클래스는 라이트 게임 객체를 회전시키는 로테이터 스크립트를 제어합니다. LightDirectionControler는 LightSystem에 의해 활성화/비활성화됩니다.

LightPadManager

LightPadManager는 모든 라이트 객체(LightInfo)를 참조합니다.

각각의 LightInfo에는 빛 매개변수를 수정할 수 있는 인덱스와 효과 시스템이 있습니다.

C#

public struct LightInfo 
{
    public int lightIndex;
    public EffectSystem effectSystem;
}

시작할 때 LightPadManager는 모든 라이트 버튼을 사전에 등록합니다.

또한 조명의 다양한 매개변수(조명 켜기/끄기, 이동 켜기/끄기, 조명 강도)를 저장할 수 있는 3개의 네트워크 딕셔너리가 있습니다.

C#

[Networked(OnChanged = nameof(OnLightStatusChanged))]
[Capacity(MAX_LIGHTS)]
public NetworkDictionary<int, NetworkBool> LightStatus { get; }

[Networked(OnChanged = nameof(OnLightMovementStatusChanged))]
[Capacity(MAX_LIGHTS)]
public NetworkDictionary<int, NetworkBool> LightMovementStatus { get; }

[Networked(OnChanged = nameof(OnLightIntensityChanged))]
[Capacity(MAX_LIGHTS)]
public NetworkDictionary<int, float> LightIntensities { get; }

로컬 플레이어가 버튼을 누르면 LightPadManager가 관련 메소드(ChangeLightState()/ChangeMovementState()/ChangeIntensity())에 의해 알려집니다. 그런 다음 연결된 네트워크 딕셔너리가 업데이트됩니다.

예를 들어 라이트가 켜지거나 꺼지면 LightPadManager가 상태 권한이 없는 경우 네트워크 사전을 업데이트하여 모든 원격 사용자가 업데이트를 받을 수 있도록 StateAuthority를 요청합니다.

C#

public async void ChangeLightState(LightPadTouch lightPadTouch, bool isLightOn)
    {
        if (!Object.HasStateAuthority)
        {
            await Object.WaitForStateAuthority();
        }

        // update network status
        LightStatus.Set(lightPadTouch.LightIndex, isLightOn);

        // movement must be stopped if the light is off
        if (!isLightOn)
            LightMovementStatus.Set(lightPadTouch.LightIndex, false);
    }

딕셔너리가 업데이트되는 즉시 Refresh() 메소드는 로컬 및 원격 플레이어에서 호출됩니다.

C#

private static void OnLightStatusChanged(Changed<LightPadManager> changed)
{
    changed.Behaviour.Refresh();
}

private static void OnLightMovementStatusChanged(Changed<LightPadManager> changed)
{
    changed.Behaviour.Refresh();
}

private static void OnLightIntensityChanged(Changed<LightPadManager> changed)
{
    changed.Behaviour.Refresh();
}

Refresh()UpdateLightsAndButtons() 메소드를 사용하여 모든 조명 상태 및 관련 버튼 업데이트를 담당합니다.

플레이어가 참여하면 조명이 네트워크 딕셔너리로 업데이트됩니다.

Back to top