This document is about: FUSION 1
SWITCH TO

수정중인 페이지 입니다.

프리팹

개요

루트 GameObjectNetworkObject 스크립트가 있고 Is Spawnable 확인란이 선택된 프리팹은 런타임에 생성될 수 있습니다.

Prefab NO with IsSpawnable
스폰할 수 있는 네트워크 객체 프리팹

Fusion은 가능할 때마다 NetworkObject 프리팹에 대한 하드 레퍼런스 생성을 피합니다. 프리팹이 어드레싱 가능하거나 리소스인 경우, Fusion은 직접 프리팹을 참조하지 않고 대신 어드레스/리소스 경로를 저장합니다. 그렇지 않은 경우 프리팹에 대한 하드 레퍼런스가 구성에 저장됩니다.

사용자 코드가 하드 레퍼런스를 형성하지 않도록 하려면 NetworkPrefabRef 타입을 사용하여 프리팹을 참조합니다. NetworkPrefabRef는 프리팹의 GUID를 기반으로 하므로 프로젝트 내 프리팹의 이름 변경/이동에 탄력적입니다.

프리팹 등록하기

Fusion은 네트워크 스폰을 수행하기 전에 프리팹을 등록해야 하며, 프리팹 GUID와 이를 로드하는 데 필요한 데이터(주소, 자원 경로 또는 정적 참조)는 NetworkProjectConfig.PrefabTable 속성으로 접근 가능한 NetworkPrefabTable에 저장됩니다.

빌드 시 존재하는 프로젝트에서 생성 가능한 모든 NetworkObject 프리팹이 자동으로 검출되어 등록됩니다. 이는 NetworkProjectConfigPrefabs 속성을 검사하여 확인할 수 있습니다.

  • [A]Addressable 의 약자입니다.
  • [R]Resources 프리팹의 약자입니다.
  • [S]Statically-referenced 프리팹의 약자입니다.
Prefab list
구성에 저장된 스폰 가능한 프리팹 정보
프리팹은 수동으로 추가, 제거, 순서 변경이 불가능합니다. 대신 프리팹의 Is Spawnable확인란을 사용하십시오.

또는 프리팹의 Prefab Source 라벨 필드를 검사할 수도 있습니다.

PrefabSource
정적으로 참조되는 프리팹(Resource 및 addressable이 아님)에 대한 Prefab Source.

테이블이 불완전하거나 Prefab Source에 잘못된 값이 표시될 경우, Fusion > Rebuild Prefab Table 메뉴 항목 또는 구성 인스펙터의 Rebuild Prefab Table 버튼을 사용합니다.

생성 가능한 모든 프리팹에는 FusionPrefab 라벨도 붙어 있습니다. 이것은 l:FusionPrefab을 프로젝트 창 검색창에서 용어로 사용할 수 있음을 의미합니다:

FusionPrefab label
`FusionPrefab` 레이블로 에셋 검색

빌드 시에 존재하지 않는 프리팹(예: 절차적으로 생성되거나 빌드 수명 동안 Addressable이 추가된 새로운 프리팹)은 런타임에 NetworkPrefabTable.TryAdd에 등록할 수 있습니다.

C#

// this will register an Addressable prefab with a know guid without having to load it first
NetworkPrefabId RegisterAddressablePrefab(NetworkProjectConfig config, NetworkObjectGuid guid) 
{
    var source = ScriptableObject.CreateInstance<NetworkPrefabSourceUnityAddressable>();
    source.Address = new AssetReferenceGameObject(guid.ToUnityGuidString());
    
    if (config.PrefabTable.TryAdd(guid, source, out var id)) {
        return id;
    }
    
    throw new ArgumentException($"Failed to register addressable guid: {guid}");
}

// this will register any prefab, but it needs to be loaded first (from whatever the source)
NetworkPrefabId RegisterPrefab(NetworkProjectConfig config, NetworkObject prefab) 
{
    var source = new NetworkPrefabSourceStatic {
        PrefabReference = prefab
    };
    
    if (config.PrefabTable.TryAdd(prefab.NetworkGuid, source, out var id)) {
        return id;
    }
    
    throw new ArgumentException($"Failed to register prefab with guid: {prefab.NetworkGuid}");
}
모든 클라이언트는 정확히 같은 순서로 프리팹을 등록해야 합니다(NetworkPrefabId 할당은 순차적입니다). 프리팹을 스폰 하기 전에 모든 클라이언트에 등록해야 합니다(예: 러너를 시작하기 전에 등록).

프리팹 스폰

NetworkPrefabRef 사용

프리팹을 생성하려면 NetworkRunner.Spawn 메소드 중 하나를 사용합니다. 권장되는 방법은 NetworkPrefabRef 필드를 사용하여 하드 레퍼런스가 형성되는 것을 방지하기 때문에 프리팹을 참조하고 생성하는 것입니다.

