mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
sceneID buildIndex byte replaced with scenePath hash and sceneID converted to long to fix #571, #577
This commit is contained in:
parent
ca69cb9c14
commit
1824e8db80
@ -32,7 +32,7 @@ public static void OnPostProcessScene()
|
||||
if (identity.isClient || identity.isServer)
|
||||
continue;
|
||||
|
||||
// valid scene id? then set build index byte
|
||||
// valid scene id? then set scene path part
|
||||
// otherwise it might be an unopened scene that still has null
|
||||
// sceneIds. builds are interrupted if they contain 0 sceneIds,
|
||||
// but it's still possible that we call LoadScene in Editor
|
||||
@ -41,7 +41,7 @@ public static void OnPostProcessScene()
|
||||
// because this function would return afterwards.
|
||||
if (identity.sceneId != 0)
|
||||
{
|
||||
identity.SetSceneIdSceneIndexByteInternal();
|
||||
identity.SetSceneIdSceneHashPartInternal();
|
||||
}
|
||||
else Debug.LogError("Scene " + identity.gameObject.scene.path + " needs to be opened and resaved, because the scene object " + identity.name + " has no valid sceneId yet.");
|
||||
|
||||
|
@ -19,7 +19,7 @@ public static class ClientScene
|
||||
|
||||
public static Dictionary<Guid, GameObject> prefabs = new Dictionary<Guid, GameObject>();
|
||||
// scene id to NetworkIdentity
|
||||
public static Dictionary<uint, NetworkIdentity> spawnableObjects;
|
||||
public static Dictionary<ulong, NetworkIdentity> spawnableObjects;
|
||||
|
||||
// spawn handlers
|
||||
internal static Dictionary<Guid, SpawnDelegate> spawnHandlers = new Dictionary<Guid, SpawnDelegate>();
|
||||
@ -172,7 +172,7 @@ public static void PrepareToSpawnSceneObjects()
|
||||
.ToDictionary(identity => identity.sceneId, identity => identity);
|
||||
}
|
||||
|
||||
internal static NetworkIdentity SpawnSceneObject(uint sceneId)
|
||||
internal static NetworkIdentity SpawnSceneObject(ulong sceneId)
|
||||
{
|
||||
if (spawnableObjects.TryGetValue(sceneId, out NetworkIdentity identity))
|
||||
{
|
||||
@ -441,7 +441,7 @@ internal static void OnSpawnSceneObject(NetworkConnection conn, SpawnSceneObject
|
||||
{
|
||||
Debug.LogError("Spawn scene object not found for " + msg.sceneId + " SpawnableObjects.Count=" + spawnableObjects.Count);
|
||||
// dump the whole spawnable objects dict for easier debugging
|
||||
foreach (KeyValuePair<uint, NetworkIdentity> kvp in spawnableObjects)
|
||||
foreach (KeyValuePair<ulong, NetworkIdentity> kvp in spawnableObjects)
|
||||
Debug.Log("Spawnable: SceneId=" + kvp.Key + " name=" + kvp.Value.name);
|
||||
return;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ public override void Serialize(NetworkWriter writer)
|
||||
class SpawnSceneObjectMessage : MessageBase
|
||||
{
|
||||
public uint netId;
|
||||
public uint sceneId;
|
||||
public ulong sceneId;
|
||||
public Vector3 position;
|
||||
public Quaternion rotation;
|
||||
public byte[] payload;
|
||||
@ -228,7 +228,7 @@ class SpawnSceneObjectMessage : MessageBase
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
netId = reader.ReadPackedUInt32();
|
||||
sceneId = reader.ReadPackedUInt32();
|
||||
sceneId = reader.ReadUInt64();
|
||||
position = reader.ReadVector3();
|
||||
rotation = reader.ReadQuaternion();
|
||||
payload = reader.ReadBytesAndSize();
|
||||
@ -237,7 +237,7 @@ public override void Deserialize(NetworkReader reader)
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
writer.WritePackedUInt32(netId);
|
||||
writer.WritePackedUInt32(sceneId);
|
||||
writer.Write(sceneId);
|
||||
writer.Write(position);
|
||||
writer.Write(rotation);
|
||||
writer.WriteBytesAndSize(payload);
|
||||
|
@ -43,7 +43,7 @@ public bool isServer
|
||||
public Dictionary<int, NetworkConnection> observers;
|
||||
|
||||
public uint netId { get; internal set; }
|
||||
public uint sceneId => m_SceneId;
|
||||
public ulong sceneId => m_SceneId;
|
||||
public bool serverOnly { get { return m_ServerOnly; } set { m_ServerOnly = value; } }
|
||||
public bool localPlayerAuthority { get { return m_LocalPlayerAuthority; } set { m_LocalPlayerAuthority = value; } }
|
||||
public NetworkConnection clientAuthorityOwner { get; internal set; }
|
||||
@ -89,11 +89,12 @@ internal set
|
||||
}
|
||||
}
|
||||
|
||||
// persistent scene id
|
||||
[SerializeField] uint m_SceneId = 0;
|
||||
// persistent scene id <sceneHash/32,sceneId/32>
|
||||
// (see AssignSceneID comments)
|
||||
[SerializeField] ulong m_SceneId = 0;
|
||||
|
||||
// keep track of all sceneIds to detect scene duplicates
|
||||
static Dictionary<uint, NetworkIdentity> sceneIds = new Dictionary<uint, NetworkIdentity>();
|
||||
static Dictionary<ulong, NetworkIdentity> sceneIds = new Dictionary<ulong, NetworkIdentity>();
|
||||
|
||||
// used when adding players
|
||||
internal void SetClientOwner(NetworkConnection conn)
|
||||
@ -261,10 +262,10 @@ void AssignSceneID()
|
||||
// -> we need to call it before changing.
|
||||
Undo.RecordObject(this, "Generated SceneId");
|
||||
|
||||
// generate random sceneId
|
||||
// range: 3 bytes to fill 0x00FFFFFF
|
||||
// generate random sceneId part (0x00000000FFFFFFFF)
|
||||
// -> exclude '0' because that's for unassigned sceneIDs
|
||||
m_SceneId = (uint)UnityEngine.Random.Range(1, 0xFFFFFF);
|
||||
// TODO use 0,uint.max later. Random.Range only has int version.
|
||||
m_SceneId = (uint)UnityEngine.Random.Range(1, int.MaxValue);
|
||||
Debug.Log(name + " in scene=" + gameObject.scene.name + " sceneId assigned to: " + m_SceneId.ToString("X") + (duplicate ? " because duplicated" : ""));
|
||||
}
|
||||
|
||||
@ -274,29 +275,30 @@ void AssignSceneID()
|
||||
sceneIds[m_SceneId] = this;
|
||||
}
|
||||
|
||||
// copy scene build index into sceneId for scene objects.
|
||||
// copy scene path hash into sceneId for scene objects.
|
||||
// this is the only way for scene file duplication to not contain
|
||||
// duplicate sceneIds as it seems.
|
||||
// -> sceneId before: 0x00AABBCCDD
|
||||
// -> then we clear the left most byte, so that our 'OR' uses 0x00
|
||||
// -> then we OR buildIndex into the 0x00 part
|
||||
// -> sceneId before: 0x00000000AABBCCDD
|
||||
// -> then we clear the left 4 bytes, so that our 'OR' uses 0x00000000
|
||||
// -> then we OR the hash into the 0x00000000 part
|
||||
// -> buildIndex is not enough, because Editor and Build have different
|
||||
// build indices if there are disabled scenes in build settings, and
|
||||
// if no scene is in build settings then Editor and Build have
|
||||
// different indices too (Editor=0, Build=-1)
|
||||
// => ONLY USE THIS FROM POSTPROCESSSCENE!
|
||||
public void SetSceneIdSceneIndexByteInternal()
|
||||
public void SetSceneIdSceneHashPartInternal()
|
||||
{
|
||||
// get build index
|
||||
// -> if the scene is not in build settings, then a build would
|
||||
// have buildIndex '-1', but pressing Play in the Editor would
|
||||
// have a buildIndex '0', which would always get sceneIds out of
|
||||
// sync if we didn't add the scene to build settings.
|
||||
// -> let's always use at least '0', which is what unity Editor does
|
||||
// internally as it seems.
|
||||
byte buildIndex = (byte)Mathf.Max(gameObject.scene.buildIndex, 0);
|
||||
// get deterministic scene hash
|
||||
uint pathHash = (uint)gameObject.scene.path.GetStableHashCode();
|
||||
|
||||
// shift hash from 0x000000FFFFFFFF to 0xFFFFFFFF00000000
|
||||
ulong shiftedHash = (ulong)pathHash << 32;
|
||||
|
||||
// OR into scene id
|
||||
m_SceneId = (m_SceneId & 0x00FFFFFF) | (uint)(buildIndex << 24);
|
||||
m_SceneId = (m_SceneId & 0xFFFFFFFF) | shiftedHash;
|
||||
|
||||
// log it. this is incredibly useful to debug sceneId issues.
|
||||
Debug.Log(name + " in scene=" + gameObject.scene.name + " scene index byte(" + buildIndex.ToString("X") + ") copied into sceneId: " + m_SceneId.ToString("X"));
|
||||
Debug.Log(name + " in scene=" + gameObject.scene.name + " scene index hash(" + pathHash.ToString("X") + ") copied into sceneId: " + m_SceneId.ToString("X"));
|
||||
}
|
||||
|
||||
void SetupIDs()
|
||||
|
Loading…
Reference in New Issue
Block a user