using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using Unity.VisualScripting; #if UNITY_EDITOR using UnityEditor; [CustomEditor(typeof(SkillTreeManager))] public class SkillTreeManagerEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); if (GUILayout.Button("Generate")) { (target as SkillTreeManager).Generate(); } } } #endif public class SkillTreeManager : MonoBehaviour { //[SerializeField] //private [SerializeField] private float _lineColorVariation = 0.2f; [SerializeField] private float _lineOffset = 5f; [SerializeField] private float _lineThickness = 10f; [SerializeField] private Vector2 _startPositionOffset = new Vector2(200, 0); [SerializeField] Vector2 _distanceBetweenItems = Vector2.one * 200; [SerializeField] List _skillTreeItems; [SerializeField] GameObject _skillTreeItemPrefab; [SerializeField] GameObject _uiLineRendererPrefab; [SerializeField] GameObject _popUpConfigPrefab; [SerializeField] GameObject _skillTreeInfoItemPrefab; [SerializeField] Transform _nodeContainer; [SerializeField] Transform _lineContainer; private List DrawColumn(List items, List created) { var testList = new List(); var returnList = new List(); var ancestors = items.Max(current => GetAncestorCount(current)); for (int i = 0; i < items.Count; i++) { var item = items[i]; var comp = created.Find(x => x.Data == item); if (comp) { returnList.Add(comp); continue; } var x = _startPositionOffset.x + ancestors * _distanceBetweenItems.x; var y = _startPositionOffset.y + _distanceBetweenItems.y * i - (items.Count / 2) * _distanceBetweenItems.y; var pos = new Vector2(x, y); var instance = Instantiate(_skillTreeItemPrefab, _nodeContainer.transform); instance.GetComponent().anchoredPosition = pos; comp = instance.GetComponent(); comp.Data = item; comp._popUpConf = _popUpConfigPrefab; created.Add(comp); returnList.Add(comp); } return returnList; static int GetAncestorCount(SkillTreeItem item, int start = 0) { var max = start; foreach(var ancestor in item.Prerequisites) { var count = GetAncestorCount(ancestor, start + 1); if (count > max) max = count; } return max; } } private void Start() { Generate(); } public void Generate() { foreach (Transform t in _nodeContainer) DestroyImmediate(t.gameObject); foreach (Transform t in _lineContainer) DestroyImmediate(t.gameObject); var dict = new Dictionary>(); var created = new List(); var choices = _skillTreeItems.FindAll(x => x.Prerequisites.Count <= 0); DrawColumn(choices, created); for (int i = 0; i < created.Count; i++) { var current = created[i]; choices = _skillTreeItems.FindAll(x => x.Prerequisites.Contains(current.Data)); if (choices.Count <= 0) continue; var column = DrawColumn(choices, created); } foreach (var node in created) { dict.TryAdd(node.Data.GetHashCode(), new()); Vector2 colorVariation = new Vector2(Random.value - 0.5f, Random.value - 0.5f) * _lineColorVariation; var rect1 = node.GetComponent(); var prereqs = created.FindAll(x => x.Data.Prerequisites.Contains(node.Data)); for (int p = 0; p < prereqs.Count; p++) { var prereq = prereqs[p]; if (dict[node.Data.GetHashCode()].Contains(prereq.Data.GetHashCode())) continue; dict[node.Data.GetHashCode()].Add(prereq.Data.GetHashCode()); var rect2 = prereq.GetComponent(); var delta = rect2.anchoredPosition - rect1.anchoredPosition; var lineObj = Instantiate(_uiLineRendererPrefab, _lineContainer); var line = lineObj.GetComponent(); node.RelatedLines.Add(line); prereq.RelatedLines.Add(line); line.points.Clear(); line.points.Add(rect1.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one); line.points.Add(rect1.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one + Vector2.right * delta.x / 2); line.points.Add(rect2.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one + Vector2.left * delta.x / 2); line.points.Add(rect2.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one); line.transform.SetAsFirstSibling(); Color.RGBToHSV(line.color, out float H, out float S, out float V); line.thickness = _lineThickness; line.color = Color.HSVToRGB(H, S + colorVariation.x, V + colorVariation.y); } } } }