C#

public class SpawnWithNetworkPrefabRef : NetworkBehaviour {
  public NetworkPrefabRef PrefabRef;

  public NetworkObject SpawnPrefab() {
    return Runner.Spawn(PrefabRef);
  }
}

Prefab이 addressable 또는 Resource인 경우 Fusion은 스폰에서 돌아오기 전에 실제 프리팹을 로드합니다. Addressable의 경우 AsyncOperationHandle.WaitForCompletion을 사용하여 프리팹이 로드되었는지 확인합니다. 리소스의 경우에는 Resources.Load를 사용합니다. 이로 인해 상당한 지연이 발생할 경우 프리팹 사전 로딩을 고려하십시오. - FusionAddressablePrefabsPreloader는 샘플 구현을 제공합니다.

비동기 로딩은 계획되어 있으나 아직은 지원하지 않습니다.

프리팹 레퍼런스 사용하기

또한, NetworkObject, GameObject 또는 SimulationBehaviour 하위 클래스 참조를 사용할 수 있습니다. Spawn은 전달된 참조가 스폰 가능한 프리팹의 루트인 GameObject에 속하지 않으면 InvalidOperationException 발생합니다. NetworkObject 그리고 GameObject 참조의 경우에는 [NetworkPrefab] 속성을 사용하여 인스펙터의 선택을 스폰 가능한 프리팹으로만 제한할 수 있습니다.

C#

public class SpawnWithReferences : NetworkBehaviour {
  [NetworkPrefab]
  public GameObject GameObjectRef;
  [NetworkPrefab]
  public NetworkObject NetworkObjectRef;
  public NetworkTransform SimulationBehaviourSubclassRef;

  public NetworkObject SpawnWithGameObjectRef() {
    return Runner.Spawn(GameObjectRef);
  }

  public NetworkObject SpawnWithNetworkObjectRef() {
    return Runner.Spawn(NetworkObjectRef);
  }

  public NetworkTransform SpawnWithSimulationBehaviourSubclassRef() {
    return Runner.Spawn(SimulationBehaviourSubclassRef);
  }
}
위의 코드는 하드 레퍼런스를 생성합니다. 참조된 프리팹이 어드레싱 가능한 경우 빌드에 하나의 복사본과 어드레싱 가능한 데이터에 하나의 복사본으로 효과적으로 복제됩니다.

NetworkPrefabId 사용하기

프리팹을 NetworkPrefabTable에 등록하면 NetworkPrefabId가 리턴됩니다. 이 타입은 크기와 네트워크에 최적화되어 있으며 프로젝트에 다른 프리팹을 추가/제거하면 프리팹의 값이 달라질 수 있기 때문에 런타임에만 사용하도록 되어 있습니다. 이 타입은 NetworkPrefabTable.TryAdd에 수동으로 추가 프리팹을 등록할 때 특히 유용합니다.

C#

public class SpawnWithNetworkPrefabId : NetworkBehaviour {
  [NonSerialized]
  public NetworkPrefabId PrefabId;
  public UnityEngine.AddressableAssets.AssetReferenceGameObject PrefabRef;

  public void RegisterPrefab() {
    var source = ScriptableObject.CreateInstance<NetworkPrefabSourceUnityAddressable>();
    source.Address = PrefabRef;
    if (!Runner.Config.PrefabTable.TryAdd(NetworkObjectGuid.Parse(PrefabRef.AssetGUID), source, out PrefabId)) {
      Debug.LogError($"Failed to register {PrefabRef}");
    }
  }

  public NetworkObject SpawnPrefab() {
    Debug.Assert(PrefabId.IsValid);
    return Runner.Spawn(PrefabId);
  }
}

동적으로 등록된 프리팹은 GUID 또는 객체 참조(이미 로드된 경우)와 함께 생성될 수도 있습니다.

사용자 지정

프리팹을 참조하는 다른 방법을 사용할 수도 있습니다. Addressable과 AssetReferenceGameObject 필드를 사용하는 기존 프로젝트는 이미 프리팹을 먼저 로드한 다음 결과 참조를 사용하여 스폰 할 수 있습니다:

C#

public class SpawnWithAddressables : NetworkBehaviour {
  public UnityEngine.AddressableAssets.AssetReferenceGameObject AddressablePrefabRef;

  public void SpawnAsync() {
    AddressablePrefabRef.LoadAssetAsync().Completed += asyncOpHandle => {
      Runner.Spawn(asyncOpHandle.Result); // asyncOpHandle.Result is of GameObject type
    };
  }
}

