-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLoadingProgressManager.cs
152 lines (139 loc) · 5.13 KB
/
LoadingProgressManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
namespace Unity.Multiplayer.Samples.Utilities
{
/// <summary>
/// Contains data on scene loading progress for the local instance and remote instances.
/// </summary>
public class LoadingProgressManager : NetworkBehaviour
{
[SerializeField]
GameObject m_ProgressTrackerPrefab;
/// <summary>
/// Dictionary containing references to the NetworkedLoadingProgessTrackers that contain the loading progress of
/// each client. Keys are ClientIds.
/// </summary>
public Dictionary<ulong, NetworkedLoadingProgressTracker> ProgressTrackers { get; } = new Dictionary<ulong, NetworkedLoadingProgressTracker>();
/// <summary>
/// This is the AsyncOperation of the current load operation. This property should be set each time a new
/// loading operation begins.
/// </summary>
public AsyncOperation LocalLoadOperation
{
set
{
m_IsLoading = true;
LocalProgress = 0;
m_LocalLoadOperation = value;
}
}
AsyncOperation m_LocalLoadOperation;
float m_LocalProgress;
bool m_IsLoading;
/// <summary>
/// This event is invoked each time the dictionary of progress trackers is updated (if one is removed or added, for example.)
/// </summary>
public event Action onTrackersUpdated;
/// <summary>
/// The current loading progress for the local client. Handled by a local field if not in a networked session,
/// or by a progress tracker from the dictionary.
/// </summary>
public float LocalProgress
{
get => IsSpawned && ProgressTrackers.ContainsKey(NetworkManager.LocalClientId) ?
ProgressTrackers[NetworkManager.LocalClientId].Progress.Value : m_LocalProgress;
private set
{
if (IsSpawned && ProgressTrackers.ContainsKey(NetworkManager.LocalClientId) && ProgressTrackers[NetworkManager.LocalClientId].IsSpawned)
{
ProgressTrackers[NetworkManager.LocalClientId].Progress.Value = value;
}
else
{
m_LocalProgress = value;
}
}
}
public override void OnNetworkSpawn()
{
if (IsServer)
{
NetworkManager.OnClientConnectedCallback += AddTracker;
NetworkManager.OnClientDisconnectCallback += RemoveTracker;
AddTracker(NetworkManager.LocalClientId);
}
}
public override void OnNetworkDespawn()
{
if (IsServer)
{
NetworkManager.OnClientConnectedCallback -= AddTracker;
NetworkManager.OnClientDisconnectCallback -= RemoveTracker;
}
ProgressTrackers.Clear();
onTrackersUpdated?.Invoke();
}
void Update()
{
if (m_LocalLoadOperation != null && m_IsLoading)
{
if (m_LocalLoadOperation.isDone)
{
m_IsLoading = false;
LocalProgress = 1;
}
else
{
LocalProgress = m_LocalLoadOperation.progress;
}
}
}
[Rpc(SendTo.ClientsAndHost)]
void ClientUpdateTrackersRpc()
{
if (!IsHost)
{
ProgressTrackers.Clear();
foreach (var tracker in FindObjectsOfType<NetworkedLoadingProgressTracker>())
{
// If a tracker is despawned but not destroyed yet, don't add it
if (tracker.IsSpawned)
{
ProgressTrackers[tracker.OwnerClientId] = tracker;
if (tracker.OwnerClientId == NetworkManager.LocalClientId)
{
LocalProgress = Mathf.Max(m_LocalProgress, LocalProgress);
}
}
}
}
onTrackersUpdated?.Invoke();
}
void AddTracker(ulong clientId)
{
if (IsServer)
{
var tracker = Instantiate(m_ProgressTrackerPrefab);
var networkObject = tracker.GetComponent<NetworkObject>();
networkObject.SpawnWithOwnership(clientId);
ProgressTrackers[clientId] = tracker.GetComponent<NetworkedLoadingProgressTracker>();
ClientUpdateTrackersRpc();
}
}
void RemoveTracker(ulong clientId)
{
if (IsServer)
{
if (ProgressTrackers.ContainsKey(clientId))
{
var tracker = ProgressTrackers[clientId];
ProgressTrackers.Remove(clientId);
tracker.NetworkObject.Despawn();
ClientUpdateTrackersRpc();
}
}
}
}
}