From a155d85f72be4bb1a9f33c7b1ec3ad10daecb849 Mon Sep 17 00:00:00 2001 From: Pasha Bibko <156938226+PashaBibko@users.noreply.github.com> Date: Thu, 15 Jan 2026 13:20:04 +0000 Subject: [PATCH] Added spawn weighting --- Assets/Scenes/GameScene.unity | 11 ++ Assets/Scripts/Ext.meta | 3 + Assets/Scripts/Ext/MonoScriptAttribute.cs | 45 ++++++++ .../Scripts/Ext/MonoScriptAttribute.cs.meta | 11 ++ .../Scripts/Ext/MonoScriptPropertyDrawer.cs | 103 ++++++++++++++++++ .../Ext/MonoScriptPropertyDrawer.cs.meta | 11 ++ Assets/Scripts/WindowSpawner.cs | 51 ++++++--- 7 files changed, 221 insertions(+), 14 deletions(-) create mode 100644 Assets/Scripts/Ext.meta create mode 100644 Assets/Scripts/Ext/MonoScriptAttribute.cs create mode 100644 Assets/Scripts/Ext/MonoScriptAttribute.cs.meta create mode 100644 Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs create mode 100644 Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs.meta diff --git a/Assets/Scenes/GameScene.unity b/Assets/Scenes/GameScene.unity index 88a7905..369c53a 100644 --- a/Assets/Scenes/GameScene.unity +++ b/Assets/Scenes/GameScene.unity @@ -642,6 +642,17 @@ MonoBehaviour: k__BackingField: {fileID: 8853825751094127020, guid: 2cad467961f3cff4984a6f50fc091377, type: 3} k__BackingField: {fileID: 1539476654} + k__BackingField: + - k__BackingField: InterfaceOff.BasicWindow + k__BackingField: 10 + - k__BackingField: InterfaceOff.MovingWindow + k__BackingField: 2 + - k__BackingField: InterfaceOff.ImageWindow + k__BackingField: 1 + - k__BackingField: InterfaceOff.TrollWindow + k__BackingField: 2 + - k__BackingField: InterfaceOff.TriviaWindow + k__BackingField: 4 k__BackingField: 1 --- !u!4 &2038986853 Transform: diff --git a/Assets/Scripts/Ext.meta b/Assets/Scripts/Ext.meta new file mode 100644 index 0000000..08e3732 --- /dev/null +++ b/Assets/Scripts/Ext.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9c4ac8eadd314129ac24f2035e462dc0 +timeCreated: 1768482210 \ No newline at end of file diff --git a/Assets/Scripts/Ext/MonoScriptAttribute.cs b/Assets/Scripts/Ext/MonoScriptAttribute.cs new file mode 100644 index 0000000..1291161 --- /dev/null +++ b/Assets/Scripts/Ext/MonoScriptAttribute.cs @@ -0,0 +1,45 @@ +/***** + * This is part of a simple PropertyDrawer for string variables to allow drag + * and drop of MonoScripts in the inspector of the Unity3d editor. + * + * NOTE: This is a runtime script and MUST NOT be placed in a folder named "editor". + * It also requires another editor file named "MonoScriptPropertyDrawer.cs" + * + * Copyright (c) 2016 Bunny83 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + *****/ + +using UnityEngine; +using System; + +namespace Ext.B83.Unity.Attributes +{ + [AttributeUsage(AttributeTargets.Field)] + public class MonoScriptAttribute : PropertyAttribute + { + public Type type; + public MonoScriptAttribute() { } + public MonoScriptAttribute(System.Type aType) + { + type = aType; + } + } +} diff --git a/Assets/Scripts/Ext/MonoScriptAttribute.cs.meta b/Assets/Scripts/Ext/MonoScriptAttribute.cs.meta new file mode 100644 index 0000000..4652f5e --- /dev/null +++ b/Assets/Scripts/Ext/MonoScriptAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 433a7d4d13adbbc43bd8ef66708150c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs b/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs new file mode 100644 index 0000000..0b990ef --- /dev/null +++ b/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs @@ -0,0 +1,103 @@ +/***** + * This is a simple PropertyDrawer for string variables to allow drag and drop + * of MonoScripts in the inspector of the Unity3d editor. + * + * NOTE: This is an editor script and need to be placed in a folder named "editor". + * It also requires another runtime file named "MonoScriptAttribute.cs" + * + * Copyright (c) 2016 Bunny83 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + *****/ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using Ext.B83.Unity.Attributes; + +namespace Ext.B83.Unity.Editor.PropertyDrawers +{ + + [CustomPropertyDrawer(typeof(MonoScriptAttribute), false)] + public class MonoScriptPropertyDrawer : PropertyDrawer + { + static Dictionary m_ScriptCache; + static MonoScriptPropertyDrawer() + { + m_ScriptCache = new Dictionary(); + var scripts = Resources.FindObjectsOfTypeAll(); + for (int i = 0; i < scripts.Length; i++) + { + var type = scripts[i].GetClass(); + if (type != null && !m_ScriptCache.ContainsKey(type.FullName)) + { + m_ScriptCache.Add(type.FullName, scripts[i]); + } + } + } + bool m_ViewString = false; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType == SerializedPropertyType.String) + { + Rect r = EditorGUI.PrefixLabel(position, label); + Rect labelRect = position; + labelRect.xMax = r.xMin; + position = r; + m_ViewString = GUI.Toggle(labelRect, m_ViewString, "", "label"); + if (m_ViewString) + { + property.stringValue = EditorGUI.TextField(position, property.stringValue); + return; + } + MonoScript script = null; + string typeName = property.stringValue; + if (!string.IsNullOrEmpty(typeName)) + { + m_ScriptCache.TryGetValue(typeName, out script); + if (script == null) + GUI.color = Color.red; + } + + script = (MonoScript)EditorGUI.ObjectField(position, script, typeof(MonoScript), false); + if (GUI.changed) + { + if (script != null) + { + var type = script.GetClass(); + MonoScriptAttribute attr = (MonoScriptAttribute)attribute; + if (attr.type != null && !attr.type.IsAssignableFrom(type)) + type = null; + if (type != null) + property.stringValue = type.FullName; + else + Debug.LogWarning("The script file " + script.name + " doesn't contain an assignable class"); + } + else + property.stringValue = ""; + } + } + else + { + GUI.Label(position, "The MonoScript attribute can only be used on string variables"); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs.meta b/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs.meta new file mode 100644 index 0000000..8c09da0 --- /dev/null +++ b/Assets/Scripts/Ext/MonoScriptPropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52d258da1716b584badd0297eae9bfbf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/WindowSpawner.cs b/Assets/Scripts/WindowSpawner.cs index 6f97530..1c72d52 100644 --- a/Assets/Scripts/WindowSpawner.cs +++ b/Assets/Scripts/WindowSpawner.cs @@ -1,37 +1,60 @@ using System; using System.Collections.Generic; +using Ext.B83.Unity.Attributes; using UnityEngine; using Random = UnityEngine.Random; namespace InterfaceOff { + [Serializable] public struct SpawnableWindowType + { + [field: SerializeField, MonoScript] private string Typename { get; set; } + public Type Type => Type.GetType(Typename); + + [field: SerializeField] public int SpawnWeight { get; private set; } + } + public class WindowSpawner : MonoBehaviour { - private List WindowTypes { get; } = new(); - [field: SerializeField] private GameObject SampleChild { get; set; } [field: SerializeField] private Canvas GameCanvas { get; set; } + [field: SerializeField] private SpawnableWindowType[] WindowTypes { get; set; } + private int TotalSpawnWeight { get; set; } + [field: SerializeField] public bool AutoSpawn { get; private set; } = true; private void Awake() { - /* Fetches all window types created */ - Type[] types = typeof(WindowBase).Assembly.GetTypes(); - foreach (Type t in types) + /* Logs the amount of types found and errors if there is none */ + Debug.Log($"Found [{WindowTypes.Length}] different window types "); + if (WindowTypes.Length == 0) { - if (t.IsSubclassOf(typeof(WindowBase))) + Debug.LogError("Could not find any window types"); + return; + } + + /* Calculates the total spawn weight */ + TotalSpawnWeight = 0; + foreach (SpawnableWindowType type in WindowTypes) + { + TotalSpawnWeight += type.SpawnWeight; + } + } + + private Type GetRandomWindowType() + { + int currentTypeWeight = Random.Range(0, TotalSpawnWeight); + foreach (SpawnableWindowType type in WindowTypes) + { + currentTypeWeight -= type.SpawnWeight; + if (currentTypeWeight <= 0) { - WindowTypes.Add(t); + return type.Type; } } - /* Logs the amount of types found and errors if there is none */ - Debug.Log($"Found [{WindowTypes.Count}] different window types "); - if (WindowTypes.Count == 0) - { - Debug.LogError("Could not find any window types"); - } + return WindowTypes[0].Type; } private void SpawnNewRandomWindow() @@ -40,7 +63,7 @@ namespace InterfaceOff GameObject go = Instantiate(SampleChild, GameCanvas.transform); go.SetActive(true); - Type type = WindowTypes.GetRandom(); + Type type = GetRandomWindowType(); go.name = type.Name; WindowBase windowBase = go.AddComponent(type) as WindowBase;