프리팹을 참조하기 위한 리소스 경로를 이미 사용하고 있는 프로젝트에도 유사한 접근 방식이 사용될 수 있습니다.

사용자 지정 콘텐츠 제공

프로젝트가 사용자 지정 콘텐츠 전달 시스템에 의존하는 경우 커스텀 프리팹 소스 구현을 고려해야 합니다. 이를 통해 사용자는 프리팹이 런타임에 로드되는 방식에 관계없이 NetworkPrefabRef, 에셋 참조 및 편집기 프리팹 자동 검색을 계속 사용할 수 있습니다. 다음은 에셋 번들 기반의 사용자 지정 프리팹 소스 구현 방법을 간략화한 샘플입니다.

먼저, INetworkPrefabSource를 구현하는 런타임 클래스가 필요합니다. 인터페이스는 하나의 프리팹을 로드하는 데 필요한 데이터와 로직을 나타냅니다. 다음 코드는 INetworkPrefabSource를 직접 구현하는 대신 기본 구현을 제공하는 ScriptableObject 기반의 기본 클래스인 NetworkPrefabSourceUnityBase를 사용합니다.

C#

public class NetworkPrefabSourceUnityAssetBundles : NetworkPrefabSourceUnityBase {
  // name of the asset bundle
  public string AssetBundleName;
  // name of the asset in the asset bundle
  public string AssetName;

  private GameObject _prefab;

  // this is what gets displayed in prefab's Prefab Source label field
  public override string EditorSummary => $"[AssetBundle: {AssetBundleName}[{AssetName}]]";

  public override void Load(in NetworkPrefabLoadContext context) {

    // load the bundle, if not yet loaded
    var bundle = AssetBundle.GetAllLoadedAssetBundles()
      .FirstOrDefault(x => x.name == AssetBundleName);

    if (bundle == null) {
      var bundlePath = System.IO.Path.Combine(Application.streamingAssetsPath, AssetBundleName);
      bundle = AssetBundle.LoadFromFile(bundlePath);
    }

    if (bundle == null) {
      context.Error(new InvalidOperationException($"Unable to load asset bundle {AssetBundleName}"));
    } else {
      // actually load the prefab
      _prefab = bundle.LoadAsset<GameObject>(AssetName);
      context.Loaded(_prefab);
    }
  }

  public override void Unload() {
    if (_prefab) {
      Destroy(_prefab);
      _prefab = null;
    }
  }
}

다음으로, INetworkPrefabSourceFactory의 편집기 전용 구현이 필요합니다. 결과 클래스는 assetPath에서 생성 가능한 프리팹이 사용자 정의 에셋 로딩을 사용해야 하는지를 감지합니다. 만약 그렇다면, NetworkPrefabSourceUnityAssetBundles의 초기화된 인스턴스를 반환합니다. Fusion 편집기 스크립트에 의해 자동으로 감지되므로 팩토리 자체를 등록할 필요가 없습니다.

C#

public class NetworkPrefabAssetFactoryAssetBundles : INetworkPrefabSourceFactory {
  int INetworkPrefabSourceFactory.Order => 0;
  Type INetworkPrefabSourceFactory.SourceType => typeof(NetworkPrefabSourceUnityAssetBundles);

  NetworkPrefabSourceUnityBase INetworkPrefabSourceFactory.TryCreate(string assetPath) {
    var prefabBundle = AssetDatabase.GetImplicitAssetBundleName(assetPath);
    if (!string.IsNullOrEmpty(prefabBundle)) {
      var result = ScriptableObject.CreateInstance<NetworkPrefabSourceUnityAssetBundles>();
      result.AssetBundleName = prefabBundle;
      result.AssetName = System.IO.Path.GetFileName(assetPath);
      return result;
    }
    // returning null instructs Fusion to use other factories with greater Order
    return null;
  }
}

이를 사용하면 에셋 번들에 할당된 스폰 가능한 프리팹은 해당 프리팹 소스를 에셋 번들로 표시하고 구성 인스펙터 프리팹 속성 항목은 [AB]로 접두사를 붙여야 합니다. 만약 그렇지 않은 경우에는 Fusion > Rebuild Prefab Table 메뉴 항목을 사용하는 것이 좋습니다.

Prefab assigned to an Asset Budle
`testassetbundle` 에셋 번들에 할당된 프리팹.
Prefab assigned to an Asset Budle
구성 `Prefabs` 속성의 항목.
운영 준비가 완료된 구현에서는 번들 수명 및 종속성 관리를 처리해야 합니다. 또한 Rebuild Prefab Table을 반복적으로 사용하지 않으려면 에셋 번들 할당 변경 사항을 듣기 위해 일부 편집기 통합 코드가 필요합니다(NetworkPrefabAssetFactoryAddressable 확인).
Back to top