Skip to content

Instantly share code, notes, and snippets.

@abdelfattahradwan
Created January 13, 2023 13:42
Show Gist options
  • Save abdelfattahradwan/67182bf41fc5d233fe167100635c1502 to your computer and use it in GitHub Desktop.
Save abdelfattahradwan/67182bf41fc5d233fe167100635c1502 to your computer and use it in GitHub Desktop.
An editor tool that allows you inspect the contents of Fish-Networking's sync collections. (https://ko-fi.com/winterboltgames)
using FishNet.Object;
using System.Collections.Generic;
using System.Reflection;
using System;
using UnityEditor;
using UnityEngine;
using System.Collections;
using System.Linq;
using FishNet.Object.Synchronizing;
internal sealed class SyncCollectionViewer : EditorWindow
{
private Vector2 _scroll = Vector2.zero;
private NetworkBehaviour[] _networkBehaviours = Array.Empty<NetworkBehaviour>();
private NetworkBehaviour _selectedNetworkBehaviour;
private FieldInfo[] _syncCollectionFields = Array.Empty<FieldInfo>();
private readonly Dictionary<FieldInfo, bool> _fieldToggles = new Dictionary<FieldInfo, bool>();
[MenuItem("Fish-Networking/Tools/Sync Collection Viewer")]
private static void ShowWindow()
{
SyncCollectionViewer syncCollectionViewer = GetWindow<SyncCollectionViewer>();
syncCollectionViewer.titleContent = new GUIContent("Sync Collection Viewer");
}
private void OnEnable()
{
EditorApplication.update += Repaint;
RefreshNetworkBehaviours();
}
private void OnDisable()
{
EditorApplication.update -= Repaint;
}
private void OnGUI()
{
if (_selectedNetworkBehaviour == null)
{
DrawNetworkBehaviourSelectionGui();
}
else
{
DrawSyncCollectionViewerGui();
}
}
private void RefreshNetworkBehaviours()
{
_networkBehaviours = FindObjectsOfType<NetworkBehaviour>();
}
private void SelectNetworkBehaviour(NetworkBehaviour networkBehaviour)
{
if (networkBehaviour == null) return;
_selectedNetworkBehaviour = networkBehaviour;
_syncCollectionFields = _selectedNetworkBehaviour.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(f => f.FieldType.IsGenericType && (f.FieldType.GetGenericTypeDefinition() == typeof(SyncList<>) || f.FieldType.GetGenericTypeDefinition() == typeof(SyncHashSet<>) || f.FieldType.GetGenericTypeDefinition() == typeof(SyncDictionary<,>)))
.ToArray();
_fieldToggles.Clear();
foreach (FieldInfo fieldInfo in _syncCollectionFields)
{
_fieldToggles.Add(fieldInfo, false);
}
}
private void DrawNetworkBehaviourSelectionGui()
{
if (GUILayout.Button("Refresh")) RefreshNetworkBehaviours();
_scroll = EditorGUILayout.BeginScrollView(_scroll);
if (_networkBehaviours.Length == 0)
{
EditorGUILayout.HelpBox("No NetworkBehaviours found in scene.", MessageType.Info);
}
else
{
for (int i = 0; i < _networkBehaviours.Length; i++)
{
NetworkBehaviour networkBehaviour = _networkBehaviours[i];
if (networkBehaviour == null) continue;
if (GUILayout.Button(networkBehaviour.name)) SelectNetworkBehaviour(networkBehaviour);
}
}
EditorGUILayout.EndScrollView();
}
private void DeselectNetworkBehaviour()
{
_selectedNetworkBehaviour = null;
_syncCollectionFields = Array.Empty<FieldInfo>();
_fieldToggles.Clear();
}
private void DrawSyncCollectionItem(object item)
{
if (item == null) return;
if (item is UnityEngine.Object unityEngineObject)
{
GUI.enabled = false;
EditorGUILayout.ObjectField(unityEngineObject, unityEngineObject.GetType(), true);
GUI.enabled = true;
}
else
{
Type itemType = item.GetType();
if (itemType.IsGenericType && itemType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Key");
DrawSyncCollectionItem(itemType.GetProperty("Key").GetValue(item));
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Value");
DrawSyncCollectionItem(itemType.GetProperty("Value").GetValue(item));
EditorGUILayout.EndHorizontal();
}
else
{
EditorGUILayout.LabelField(item.ToString());
}
}
}
private void DrawSyncCollectionViewerGui()
{
if (GUILayout.Button("Deselect"))
{
DeselectNetworkBehaviour();
return;
}
_scroll = EditorGUILayout.BeginScrollView(_scroll);
foreach (FieldInfo syncCollectionField in _syncCollectionFields)
{
IEnumerable syncCollection = syncCollectionField.GetValue(_selectedNetworkBehaviour) as IEnumerable;
_fieldToggles[syncCollectionField] = EditorGUILayout.Foldout(_fieldToggles[syncCollectionField], syncCollectionField.Name);
if (_fieldToggles[syncCollectionField])
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
foreach (object item in syncCollection)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
DrawSyncCollectionItem(item);
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndVertical();
}
}
EditorGUILayout.EndScrollView();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment