mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-17 18:40:33 +00:00
Compare commits
25 Commits
6f2d489ec1
...
29ee1317e4
Author | SHA1 | Date | |
---|---|---|---|
|
29ee1317e4 | ||
|
04bb95311b | ||
|
e9a8e02a40 | ||
|
bb97db4eaa | ||
|
e7b3aa77df | ||
|
f61524863e | ||
|
af133e6110 | ||
|
a9d280cd4b | ||
|
c4f803fcf6 | ||
|
03357f4275 | ||
|
c80a3c8ea5 | ||
|
68c7d14a16 | ||
|
df7a343d7e | ||
|
b0fa0c50b9 | ||
|
d04e0b1f06 | ||
|
d09f5ef008 | ||
|
a14d094bc5 | ||
|
ae9ecf3483 | ||
|
bf49b6c923 | ||
|
477d430a3f | ||
|
12ce588711 | ||
|
ebdd36f6fc | ||
|
5ede69c025 | ||
|
338c0634a5 | ||
|
7e1156a4d6 |
2
.github/workflows/RunUnityTests.yml
vendored
2
.github/workflows/RunUnityTests.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
- 2021.3.45f1
|
||||
- 2022.3.51f1
|
||||
- 2023.2.20f1
|
||||
- 6000.0.24f1
|
||||
- 6000.0.25f1
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
@ -0,0 +1,369 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Mirror;
|
||||
using UnityEngine;
|
||||
|
||||
public class FastSpatialInterestManagement : InterestManagementBase
|
||||
{
|
||||
Vector2Int InvalidPosition => new Vector2Int(int.MaxValue,
|
||||
int.MaxValue);
|
||||
|
||||
|
||||
[Tooltip("The maximum range that objects will be visible at.")]
|
||||
public int visRange = 30;
|
||||
|
||||
[Tooltip("Rebuild all every 'rebuildInterval' seconds.")]
|
||||
public float rebuildInterval = 1;
|
||||
|
||||
double lastRebuildTime;
|
||||
|
||||
// we use a 9 neighbour grid.
|
||||
// so we always see in a distance of 2 grids.
|
||||
// for example, our own grid and then one on top / below / left / right.
|
||||
//
|
||||
// this means that grid resolution needs to be distance / 2.
|
||||
// so for example, for distance = 30 we see 2 cells = 15 * 2 distance.
|
||||
//
|
||||
// on first sight, it seems we need distance / 3 (we see left/us/right).
|
||||
// but that's not the case.
|
||||
// resolution would be 10, and we only see 1 cell far, so 10+10=20.
|
||||
int TileSize => visRange / 2;
|
||||
|
||||
// the grid
|
||||
Dictionary<Vector2Int, HashSet<NetworkIdentity>> grid =
|
||||
new Dictionary<Vector2Int, HashSet<NetworkIdentity>>();
|
||||
|
||||
class Tracked
|
||||
{
|
||||
public Vector2Int Position;
|
||||
public Transform Transform;
|
||||
public NetworkIdentity Identity;
|
||||
public Visibility PreviousVisibility;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Vector2Int GridPosition(int tileSize)
|
||||
{
|
||||
Vector3 transformPos = Transform.position;
|
||||
return Vector2Int.RoundToInt(new Vector2(transformPos.x, transformPos.z) / tileSize);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<NetworkIdentity, Tracked> trackedIdentities = new Dictionary<NetworkIdentity, Tracked>();
|
||||
|
||||
public override void Rebuild(NetworkIdentity identity, bool initialize)
|
||||
{
|
||||
// do nothing, we rebuild globally and individually in OnSpawned
|
||||
}
|
||||
|
||||
public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver)
|
||||
{
|
||||
// do nothing, we rebuild globally and individually in OnSpawned
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void LateUpdate()
|
||||
{
|
||||
// only on server
|
||||
if (!NetworkServer.active) return;
|
||||
|
||||
// rebuild all spawned entities' observers every 'interval'
|
||||
// this will call OnRebuildObservers which then returns the
|
||||
// observers at grid[position] for each entity.
|
||||
if (NetworkTime.localTime >= lastRebuildTime + rebuildInterval)
|
||||
{
|
||||
RebuildAll();
|
||||
lastRebuildTime = NetworkTime.localTime;
|
||||
}
|
||||
}
|
||||
|
||||
// When a new identity is spawned
|
||||
public override void OnSpawned(NetworkIdentity identity)
|
||||
{
|
||||
// host visibility shim to make sure unseen entities are hidden, we initialize actual visibility later
|
||||
if (NetworkClient.active)
|
||||
{
|
||||
SetHostVisibility(identity, false);
|
||||
}
|
||||
|
||||
if (identity.connectionToClient != null)
|
||||
{
|
||||
// client always sees itself
|
||||
AddObserver(identity.connectionToClient, identity);
|
||||
}
|
||||
|
||||
Tracked tracked = new Tracked
|
||||
{
|
||||
Transform = identity.transform, Identity = identity, PreviousVisibility = identity.visibility,
|
||||
};
|
||||
|
||||
// set initial position
|
||||
tracked.Position = tracked.GridPosition(TileSize);
|
||||
// add to tracked
|
||||
trackedIdentities.Add(identity, tracked);
|
||||
// initialize in grid
|
||||
RebuildAdd(identity, InvalidPosition, tracked.Position, true);
|
||||
}
|
||||
|
||||
|
||||
// when an identity is despawned/destroyed
|
||||
public override void OnDestroyed(NetworkIdentity identity)
|
||||
{
|
||||
Tracked obj = trackedIdentities[identity];
|
||||
trackedIdentities.Remove(identity);
|
||||
|
||||
// observers are cleaned up automatically when destroying, we just need to remove it from our grid
|
||||
grid[obj.Position].Remove(identity);
|
||||
}
|
||||
|
||||
private void RebuildAll()
|
||||
{
|
||||
// loop over all identities and check if their position has changed
|
||||
foreach (Tracked tracked in trackedIdentities.Values)
|
||||
{
|
||||
// Check if visibility has changed, this should usually be false
|
||||
bool visibilityChanged = tracked.Identity.visibility != tracked.PreviousVisibility;
|
||||
// Visibility change *to* default needs to be handled before the normal grid update
|
||||
// since observers are manipulated in RebuildAdd/RebuildRemove if visibility == Default
|
||||
if (visibilityChanged && tracked.Identity.visibility == Visibility.Default)
|
||||
{
|
||||
switch (tracked.PreviousVisibility)
|
||||
{
|
||||
case Visibility.ForceHidden:
|
||||
// Hidden To Default
|
||||
AddObserversHiddenToDefault(tracked.Identity, tracked.Position);
|
||||
break;
|
||||
case Visibility.ForceShown:
|
||||
// Shown To Default
|
||||
RemoveObserversShownToDefault(tracked.Identity, tracked.Position);
|
||||
break;
|
||||
case Visibility.Default:
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
Vector2Int currentPosition = tracked.GridPosition(TileSize);
|
||||
// if the position changed, move the identity in the grid and update observers accordingly
|
||||
if (currentPosition != tracked.Position)
|
||||
{
|
||||
Vector2Int oldPosition = tracked.Position;
|
||||
tracked.Position = currentPosition;
|
||||
// First remove from old grid position
|
||||
RebuildRemove(tracked.Identity, oldPosition, currentPosition);
|
||||
// Then add to new grid position
|
||||
RebuildAdd(tracked.Identity, oldPosition, currentPosition, false);
|
||||
}
|
||||
|
||||
// after updating the grid, if the visibility has changed
|
||||
if (visibilityChanged)
|
||||
{
|
||||
switch (tracked.Identity.visibility)
|
||||
{
|
||||
case Visibility.ForceHidden:
|
||||
ClearObservers(tracked.Identity);
|
||||
break;
|
||||
case Visibility.ForceShown:
|
||||
AddObserversAllReady(tracked.Identity);
|
||||
break;
|
||||
case Visibility.Default:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
tracked.PreviousVisibility = tracked.Identity.visibility;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RebuildRemove(NetworkIdentity changedIdentity, Vector2Int oldPosition, Vector2Int newPosition)
|
||||
{
|
||||
// sanity check
|
||||
if (!grid[oldPosition].Remove(changedIdentity))
|
||||
{
|
||||
throw new InvalidOperationException("changedIdentity was not in the provided grid");
|
||||
}
|
||||
|
||||
// for all tiles the changedIdentity could see at the old position
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
Vector2Int tilePos = oldPosition + new Vector2Int(x, y);
|
||||
// Skip grid tiles that are still visible
|
||||
if (Mathf.Abs(tilePos.x - newPosition.x) <= 1 &&
|
||||
Mathf.Abs(tilePos.y - newPosition.y) <= 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!grid.TryGetValue(tilePos, out HashSet<NetworkIdentity> tile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (NetworkIdentity gridIdentity in tile)
|
||||
{
|
||||
if (gridIdentity == changedIdentity)
|
||||
{
|
||||
// Don't do anything with yourself
|
||||
continue;
|
||||
}
|
||||
|
||||
// we only modify observers here if the visibility is default, ForceShown/ForceHidden are handled in RebuildAll
|
||||
|
||||
// if the gridIdentity is a player, it can't see changedIdentity anymore
|
||||
if (gridIdentity.connectionToClient != null && changedIdentity.visibility == Visibility.Default)
|
||||
{
|
||||
RemoveObserver(gridIdentity.connectionToClient, changedIdentity);
|
||||
}
|
||||
|
||||
// if the changedIdentity is a player, it can't see gridIdentity anymore
|
||||
if (changedIdentity.connectionToClient != null && gridIdentity.visibility == Visibility.Default)
|
||||
{
|
||||
RemoveObserver(changedIdentity.connectionToClient, gridIdentity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RebuildAdd(NetworkIdentity changedIdentity, Vector2Int oldPosition, Vector2Int newPosition,
|
||||
bool initialize)
|
||||
{
|
||||
// for all tiles the changedIdentity now sees at the new position
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
Vector2Int tilePos = newPosition + new Vector2Int(x, y);
|
||||
|
||||
// Skip grid tiles that were already visible before moving
|
||||
if (!initialize && (Mathf.Abs(tilePos.x - oldPosition.x) <= 1 &&
|
||||
Mathf.Abs(tilePos.y - oldPosition.y) <= 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!grid.TryGetValue(tilePos, out HashSet<NetworkIdentity> tile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (NetworkIdentity gridIdentity in tile)
|
||||
{
|
||||
if (gridIdentity == changedIdentity)
|
||||
{
|
||||
// Don't do anything with yourself
|
||||
continue;
|
||||
}
|
||||
|
||||
// we only modify observers here if the visibility is default, ForceShown/ForceHidden are handled in RebuildAll
|
||||
|
||||
// if the gridIdentity is a player, it can now see changedIdentity
|
||||
if (gridIdentity.connectionToClient != null && changedIdentity.visibility == Visibility.Default)
|
||||
{
|
||||
AddObserver(gridIdentity.connectionToClient, changedIdentity);
|
||||
}
|
||||
|
||||
// if the changedIdentity is a player, it can now see gridIdentity
|
||||
if (changedIdentity.connectionToClient != null && gridIdentity.visibility == Visibility.Default)
|
||||
{
|
||||
AddObserver(changedIdentity.connectionToClient, gridIdentity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add ourselves to the new grid position
|
||||
if (!grid.TryGetValue(newPosition, out HashSet<NetworkIdentity> addTile))
|
||||
{
|
||||
addTile = new HashSet<NetworkIdentity>();
|
||||
grid[newPosition] = addTile;
|
||||
}
|
||||
|
||||
if (!addTile.Add(changedIdentity))
|
||||
{
|
||||
throw new InvalidOperationException("identity was already in the grid");
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds observers to the NI, but not the other way around. This is used when a NI changes from ForceHidden to Default
|
||||
private void AddObserversHiddenToDefault(NetworkIdentity changed, Vector2Int gridPosition)
|
||||
{
|
||||
// for all tiles around the changedIdentity
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
Vector2Int tilePos = gridPosition + new Vector2Int(x, y);
|
||||
if (!grid.TryGetValue(tilePos, out HashSet<NetworkIdentity> tile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (NetworkIdentity gridIdentity in tile)
|
||||
{
|
||||
if (gridIdentity == changed)
|
||||
{
|
||||
// Don't do anything with yourself
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the gridIdentity is a player, it can now see changedIdentity
|
||||
if (gridIdentity.connectionToClient != null)
|
||||
{
|
||||
AddObserver(gridIdentity.connectionToClient, changed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temp hashset to avoid runtime allocation
|
||||
private HashSet<NetworkConnectionToClient> tempShownToDefaultSet = new HashSet<NetworkConnectionToClient>();
|
||||
|
||||
/// Removes observers from the NI, but doesn't change observing. This is used when a NI changes from ForceShown to Default
|
||||
private void RemoveObserversShownToDefault(NetworkIdentity changedIdentity, Vector2Int gridPosition)
|
||||
{
|
||||
tempShownToDefaultSet.Clear();
|
||||
// copy over all current connections that are seeing the NI
|
||||
foreach (NetworkConnectionToClient observer in changedIdentity.observers.Values)
|
||||
{
|
||||
tempShownToDefaultSet.Add(observer);
|
||||
}
|
||||
|
||||
// for all tiles around the changedIdentity, remove any connections that can still see it
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
Vector2Int tilePos = gridPosition + new Vector2Int(x, y);
|
||||
if (!grid.TryGetValue(tilePos, out HashSet<NetworkIdentity> tile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (NetworkIdentity gridIdentity in tile)
|
||||
{
|
||||
// if the gridIdentity is a player, it can see changedIdentity
|
||||
// (also yourself! don't need the extra check here)
|
||||
if (gridIdentity.connectionToClient != null)
|
||||
{
|
||||
tempShownToDefaultSet.Remove(gridIdentity.connectionToClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// any left over connections can't see changedIdentity - thus need removing
|
||||
foreach (NetworkConnectionToClient connection in tempShownToDefaultSet)
|
||||
{
|
||||
RemoveObserver(connection, changedIdentity);
|
||||
}
|
||||
|
||||
// clear when done
|
||||
tempShownToDefaultSet.Clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86996600b40a4c41bb300ac0aed33189
|
||||
timeCreated: 1676129828
|
@ -1,6 +1,7 @@
|
||||
// interest management component for custom solutions like
|
||||
// distance based, spatial hashing, raycast based, etc.
|
||||
// low level base class allows for low level spatial hashing etc., which is 3-5x faster.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
@ -73,5 +74,39 @@ protected void RemoveObserver(NetworkConnectionToClient connection, NetworkIdent
|
||||
connection.RemoveFromObserving(identity, false);
|
||||
identity.observers.Remove(connection.connectionId);
|
||||
}
|
||||
|
||||
/// For ForceShown: Makes sure all ready connections (that aren't already) are added to observers
|
||||
protected void AddObserversAllReady(NetworkIdentity identity)
|
||||
{
|
||||
foreach (NetworkConnectionToClient connection in NetworkServer.connections.Values)
|
||||
{
|
||||
if (connection.isReady && !identity.observers.ContainsKey(connection.connectionId))
|
||||
{
|
||||
connection.AddToObserving(identity);
|
||||
identity.observers.Add(connection.connectionId, connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For ForceHidden: Removes all observers from this identity
|
||||
protected void ClearObservers(NetworkIdentity identity)
|
||||
{
|
||||
foreach (NetworkConnectionToClient connection in identity.observers.Values)
|
||||
{
|
||||
// Don't remove the client from observing its owned objects
|
||||
if (connection != identity.connectionToClient)
|
||||
{
|
||||
connection.RemoveFromObserving(identity, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear..
|
||||
identity.observers.Clear();
|
||||
// If the object is owned by a client, add it's connection back to the observing set
|
||||
if (identity.connectionToClient != null)
|
||||
{
|
||||
identity.observers.Add(identity.connectionToClient.connectionId, identity.connectionToClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -671,7 +671,24 @@ void OnDestroy()
|
||||
|
||||
// if an identity is still in .spawned, remove it too.
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/3324
|
||||
NetworkClient.spawned.Remove(netId);
|
||||
//
|
||||
// however, verify that spawned[netId] is this NetworkIdentity
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/3785
|
||||
// - server: netId=42 walks out of and back into AOI range in same frame
|
||||
// - client frame 1:
|
||||
// on_destroymsg(42) -> NetworkClient.DestroyObject -> GameObject.Destroy(42) // next frame
|
||||
// on_spawnmsg(42) -> NetworkClient.SpawnPrefab -> Instantiate(42) -> spawned[42]=new_identity
|
||||
// - client frame 2:
|
||||
// Unity destroys the old 42
|
||||
// NetworkIdentity.OnDestroy removes .spawned[42] which is new_identity not old_identity
|
||||
// new_identity becomes orphaned
|
||||
//
|
||||
// solution: only remove if spawned[netId] is this NetworkIdentity or null
|
||||
if (NetworkClient.spawned.TryGetValue(netId, out NetworkIdentity entry))
|
||||
{
|
||||
if (entry == this || entry == null)
|
||||
NetworkClient.spawned.Remove(netId);
|
||||
}
|
||||
}
|
||||
|
||||
// workaround for cyclid NI<->NB reference causing memory leaks
|
||||
|
@ -634,31 +634,6 @@ public void StopClient()
|
||||
NetworkClient.Disconnect();
|
||||
}
|
||||
|
||||
// called when quitting the application by closing the window / pressing
|
||||
// stop in the editor. virtual so that inheriting classes'
|
||||
// OnApplicationQuit() can call base.OnApplicationQuit() too
|
||||
public virtual void OnApplicationQuit()
|
||||
{
|
||||
// stop client first
|
||||
// (we want to send the quit packet to the server instead of waiting
|
||||
// for a timeout)
|
||||
if (NetworkClient.isConnected)
|
||||
{
|
||||
StopClient();
|
||||
//Debug.Log("OnApplicationQuit: stopped client");
|
||||
}
|
||||
|
||||
// stop server after stopping client (for proper host mode stopping)
|
||||
if (NetworkServer.active)
|
||||
{
|
||||
StopServer();
|
||||
//Debug.Log("OnApplicationQuit: stopped server");
|
||||
}
|
||||
|
||||
// Call ResetStatics to reset statics and singleton
|
||||
ResetStatics();
|
||||
}
|
||||
|
||||
/// <summary>Set the frame rate for a headless builds. Override to disable or modify.</summary>
|
||||
// useful for dedicated servers.
|
||||
// useful for headless benchmark clients.
|
||||
@ -772,12 +747,41 @@ public static void ResetStatics()
|
||||
singleton = null;
|
||||
}
|
||||
|
||||
// virtual so that inheriting classes' OnDestroy() can call base.OnDestroy() too
|
||||
// called when quitting the application by closing the window / pressing
|
||||
// stop in the editor.
|
||||
// use OnDestroy instead of OnApplicationQuit:
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2802
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
//Debug.Log("NetworkManager destroyed");
|
||||
|
||||
// stop client first
|
||||
// (we want to send the quit packet to the server instead of waiting
|
||||
// for a timeout)
|
||||
if (NetworkClient.isConnected)
|
||||
{
|
||||
StopClient();
|
||||
//Debug.Log("OnApplicationQuit: stopped client");
|
||||
}
|
||||
|
||||
// stop server after stopping client (for proper host mode stopping)
|
||||
if (NetworkServer.active)
|
||||
{
|
||||
StopServer();
|
||||
//Debug.Log("OnApplicationQuit: stopped server");
|
||||
}
|
||||
|
||||
// Call ResetStatics to reset statics and singleton
|
||||
ResetStatics();
|
||||
}
|
||||
|
||||
// [Obsolete] in case someone is inheriting it.
|
||||
// don't use this anymore.
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2802
|
||||
// DEPRECATED 2024-10-29
|
||||
[Obsolete("Override OnDestroy instead of OnApplicationQuit.")]
|
||||
public virtual void OnApplicationQuit() {}
|
||||
|
||||
/// <summary>The name of the current network scene.</summary>
|
||||
// set by NetworkManager when changing the scene.
|
||||
// new clients will automatically load this scene.
|
||||
|
@ -313,8 +313,6 @@ public static List<T> ReadList<T>(this NetworkReader reader)
|
||||
// structs may have .Set<T> members which weaver needs to be able to
|
||||
// fully serialize for NetworkMessages etc.
|
||||
// note that Weaver/Readers/GenerateReader() handles this manually.
|
||||
// TODO writer not found. need to adjust weaver first. see tests.
|
||||
/*
|
||||
public static HashSet<T> ReadHashSet<T>(this NetworkReader reader)
|
||||
{
|
||||
// we offset count by '1' to easily support null without writing another byte.
|
||||
@ -334,7 +332,6 @@ public static HashSet<T> ReadHashSet<T>(this NetworkReader reader)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
public static T[] ReadArray<T>(this NetworkReader reader)
|
||||
{
|
||||
|
@ -365,28 +365,25 @@ public static void WriteList<T>(this NetworkWriter writer, List<T> list)
|
||||
// structs may have .Set<T> members which weaver needs to be able to
|
||||
// fully serialize for NetworkMessages etc.
|
||||
// note that Weaver/Writers/GenerateWriter() handles this manually.
|
||||
// TODO writer not found. need to adjust weaver first. see tests.
|
||||
// /*
|
||||
// public static void WriteHashSet<T>(this NetworkWriter writer, HashSet<T> hashSet)
|
||||
// {
|
||||
// // we offset count by '1' to easily support null without writing another byte.
|
||||
// // encoding null as '0' instead of '-1' also allows for better compression
|
||||
// // (ushort vs. short / varuint vs. varint) etc.
|
||||
// if (hashSet is null)
|
||||
// {
|
||||
// // most sizes are small, write size as VarUInt!
|
||||
// Compression.CompressVarUInt(writer, 0u);
|
||||
// //writer.WriteUInt(0);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // most sizes are small, write size as VarUInt!
|
||||
// Compression.CompressVarUInt(writer, checked((uint)hashSet.Count) + 1u);
|
||||
// //writer.WriteUInt(checked((uint)hashSet.Count) + 1u);
|
||||
// foreach (T item in hashSet)
|
||||
// writer.Write(item);
|
||||
// }
|
||||
// */
|
||||
public static void WriteHashSet<T>(this NetworkWriter writer, HashSet<T> hashSet)
|
||||
{
|
||||
// we offset count by '1' to easily support null without writing another byte.
|
||||
// encoding null as '0' instead of '-1' also allows for better compression
|
||||
// (ushort vs. short / varuint vs. varint) etc.
|
||||
if (hashSet is null)
|
||||
{
|
||||
// most sizes are small, write size as VarUInt!
|
||||
Compression.CompressVarUInt(writer, 0u);
|
||||
//writer.WriteUInt(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// most sizes are small, write size as VarUInt!
|
||||
Compression.CompressVarUInt(writer, checked((uint)hashSet.Count) + 1u);
|
||||
//writer.WriteUInt(checked((uint)hashSet.Count) + 1u);
|
||||
foreach (T item in hashSet)
|
||||
writer.Write(item);
|
||||
}
|
||||
|
||||
public static void WriteArray<T>(this NetworkWriter writer, T[] array)
|
||||
{
|
||||
|
@ -114,6 +114,18 @@ public static void SetPositionAndRotation(this Transform transform, Vector3 posi
|
||||
transform.position = position;
|
||||
transform.rotation = rotation;
|
||||
}
|
||||
|
||||
public static void GetLocalPositionAndRotation(this Transform transform, out Vector3 position, out Quaternion rotation)
|
||||
{
|
||||
position = transform.localPosition;
|
||||
rotation = transform.localRotation;
|
||||
}
|
||||
|
||||
public static void SetLocalPositionAndRotation(this Transform transform, Vector3 position, Quaternion rotation)
|
||||
{
|
||||
transform.localPosition = position;
|
||||
transform.localRotation = rotation;
|
||||
}
|
||||
#endif
|
||||
|
||||
// IPEndPoint address only to pretty string.
|
||||
|
@ -196,8 +196,15 @@ public virtual void ServerLateUpdate() {}
|
||||
/// <summary>Shut down the transport, both as client and server</summary>
|
||||
public abstract void Shutdown();
|
||||
|
||||
/// <summary>Called by Unity when quitting. Inheriting Transports should call base for proper Shutdown.</summary>
|
||||
public virtual void OnApplicationQuit()
|
||||
// [Obsolete] in case someone is inheriting it.
|
||||
// don't use this anymore.
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2802
|
||||
// DEPRECATED 2024-10-29
|
||||
[Obsolete("Override OnDestroy instead of OnApplicationQuit.")]
|
||||
public virtual void OnApplicationQuit() {}
|
||||
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2802
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
// stop transport (e.g. to shut down threads)
|
||||
// (when pressing Stop in the Editor, Unity keeps threads alive
|
||||
|
@ -55,19 +55,28 @@ public static void OnPostProcessScene()
|
||||
else
|
||||
{
|
||||
// there are two cases where sceneId == 0:
|
||||
// * if we have a prefab open in the prefab scene
|
||||
// * if an unopened scene needs resaving
|
||||
// show a proper error message in both cases so the user
|
||||
// knows what to do.
|
||||
// if we have a prefab open in the prefab scene
|
||||
string path = identity.gameObject.scene.path;
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
// pressing play while in prefab edit mode used to freeze/crash Unity 2019.
|
||||
// this seems fine now so we don't need to stop the editor anymore.
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
Debug.LogWarning($"{identity.name} was open in Prefab Edit Mode while launching with Mirror. If this causes issues, please let us know.");
|
||||
#else
|
||||
Debug.LogError($"{identity.name} is currently open in Prefab Edit Mode. Please open the actual scene before launching Mirror.");
|
||||
EditorApplication.isPlaying = false;
|
||||
#endif
|
||||
}
|
||||
// if an unopened scene needs resaving
|
||||
else
|
||||
Debug.LogError($"Scene {path} needs to be opened and resaved, because the scene object {identity.name} has no valid sceneId yet.");
|
||||
{
|
||||
|
||||
// either way we shouldn't continue. nothing good will
|
||||
// happen when trying to launch with invalid sceneIds.
|
||||
EditorApplication.isPlaying = false;
|
||||
// nothing good will happen when trying to launch with invalid sceneIds.
|
||||
// show an error and stop playing immediately.
|
||||
Debug.LogError($"Scene {path} needs to be opened and resaved, because the scene object {identity.name} has no valid sceneId yet.");
|
||||
EditorApplication.isPlaying = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,13 @@ MethodReference GenerateReader(TypeReference variableReference, ref bool Weaving
|
||||
|
||||
return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadList), ref WeavingFailed);
|
||||
}
|
||||
else if (variableDefinition.Is(typeof(HashSet<>)))
|
||||
{
|
||||
GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
|
||||
TypeReference elementType = genericInstance.GenericArguments[0];
|
||||
|
||||
return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadHashSet), ref WeavingFailed);
|
||||
}
|
||||
// handle both NetworkBehaviour and inheritors.
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
|
||||
else if (variableReference.IsDerivedFrom<NetworkBehaviour>() || variableReference.Is<NetworkBehaviour>())
|
||||
|
@ -126,6 +126,13 @@ MethodReference GenerateWriter(TypeReference variableReference, ref bool Weaving
|
||||
|
||||
return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteList), ref WeavingFailed);
|
||||
}
|
||||
if (variableReference.Is(typeof(HashSet<>)))
|
||||
{
|
||||
GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
|
||||
TypeReference elementType = genericInstance.GenericArguments[0];
|
||||
|
||||
return GenerateCollectionWriter(variableReference, elementType, nameof(NetworkWriterExtensions.WriteHashSet), ref WeavingFailed);
|
||||
}
|
||||
|
||||
// handle both NetworkBehaviour and inheritors.
|
||||
// fixes: https://github.com/MirrorNetworking/Mirror/issues/2939
|
||||
|
@ -62,15 +62,6 @@ public override void LateUpdate()
|
||||
base.LateUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs on both Server and Client
|
||||
/// </summary>
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
//UnityEngine.Debug.Log("OnDestroy");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Start & Stop
|
||||
@ -87,10 +78,10 @@ public override void ConfigureHeadlessFrameRate()
|
||||
/// <summary>
|
||||
/// called when quitting the application by closing the window / pressing stop in the editor
|
||||
/// </summary>
|
||||
public override void OnApplicationQuit()
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnApplicationQuit();
|
||||
//UnityEngine.Debug.Log("OnApplicationQuit");
|
||||
base.OnDestroy();
|
||||
//UnityEngine.Debug.Log("OnDestroy");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -148,5 +148,5 @@ MonoBehaviour:
|
||||
syncMode: 0
|
||||
syncInterval: 0.1
|
||||
speed: 1
|
||||
movementProbability: 0.5
|
||||
movementProbability: 0.1
|
||||
movementDistance: 20
|
||||
|
@ -5,7 +5,13 @@ namespace Mirror.Examples.Benchmark
|
||||
public class MonsterMovement : NetworkBehaviour
|
||||
{
|
||||
public float speed = 1;
|
||||
public float movementProbability = 0.5f;
|
||||
|
||||
// movement probability:
|
||||
// 0.5 is too high, monsters are moving almost all the time.
|
||||
// only-sync-on-change shows no difference with 0.5 at all.
|
||||
// in other words: broken change detection would be too easy to miss!
|
||||
[Header("Note: use 0.1 to test change detection, 0.5 is too high!")]
|
||||
public float movementProbability = 0.1f;
|
||||
public float movementDistance = 20;
|
||||
|
||||
bool moving;
|
||||
|
@ -1,5 +1,111 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2505838817581327622
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8070823805368028938}
|
||||
- component: {fileID: 9066655185906928051}
|
||||
- component: {fileID: 4760233786622638652}
|
||||
- component: {fileID: 2239866139065920034}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8070823805368028938
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2505838817581327622}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1.4999999, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5650773562400175449}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &9066655185906928051
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2505838817581327622}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &4760233786622638652
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2505838817581327622}
|
||||
m_Text: RB Reliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967040
|
||||
--- !u!114 &2239866139065920034
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2505838817581327622}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &3564599214188516024
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -194,6 +300,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 4320229852458648655}
|
||||
- {fileID: 8070823805368028938}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -1,5 +1,111 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1900176203039934355
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4129545300081926521}
|
||||
- component: {fileID: 6572775962608386051}
|
||||
- component: {fileID: 3912971638250293984}
|
||||
- component: {fileID: 4630973873820678624}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4129545300081926521
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1900176203039934355}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1.4999999, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6814142693731383418}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &6572775962608386051
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1900176203039934355}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &3912971638250293984
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1900176203039934355}
|
||||
m_Text: RB Unreliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4278255615
|
||||
--- !u!114 &4630973873820678624
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1900176203039934355}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &2414815785185615771
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -194,6 +300,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 3102887894851733868}
|
||||
- {fileID: 4129545300081926521}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -79,6 +79,112 @@ MeshRenderer:
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!1 &5366675989284536270
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1545974004720046327}
|
||||
- component: {fileID: 1128890847761595466}
|
||||
- component: {fileID: 396193860522376263}
|
||||
- component: {fileID: 6075803386746488465}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1545974004720046327
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5366675989284536270}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1.5, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &1128890847761595466
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5366675989284536270}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &396193860522376263
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5366675989284536270}
|
||||
m_Text: Reliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967040
|
||||
--- !u!114 &6075803386746488465
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5366675989284536270}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &5844787331012650587
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -195,6 +301,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 3834521907656645861}
|
||||
- {fileID: 1545974004720046327}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -71,14 +71,6 @@ public override void ConfigureHeadlessFrameRate()
|
||||
base.ConfigureHeadlessFrameRate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called when quitting the application by closing the window / pressing stop in the editor
|
||||
/// </summary>
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
base.OnApplicationQuit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scene Management
|
||||
|
@ -159,6 +159,112 @@ MeshRenderer:
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!1 &7554601580530514207
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8679949096303753939}
|
||||
- component: {fileID: 3142866354055383265}
|
||||
- component: {fileID: 8297296856940116434}
|
||||
- component: {fileID: 1123801447343694564}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8679949096303753939
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7554601580530514207}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1.4999999, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &3142866354055383265
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7554601580530514207}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &8297296856940116434
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7554601580530514207}
|
||||
m_Text: Unreliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4278255615
|
||||
--- !u!114 &1123801447343694564
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7554601580530514207}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &7863680369626900553
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -195,6 +301,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 3834521907656645861}
|
||||
- {fileID: 8679949096303753939}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -38,6 +38,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 702109291309605218}
|
||||
- {fileID: 1245118046271587945}
|
||||
- {fileID: 8174595063106582951}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
@ -197,7 +198,6 @@ MonoBehaviour:
|
||||
maxTurnSpeed: 100
|
||||
turnAcceleration: 3
|
||||
runtimeData:
|
||||
_horizontal: 0
|
||||
_vertical: 0
|
||||
_turnSpeed: 0
|
||||
_animVelocity: 0
|
||||
@ -328,6 +328,112 @@ MonoBehaviour:
|
||||
rotationSensitivity: 0.01
|
||||
positionPrecision: 0.01
|
||||
scalePrecision: 0.01
|
||||
--- !u!1 &8370326626297540303
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1245118046271587945}
|
||||
- component: {fileID: 2132579043257509693}
|
||||
- component: {fileID: 7297775110981071875}
|
||||
- component: {fileID: 755026988438523126}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1245118046271587945
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8370326626297540303}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 4.5, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &2132579043257509693
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8370326626297540303}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &7297775110981071875
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8370326626297540303}
|
||||
m_Text: Reliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967040
|
||||
--- !u!114 &755026988438523126
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8370326626297540303}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &9109672380512621037
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -359,7 +465,7 @@ Transform:
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &4153780752967283830
|
||||
MeshRenderer:
|
||||
@ -446,6 +552,11 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: BasePrefab
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3638700596990361445, guid: dad07e68d3659e6439279d0d4110cf4c,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3638700596990361445, guid: dad07e68d3659e6439279d0d4110cf4c,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
|
@ -38,6 +38,7 @@ Transform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 702109291309605218}
|
||||
- {fileID: 3980373565918037634}
|
||||
- {fileID: 8174595063106582951}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
@ -197,7 +198,6 @@ MonoBehaviour:
|
||||
maxTurnSpeed: 100
|
||||
turnAcceleration: 3
|
||||
runtimeData:
|
||||
_horizontal: 0
|
||||
_vertical: 0
|
||||
_turnSpeed: 0
|
||||
_animVelocity: 0
|
||||
@ -328,6 +328,112 @@ MonoBehaviour:
|
||||
positionSensitivity: 0.01
|
||||
rotationSensitivity: 0.01
|
||||
scaleSensitivity: 0.01
|
||||
--- !u!1 &8921157218750951074
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3980373565918037634}
|
||||
- component: {fileID: 6676747655999921495}
|
||||
- component: {fileID: 2065557788844610204}
|
||||
- component: {fileID: 7150452883383585942}
|
||||
m_Layer: 0
|
||||
m_Name: PlayerName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3980373565918037634
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8921157218750951074}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 4.5, z: 0}
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &6676747655999921495
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8921157218750951074}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!102 &2065557788844610204
|
||||
TextMesh:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8921157218750951074}
|
||||
m_Text: Unreliable
|
||||
m_OffsetZ: 0
|
||||
m_CharacterSize: 0.5
|
||||
m_LineSpacing: 1
|
||||
m_Anchor: 4
|
||||
m_Alignment: 1
|
||||
m_TabSize: 4
|
||||
m_FontSize: 100
|
||||
m_FontStyle: 0
|
||||
m_RichText: 1
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Color:
|
||||
serializedVersion: 2
|
||||
rgba: 4278255615
|
||||
--- !u!114 &7150452883383585942
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8921157218750951074}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: afa2d590c474413d9fc183551385ed85, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &9109672380512621037
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -359,7 +465,7 @@ Transform:
|
||||
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4659514702152478195}
|
||||
m_RootOrder: 1
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!23 &4153780752967283830
|
||||
MeshRenderer:
|
||||
@ -446,6 +552,11 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: BasePrefab
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3638700596990361445, guid: dad07e68d3659e6439279d0d4110cf4c,
|
||||
type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3638700596990361445, guid: dad07e68d3659e6439279d0d4110cf4c,
|
||||
type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
|
@ -8,7 +8,7 @@ Material:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Robot_Color
|
||||
m_Shader: {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Shader: {fileID: 2, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 1
|
||||
m_EnableInstancingVariants: 0
|
||||
@ -24,7 +24,7 @@ Material:
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 2800000, guid: a1454d7237641fa49a7f66d6bee624ad, type: 3}
|
||||
m_Texture: {fileID: 2800000, guid: 7bf5087089ac3424a982003c10dda35f, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
@ -32,7 +32,7 @@ Material:
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 1fbb41709a1d9334696860db720026e5, type: 3}
|
||||
m_Texture: {fileID: 2800000, guid: fa652271323864a648c14b00ef5c677b, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _SpecGlossMap:
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 482 KiB |
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa652271323864a648c14b00ef5c677b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 MiB |
@ -1,45 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fbb41709a1d9334696860db720026e5
|
||||
TextureImporter:
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
Binary file not shown.
After Width: | Height: | Size: 431 KiB |
@ -0,0 +1,104 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bf5087089ac3424a982003c10dda35f
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 1
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 1024
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 MiB |
@ -1,45 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1454d7237641fa49a7f66d6bee624ad
|
||||
TextureImporter:
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 1
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 1
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 1024
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -1
|
||||
wrapMode: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: 1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
@ -19,11 +19,6 @@ void Awake()
|
||||
mainCam = Camera.main;
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
//Debug.Log("PlayerCamera.OnDisable");
|
||||
}
|
||||
|
||||
public override void OnStartLocalPlayer()
|
||||
{
|
||||
if (mainCam != null)
|
||||
@ -38,16 +33,46 @@ public override void OnStartLocalPlayer()
|
||||
Debug.LogWarning("PlayerCamera: Could not find a camera in scene with 'MainCamera' tag.");
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
//Debug.Log("PlayerCamera.OnApplicationQuit");
|
||||
ReleaseCamera();
|
||||
}
|
||||
|
||||
public override void OnStopLocalPlayer()
|
||||
{
|
||||
//Debug.Log("PlayerCamera.OnStopLocalPlayer");
|
||||
ReleaseCamera();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
//Debug.Log("PlayerCamera.OnDisable");
|
||||
ReleaseCamera();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
//Debug.Log("PlayerCamera.OnDestroy");
|
||||
ReleaseCamera();
|
||||
}
|
||||
|
||||
void ReleaseCamera()
|
||||
{
|
||||
if (mainCam != null && mainCam.transform.parent == transform)
|
||||
{
|
||||
//Debug.Log("PlayerCamera.ReleaseCamera");
|
||||
|
||||
mainCam.transform.SetParent(null);
|
||||
SceneManager.MoveGameObjectToScene(mainCam.gameObject, SceneManager.GetActiveScene());
|
||||
mainCam.orthographic = true;
|
||||
mainCam.orthographicSize = 15f;
|
||||
mainCam.transform.localPosition = new Vector3(0f, 70f, 0f);
|
||||
mainCam.transform.localEulerAngles = new Vector3(90f, 0f, 0f);
|
||||
|
||||
if (mainCam.gameObject.scene != SceneManager.GetActiveScene())
|
||||
SceneManager.MoveGameObjectToScene(mainCam.gameObject, SceneManager.GetActiveScene());
|
||||
|
||||
mainCam = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,223 @@
|
||||
// TODO: test despawning
|
||||
// TODO: test non-player ni's
|
||||
// TODO: test grid size changing at runtime
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror.Tests.InterestManagement
|
||||
{
|
||||
public class InterestManagementTests_FastSpatialHashing : MirrorEditModeTest
|
||||
{
|
||||
FastSpatialInterestManagement aoi;
|
||||
|
||||
protected NetworkIdentity CreateNI(Action<NetworkIdentity> prespawn = null)
|
||||
{
|
||||
CreateNetworked(out var gameObject, out var identity);
|
||||
prespawn?.Invoke(identity);
|
||||
NetworkServer.Spawn(gameObject);
|
||||
return identity;
|
||||
}
|
||||
|
||||
protected NetworkIdentity CreatePlayerNI(int connectionId, Action<NetworkIdentity> prespawn = null)
|
||||
{
|
||||
CreateNetworked(out var gameObject, out var identity);
|
||||
prespawn?.Invoke(identity);
|
||||
NetworkConnectionToClient connection = new NetworkConnectionToClient(connectionId);
|
||||
connection.isAuthenticated = true;
|
||||
connection.identity = identity;
|
||||
NetworkServer.connections.Add(connectionId, connection);
|
||||
|
||||
NetworkServer.Spawn(gameObject, connection);
|
||||
NetworkServer.SetClientReady(connection); // AddPlayerForConnection also calls this!
|
||||
return identity;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
// need to start server so that interest management works
|
||||
NetworkServer.Listen(10);
|
||||
|
||||
aoi = holder.AddComponent<FastSpatialInterestManagement>();
|
||||
aoi.visRange = 10;
|
||||
aoi.rebuildInterval = -1; // rebuild every call :)
|
||||
// setup server aoi since InterestManagement Awake isn't called
|
||||
NetworkServer.aoi = aoi;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
foreach (GameObject go in instantiated)
|
||||
{
|
||||
if (go.TryGetComponent(out NetworkIdentity ni))
|
||||
{
|
||||
// set isServer is false. otherwise Destroy instead of
|
||||
// DestroyImmediate is called internally, giving an error in Editor
|
||||
ni.isServer = false;
|
||||
}
|
||||
}
|
||||
|
||||
// clear connections first. calling OnDisconnect wouldn't work since
|
||||
// we have no real clients.
|
||||
NetworkServer.connections.Clear();
|
||||
|
||||
base.TearDown();
|
||||
// clear server aoi again
|
||||
NetworkServer.aoi = null;
|
||||
}
|
||||
|
||||
private void AssertSelfVisible(NetworkIdentity id)
|
||||
{
|
||||
// identities ALWAYS see themselves, if they have a player
|
||||
if (id.connectionToClient != null)
|
||||
{
|
||||
Assert.That(id.observers.ContainsKey(id.connectionToClient.connectionId), Is.True);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ForceHidden()
|
||||
{
|
||||
// A and B are at (0,0,0) so within range!
|
||||
var a = CreatePlayerNI(1, ni => ni.visibility = Visibility.ForceHidden);
|
||||
var b = CreatePlayerNI(2);
|
||||
|
||||
// no rebuild required here due to initial state :)
|
||||
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// A should not be seen by B because A is force hidden
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
// B should be seen by A
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
|
||||
// If we now set a to default, and rebuild, they should both see each other!
|
||||
a.visibility = Visibility.Default;
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
// If we now set both hidden, and rebuild, they both won't see each other!
|
||||
a.visibility = Visibility.ForceHidden;
|
||||
b.visibility = Visibility.ForceHidden;
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ForceShown()
|
||||
{
|
||||
// A and B are at (0,0,0) so within range!
|
||||
var a = CreatePlayerNI(1, ni => ni.visibility = Visibility.ForceShown);
|
||||
var b = CreatePlayerNI(2);
|
||||
|
||||
// no rebuild required here due to initial state :)
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// A&B should see each other
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
aoi.LateUpdate();
|
||||
// rebuild doesnt change that
|
||||
// no rebuild required here due to initial state :)
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// A&B should see each other
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
|
||||
// If we now move A out of range of B
|
||||
a.transform.position = new Vector3(aoi.visRange * 100, 0, 0);
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
|
||||
// a will be seen by B still
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
// But B is out of range of A
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
|
||||
|
||||
// B to ForceShown:
|
||||
b.visibility = Visibility.ForceShown;
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// A&B should see each other
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
// A&B to default
|
||||
a.visibility = Visibility.Default;
|
||||
b.visibility = Visibility.Default;
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// and they can't see each other anymore
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InRangeInitial_To_OutRange()
|
||||
{
|
||||
// A and B are at (0,0,0) so within range!
|
||||
var a = CreatePlayerNI(1);
|
||||
var b = CreatePlayerNI(2);
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// both should see each other because they are in range
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
// update won't change that
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
// move out of range
|
||||
a.transform.position = new Vector3(aoi.visRange * 100, 0, 0);
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// and they'll see not each other anymore
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OutRangeInitial_To_InRange()
|
||||
{
|
||||
// A and B are not in range
|
||||
var a = CreatePlayerNI(1,
|
||||
ni => ni.transform.position = new Vector3(aoi.visRange * 100, 0, 0));
|
||||
var b = CreatePlayerNI(2);
|
||||
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// both should not see each other because they aren't in range
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// update won't change that
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.False);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.False);
|
||||
// move into range
|
||||
a.transform.position = Vector3.zero;
|
||||
aoi.LateUpdate();
|
||||
AssertSelfVisible(a);
|
||||
AssertSelfVisible(b);
|
||||
// and they'll see each other
|
||||
Assert.That(a.observers.ContainsKey(b.connectionToClient.connectionId), Is.True);
|
||||
Assert.That(b.observers.ContainsKey(a.connectionToClient.connectionId), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d74fcd64861c40f8856d3479137f49f2
|
||||
timeCreated: 1676129959
|
@ -1341,7 +1341,15 @@ public void TestNullList()
|
||||
Assert.That(readList, Is.Null);
|
||||
}
|
||||
|
||||
[Test, Ignore("TODO")]
|
||||
// writer.Write<T> for HashSet only works if it's actually used by weaver somewhere.
|
||||
// so for TestHashSet() to pass, we need to pretend using a HashSet<int> somewhere.
|
||||
class HashSetNetworkBehaviour : NetworkBehaviour
|
||||
{
|
||||
[Command]
|
||||
public void CmdHashSet(HashSet<int> hashSet) {}
|
||||
}
|
||||
|
||||
[Test] // requires HashSetNetworkBehaviour to exits!
|
||||
public void TestHashSet()
|
||||
{
|
||||
HashSet<int> original = new HashSet<int>() { 1, 2, 3, 4, 5 };
|
||||
@ -1353,7 +1361,7 @@ public void TestHashSet()
|
||||
Assert.That(readHashSet, Is.EqualTo(original));
|
||||
}
|
||||
|
||||
[Test, Ignore("TODO")]
|
||||
[Test] // requires HashSetNetworkBehaviour to exits!
|
||||
public void TestNullHashSet()
|
||||
{
|
||||
NetworkWriter writer = new NetworkWriter();
|
||||
|
@ -323,7 +323,7 @@ public void SetServerLobbyParams(LobbyCreateRequest request)
|
||||
_request = request;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// attempt to clean up lobbies, if active
|
||||
if (NetworkServer.active)
|
||||
@ -340,6 +340,8 @@ private void OnDestroy()
|
||||
// sorry. this can go once the lobby service can timeout lobbies itself
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ protected virtual void Awake()
|
||||
() => OnClientConnected.Invoke(),
|
||||
(message, channel) => OnClientDataReceived.Invoke(message, FromKcpChannel(channel)),
|
||||
() => OnClientDisconnected?.Invoke(), // may be null in StopHost(): https://github.com/MirrorNetworking/Mirror/issues/3708
|
||||
(error, reason) => OnClientError.Invoke(ToTransportError(error), reason),
|
||||
(error, reason) => OnClientError?.Invoke(ToTransportError(error), reason), // may be null during shutdown: https://github.com/MirrorNetworking/Mirror/issues/3876
|
||||
config
|
||||
);
|
||||
|
||||
|
@ -197,11 +197,10 @@ void EnsureThread()
|
||||
Debug.Log($"ThreadedTransport: started worker thread!");
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
public override void OnDestroy()
|
||||
{
|
||||
// stop thread fully
|
||||
Shutdown();
|
||||
|
||||
base.OnDestroy();
|
||||
// TODO recycle writers.
|
||||
}
|
||||
|
||||
|
@ -68,14 +68,6 @@ public class #SCRIPTNAME# : NetworkManager
|
||||
base.ConfigureHeadlessFrameRate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called when quitting the application by closing the window / pressing stop in the editor
|
||||
/// </summary>
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
base.OnApplicationQuit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scene Management
|
||||
|
@ -15,8 +15,6 @@ public class #SCRIPTNAME# : NetworkManager
|
||||
public event Action OnStartAction;
|
||||
public event Action OnDestroyAction;
|
||||
|
||||
public event Action OnApplicationQuitAction;
|
||||
|
||||
public event Action<string> ServerChangeSceneAction;
|
||||
public event Action<string> OnServerChangeSceneAction;
|
||||
public event Action<string> OnServerSceneChangedAction;
|
||||
@ -117,15 +115,6 @@ public class #SCRIPTNAME# : NetworkManager
|
||||
base.ConfigureHeadlessFrameRate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called when quitting the application by closing the window / pressing stop in the editor
|
||||
/// </summary>
|
||||
public override void OnApplicationQuit()
|
||||
{
|
||||
OnApplicationQuitAction?.Invoke();
|
||||
base.OnApplicationQuit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scene Management
|
||||
|
Loading…
Reference in New Issue
Block a user