Merge pull request #18 from AnnulusGames/feature-hierarchy-extensions

Feature: hierarchy extensions
This commit is contained in:
Annulus Games 2024-02-16 21:38:59 +09:00 committed by GitHub
commit 43d241c0bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 902 additions and 18 deletions

View File

@ -0,0 +1,42 @@
using System.IO;
using UnityEngine;
using Alchemy.Hierarchy;
namespace Alchemy.Editor
{
public sealed class AlchemySettings : ScriptableObject
{
static readonly string SettingsPath = "ProjectSettings/AlchemySettings.json";
static AlchemySettings instance;
public static AlchemySettings GetOrCreateSettings()
{
if (instance != null) return instance;
if (File.Exists(SettingsPath))
{
instance = CreateInstance<AlchemySettings>();
JsonUtility.FromJsonOverwrite(File.ReadAllText(SettingsPath), instance);
}
else
{
instance = CreateInstance<AlchemySettings>();
}
return instance;
}
public static void SaveSettings()
{
File.WriteAllText(SettingsPath, JsonUtility.ToJson(instance, true));
}
[SerializeField] HierarchyObjectMode hierarchyObjectMode = HierarchyObjectMode.RemoveInBuild;
[SerializeField] bool showHierarchyToggles;
[SerializeField] bool showComponentIcons;
public HierarchyObjectMode HierarchyObjectMode => hierarchyObjectMode;
public bool ShowHierarchyToggles => showHierarchyToggles;
public bool ShowComponentIcons => showComponentIcons;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be6c5afdb20ff4718b97d2eeeb1787e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,47 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Alchemy.Editor
{
internal static class AlchemySettingsProvider
{
static readonly string MenuName = "Project/Alchemy";
[SettingsProvider]
public static SettingsProvider CreateSettingsProvider()
{
return new SettingsProvider(MenuName, SettingsScope.Project)
{
label = "Alchemy",
keywords = new HashSet<string>(new[] { "Alchemy, Inspector, Hierarchy" }),
guiHandler = searchContext =>
{
var serializedObject = new SerializedObject(AlchemySettings.GetOrCreateSettings());
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(10f);
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.LabelField("Hierarchy", EditorStyles.boldLabel);
using (var changeCheck = new EditorGUI.ChangeCheckScope())
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("hierarchyObjectMode"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("showHierarchyToggles"), new GUIContent("Show Toggles"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("showComponentIcons"));
if (changeCheck.changed)
{
serializedObject.ApplyModifiedProperties();
AlchemySettings.SaveSettings();
}
}
}
}
},
};
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7430b79e486304556b32ebe13b6674b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7706aa48d1fdb4b70a5b1730f9a590b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,40 @@
using UnityEditor;
using UnityEngine;
using Alchemy.Editor.Internal;
namespace Alchemy.Editor
{
public abstract class HierarchyDrawer
{
public abstract void OnGUI(int instanceID, Rect selectionRect);
protected static Rect GetBackgroundRect(Rect selectionRect)
{
return selectionRect.AddXMax(20f);
}
protected static void DrawBackground(int instanceID, Rect selectionRect)
{
var backgroundRect = GetBackgroundRect(selectionRect);
Color backgroundColor;
var e = Event.current;
var isHover = backgroundRect.Contains(e.mousePosition);
if (Selection.Contains(instanceID))
{
backgroundColor = EditorColors.HighlightBackground;
}
else if (isHover)
{
backgroundColor = EditorColors.HighlightBackgroundInactive;
}
else
{
backgroundColor = EditorColors.WindowBackground;
}
EditorGUI.DrawRect(backgroundRect, backgroundColor);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99c62ee36c15445da9b11f082910fdfd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
using System;
using System.Linq;
using UnityEditor;
namespace Alchemy.Editor
{
internal static class HierarchyDrawerInitializer
{
[InitializeOnLoadMethod]
static void Init()
{
var drawers = TypeCache.GetTypesDerivedFrom<HierarchyDrawer>()
.Where(x => !x.IsAbstract)
.Select(x => (HierarchyDrawer)Activator.CreateInstance(x));
foreach (var drawer in drawers)
{
EditorApplication.hierarchyWindowItemOnGUI += drawer.OnGUI;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b5afaf0d349640efa275f491f5caf46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,34 @@
using UnityEditor;
using UnityEngine;
using Alchemy.Hierarchy;
namespace Alchemy.Editor
{
public sealed class HierarchyHeaderDrawer : HierarchyDrawer
{
static Color HeaderColor => EditorGUIUtility.isProSkin ? new(0.45f, 0.45f, 0.45f, 0.5f) : new(0.55f, 0.55f, 0.55f, 0.5f);
static GUIStyle labelStyle;
public override void OnGUI(int instanceID, Rect selectionRect)
{
if (labelStyle == null)
{
labelStyle = new GUIStyle(EditorStyles.boldLabel)
{
alignment = TextAnchor.MiddleCenter,
fontSize = 11,
};
}
var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (gameObject == null) return;
if (!gameObject.TryGetComponent<HierarchyHeader>(out _)) return;
DrawBackground(instanceID, selectionRect);
var headerRect = selectionRect.AddXMax(14f).AddYMax(-1f);
EditorGUI.DrawRect(headerRect, HeaderColor);
EditorGUI.LabelField(headerRect, gameObject.name, labelStyle);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 21aad9026029c4fdfa791adb1c12777b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,29 @@
using UnityEditor;
using UnityEngine;
using Alchemy.Hierarchy;
namespace Alchemy.Editor
{
internal static class HierarchyObjectCreationMenu
{
[MenuItem("GameObject/Alchemy/Header", false)]
static void CreateHeader(MenuCommand menuCommand)
{
var obj = new GameObject("Header");
obj.AddComponent<HierarchyHeader>();
GameObjectUtility.SetParentAndAlign(obj, menuCommand.context as GameObject);
Undo.RegisterCreatedObjectUndo(obj, "Create " + obj.name);
Selection.activeObject = obj;
}
[MenuItem("GameObject/Alchemy/Separator", false)]
static void CreateSeparator(MenuCommand menuCommand)
{
var obj = new GameObject("Separator");
obj.AddComponent<HierarchySeparator>();
GameObjectUtility.SetParentAndAlign(obj, menuCommand.context as GameObject);
Undo.RegisterCreatedObjectUndo(obj, "Create " + obj.name);
Selection.activeObject = obj;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a76950d5487d4ea9a206d592736591b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,26 @@
using UnityEditor;
using UnityEngine.UIElements;
using Alchemy.Hierarchy;
using UnityEditor.UIElements;
namespace Alchemy.Editor
{
[CustomEditor(typeof(HierarchyObject), true)]
[CanEditMultipleObjects]
public sealed class HierarchyObjectEditor : UnityEditor.Editor
{
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
var iterator = serializedObject.GetIterator();
iterator.NextVisible(true);
while (iterator.NextVisible(false))
{
root.Add(new PropertyField(iterator));
}
return root;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad667e8cf560a44f7a8d1cfd5f79f2df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.SceneManagement;
using Alchemy.Hierarchy;
namespace Alchemy.Editor
{
public sealed class HierarchyObjectProcessor : IProcessSceneWithReport
{
public int callbackOrder => 0;
public void OnProcessScene(Scene scene, BuildReport report)
{
var settings = AlchemySettings.GetOrCreateSettings();
var hierarchyObjects = scene.GetRootGameObjects()
.SelectMany(x => x.GetComponentsInChildren<HierarchyObject>())
.Where(x => x != null)
.OrderByDescending(x => GetDepth(x.transform));
foreach (var obj in hierarchyObjects)
{
if (obj == null) continue;
switch (GetHierarchyObjectMode(obj))
{
case HierarchyObjectMode.None:
break;
case HierarchyObjectMode.RemoveInPlayMode:
obj.transform.DetachChildren();
Object.DestroyImmediate(obj.gameObject);
break;
case HierarchyObjectMode.RemoveInBuild:
if (EditorApplication.isPlaying) break;
obj.transform.DetachChildren();
Object.DestroyImmediate(obj.gameObject);
break;
}
}
}
static HierarchyObjectMode GetHierarchyObjectMode(HierarchyObject obj)
{
return obj.HierarchyObjectMode != HierarchyObject.Mode.UseSettings
? (HierarchyObjectMode)(obj.HierarchyObjectMode - 1)
: AlchemySettings.GetOrCreateSettings().HierarchyObjectMode;
}
static int GetDepth(Transform transform)
{
var depth = 0;
var parent = transform.parent;
while (parent != null)
{
depth++;
parent = parent.parent;
}
return depth;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41689920aa3aa442ab979a1a81dd7568
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
using UnityEditor;
using UnityEngine;
using Alchemy.Hierarchy;
namespace Alchemy.Editor
{
public sealed class HierarchySeparatorDrawer : HierarchyDrawer
{
static Color SeparatorColor => new(0.5f, 0.5f, 0.5f);
public override void OnGUI(int instanceID, Rect selectionRect)
{
var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (gameObject == null) return;
if (!gameObject.TryGetComponent<HierarchySeparator>(out _)) return;
DrawBackground(instanceID, selectionRect);
var lineRect = selectionRect.AddY(selectionRect.height * 0.5f).AddXMax(14f).SetHeight(1f);
EditorGUI.DrawRect(lineRect, SeparatorColor);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf8a3062aab50494990244011aa1ec06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,82 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
using Alchemy.Hierarchy;
using Alchemy.Editor.Internal;
namespace Alchemy.Editor
{
public sealed class HierarchyToggleDrawer : HierarchyDrawer
{
public override void OnGUI(int instanceID, Rect selectionRect)
{
var gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (gameObject == null) return;
if (gameObject.TryGetComponent<HierarchyObject>(out _)) return;
var settings = AlchemySettings.GetOrCreateSettings();
if (settings.ShowHierarchyToggles)
{
var rect = selectionRect;
rect.x = rect.xMax - 2.7f;
rect.width = 16f;
var active = GUI.Toggle(rect, gameObject.activeSelf, string.Empty);
if (active != gameObject.activeSelf)
{
Undo.RecordObject(gameObject, $"{(active ? "Activate" : "Deactivate")} GameObject '{gameObject.name}'");
gameObject.SetActive(active);
EditorUtility.SetDirty(gameObject);
}
}
if (settings.ShowComponentIcons)
{
var rect = selectionRect;
rect.x = rect.xMax - (settings.ShowHierarchyToggles ? 18.7f : 2.7f);
rect.y += 1f;
rect.width = 14f;
rect.height = 14f;
var components = gameObject
.GetComponents<Component>()
.AsEnumerable()
.Reverse();
var existsScriptIcon = false;
foreach (var component in components)
{
var image = AssetPreview.GetMiniThumbnail(component);
if (image == null) continue;
if (image == EditorIcons.CsScriptIcon.image)
{
if (existsScriptIcon) continue;
existsScriptIcon = true;
}
DrawIcon(ref rect, image, IsEnabled(component) ? Color.white : new(1f, 1f, 1f, 0.5f));
}
}
}
static void DrawIcon(ref Rect rect, Texture image, Color color)
{
var defaultColor = GUI.color;
GUI.color = color;
GUI.DrawTexture(rect, image, ScaleMode.ScaleToFit);
rect.x -= rect.width;
GUI.color = defaultColor;
}
static bool IsEnabled(Component component)
{
var property = component.GetType().GetProperty("enabled", typeof(bool));
return (bool)(property?.GetValue(component, null) ?? true);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 527cfc72d81d34166ab175d08e86e0b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,71 @@
using UnityEngine;
using UnityEditor;
using System;
namespace Alchemy.Editor.Internal
{
// Rererence: https://www.foundations.unity.com/fundamentals/color-palette
internal static class EditorColors
{
static Color GetColor(string htmlColor)
{
if (!ColorUtility.TryParseHtmlString(htmlColor, out var color)) throw new ArgumentException();
return color;
}
public static Color DefaultBackground
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#282828");
else return GetColor("#A5A5A5");
}
}
public static Color HighlightBackgroundInactive
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#4D4D4D");
else return GetColor("#AEAEAE");
}
}
public static Color HighlightBackground
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#2C5D87");
else return GetColor("#3A72B0");
}
}
public static Color WindowBackground
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#383838");
else return GetColor("#C8C8C8");
}
}
public static Color InspectorTitlebarBorder
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#1A1A1A");
else return GetColor("#7F7F7F");
}
}
public static Color DefaultText
{
get
{
if (EditorGUIUtility.isProSkin) return GetColor("#D2D2D2");
else return GetColor("#090909");
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e417a3e095b0d43a1b3d886d05d2b4c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
using UnityEngine;
namespace Alchemy.Editor
{
internal static class RectHelper
{
public static Rect Expand(this Rect rect, float value)
{
rect.xMin -= value;
rect.xMax += value;
rect.yMin -= value;
rect.yMax += value;
return rect;
}
public static Rect ExpandX(this Rect rect, float value)
{
rect.xMin -= value;
rect.xMax += value;
return rect;
}
public static Rect ExpandY(this Rect rect, float value)
{
rect.yMin -= value;
rect.yMax += value;
return rect;
}
public static Rect AddX(this Rect rect, float value)
{
rect.x += value;
return rect;
}
public static Rect AddY(this Rect rect, float value)
{
rect.y += value;
return rect;
}
public static Rect AddXMin(this Rect rect, float value)
{
rect.xMin += value;
return rect;
}
public static Rect AddXMax(this Rect rect, float value)
{
rect.xMax += value;
return rect;
}
public static Rect AddYMin(this Rect rect, float value)
{
rect.yMin += value;
return rect;
}
public static Rect AddYMax(this Rect rect, float value)
{
rect.yMax += value;
return rect;
}
public static Rect SetWidth(this Rect rect, float value)
{
rect.width = value;
return rect;
}
public static Rect SetHeight(this Rect rect, float value)
{
rect.height = value;
return rect;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ebc9adffd3924cb68c38dd5d6789d24
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f1d5771148ed6492c9fb410ac314cb84
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace Alchemy.Hierarchy
{
[AddComponentMenu("Alchemy/Hierarchy Header")]
public sealed class HierarchyHeader : HierarchyObject { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f517a64d7c9c64b32922a42317242caf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
using UnityEngine;
namespace Alchemy.Hierarchy
{
[DisallowMultipleComponent]
[AddComponentMenu("Alchemy/Hierarchy Object")]
public class HierarchyObject : MonoBehaviour
{
public enum Mode
{
UseSettings = 0,
None = 1,
RemoveInPlayMode = 2,
RemoveInBuild = 3
}
[SerializeField] Mode hierarchyObjectMode = Mode.UseSettings;
public Mode HierarchyObjectMode => hierarchyObjectMode;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3887b4614e88d4da584077c7dc0e6b90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
namespace Alchemy.Hierarchy
{
public enum HierarchyObjectMode
{
None = 0,
RemoveInPlayMode = 1,
RemoveInBuild = 2
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed6b9dff8345a4f5f91110010d6d7d54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
using UnityEngine;
namespace Alchemy.Hierarchy
{
[AddComponentMenu("Alchemy/Hierarchy Separator")]
public sealed class HierarchySeparator : HierarchyObject { }
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 941cd1bade9ee428cbf8dc33883c67b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
{
"hierarchyObjectMode": 2,
"showHierarchyToggles": true,
"showComponentIcons": true
}

View File

@ -6,7 +6,7 @@ QualitySettings:
serializedVersion: 5 serializedVersion: 5
m_CurrentQuality: 5 m_CurrentQuality: 5
m_QualitySettings: m_QualitySettings:
- serializedVersion: 2 - serializedVersion: 3
name: Very Low name: Very Low
pixelLightCount: 0 pixelLightCount: 0
shadows: 0 shadows: 0
@ -18,17 +18,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0 shadowmaskMode: 0
blendWeights: 1 skinWeights: 1
textureQuality: 1 globalTextureMipmapLimit: 1
textureMipmapLimitSettings: []
anisotropicTextures: 0 anisotropicTextures: 0
antiAliasing: 0 antiAliasing: 0
softParticles: 0 softParticles: 0
softVegetation: 0 softVegetation: 0
realtimeReflectionProbes: 0 realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0 billboardsFaceCameraPosition: 0
useLegacyDetailDistribution: 1
vSyncCount: 0 vSyncCount: 0
realtimeGICPUUsage: 25
lodBias: 0.3 lodBias: 0.3
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -40,8 +44,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
- serializedVersion: 2 - serializedVersion: 3
name: Low name: Low
pixelLightCount: 0 pixelLightCount: 0
shadows: 0 shadows: 0
@ -53,17 +67,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0 shadowmaskMode: 0
blendWeights: 2 skinWeights: 2
textureQuality: 0 globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 0 anisotropicTextures: 0
antiAliasing: 0 antiAliasing: 0
softParticles: 0 softParticles: 0
softVegetation: 0 softVegetation: 0
realtimeReflectionProbes: 0 realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0 billboardsFaceCameraPosition: 0
useLegacyDetailDistribution: 1
vSyncCount: 0 vSyncCount: 0
realtimeGICPUUsage: 25
lodBias: 0.4 lodBias: 0.4
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -75,8 +93,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
- serializedVersion: 2 - serializedVersion: 3
name: Medium name: Medium
pixelLightCount: 1 pixelLightCount: 1
shadows: 1 shadows: 1
@ -88,17 +116,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0 shadowmaskMode: 0
blendWeights: 2 skinWeights: 2
textureQuality: 0 globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 1 anisotropicTextures: 1
antiAliasing: 0 antiAliasing: 0
softParticles: 0 softParticles: 0
softVegetation: 0 softVegetation: 0
realtimeReflectionProbes: 0 realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0 billboardsFaceCameraPosition: 0
useLegacyDetailDistribution: 1
vSyncCount: 1 vSyncCount: 1
realtimeGICPUUsage: 25
lodBias: 0.7 lodBias: 0.7
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -110,8 +142,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
- serializedVersion: 2 - serializedVersion: 3
name: High name: High
pixelLightCount: 2 pixelLightCount: 2
shadows: 2 shadows: 2
@ -123,17 +165,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1 shadowmaskMode: 1
blendWeights: 2 skinWeights: 2
textureQuality: 0 globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 1 anisotropicTextures: 1
antiAliasing: 0 antiAliasing: 0
softParticles: 0 softParticles: 0
softVegetation: 1 softVegetation: 1
realtimeReflectionProbes: 1 realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1 billboardsFaceCameraPosition: 1
useLegacyDetailDistribution: 1
vSyncCount: 1 vSyncCount: 1
realtimeGICPUUsage: 50
lodBias: 1 lodBias: 1
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -145,8 +191,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
- serializedVersion: 2 - serializedVersion: 3
name: Very High name: Very High
pixelLightCount: 3 pixelLightCount: 3
shadows: 2 shadows: 2
@ -158,17 +214,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1 shadowmaskMode: 1
blendWeights: 4 skinWeights: 4
textureQuality: 0 globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 2 anisotropicTextures: 2
antiAliasing: 2 antiAliasing: 2
softParticles: 1 softParticles: 1
softVegetation: 1 softVegetation: 1
realtimeReflectionProbes: 1 realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1 billboardsFaceCameraPosition: 1
useLegacyDetailDistribution: 1
vSyncCount: 1 vSyncCount: 1
realtimeGICPUUsage: 50
lodBias: 1.5 lodBias: 1.5
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -180,8 +240,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
- serializedVersion: 2 - serializedVersion: 3
name: Ultra name: Ultra
pixelLightCount: 4 pixelLightCount: 4
shadows: 2 shadows: 2
@ -193,17 +263,21 @@ QualitySettings:
shadowCascade2Split: 0.33333334 shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1 shadowmaskMode: 1
blendWeights: 4 skinWeights: 4
textureQuality: 0 globalTextureMipmapLimit: 0
textureMipmapLimitSettings: []
anisotropicTextures: 2 anisotropicTextures: 2
antiAliasing: 2 antiAliasing: 2
softParticles: 1 softParticles: 1
softVegetation: 1 softVegetation: 1
realtimeReflectionProbes: 1 realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1 billboardsFaceCameraPosition: 1
useLegacyDetailDistribution: 1
vSyncCount: 1 vSyncCount: 1
realtimeGICPUUsage: 100
lodBias: 2 lodBias: 2
maximumLODLevel: 0 maximumLODLevel: 0
enableLODCrossFade: 1
streamingMipmapsActive: 0 streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1 streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512 streamingMipmapsMemoryBudget: 512
@ -215,7 +289,18 @@ QualitySettings:
asyncUploadBufferSize: 16 asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1 asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1 resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
terrainQualityOverrides: 0
terrainPixelError: 1
terrainDetailDensityScale: 1
terrainBasemapDistance: 1000
terrainDetailDistance: 80
terrainTreeDistance: 5000
terrainBillboardStart: 50
terrainFadeLength: 5
terrainMaxTrees: 50
excludedTargetPlatforms: [] excludedTargetPlatforms: []
m_TextureMipmapLimitGroupNames: []
m_PerPlatformDefaultQuality: m_PerPlatformDefaultQuality:
Android: 2 Android: 2
Lumin: 5 Lumin: 5
@ -223,6 +308,7 @@ QualitySettings:
Nintendo Switch: 5 Nintendo Switch: 5
PS4: 5 PS4: 5
PSP2: 2 PSP2: 2
Server: 0
Stadia: 5 Stadia: 5
Standalone: 5 Standalone: 5
WebGL: 3 WebGL: 3