ㅋㅋㅋㄹㅇ


내가 짠 코드보면 한숨 나옴



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System.Collections.Generic;
using UnityEngine;
using Core;
using MainGame;
 
namespace Target2DSystem
{
    /// <summary>
    /// QuadTree를 사용하여 2D 환경에서 타겟팅 시스템을 관리하는 클래스
    /// 이 클래스는 적 또는 다른 타겟을 QuadTree에 추가 및 제거하며,
    /// 지정된 위치에서 가장 가까운 타겟, 가장 먼 타겟, 또는 우선순위가 가장 높은 타겟을 검색하는 기능을 제공
    /// </summary>
    public class QuadTreeTargetingSystem : Singleton<QuadTreeTargetingSystem>
    {
        private QuadTree quadTree; // QuadTree 객체
        private Rect worldBounds;  // QuadTree가 커버하는 월드 범위
 
        private bool isInitialized = false// 초기화 여부를 확인하기 위한 플래그
 
        /// <summary>
        /// QuadTreeTargetingSystem을 초기화하는 메서드
        /// 던전 빌더로부터 던전 경계를 가져와 QuadTree를 생성
        /// </summary>
        private void Initialize()
        {
            worldBounds = DungeonBuilder.Instance.GetDungeonBounds(); // 던전 경계를 가져옴
            quadTree = new QuadTree(worldBounds, 4); // QuadTree를 생성, 최대 4개의 객체를 가지는 노드로 설정
            isInitialized = true// 초기화 완료
        }
 
        /// <summary>
        /// QuadTreeTargetingSystem이 초기화되었는지 확인하고, 초기화되지 않은 경우 초기화를 수행
        /// </summary>
        private void EnsureInitialized()
        {
            if (!isInitialized)
            {
                Initialize();
            }
        }
 
        /// <summary>
        /// 새로운 타겟을 QuadTree에 추가
        /// </summary>
        /// <param name="target">추가할 타겟</param>
        public void AddTarget(ITargetable target)
        {
            EnsureInitialized(); // 초기화 확인
            // 타겟 추가 전 Faction 정보를 출력
            //Faction faction = target.GetFactionDetails().GetFaction();
            //Debug.Log($"[쿼드트리 타겟 추가] 타겟: {target}, Faction: {faction}");
            quadTree.Insert(target); // 타겟 추가
        }
 
        /// <summary>
        /// 타겟을 QuadTree에서 제거
        /// </summary>
        /// <param name="target">제거할 타겟</param>
        public void RemoveTarget(ITargetable target)
        {
            EnsureInitialized(); // 초기화 확인
            quadTree.Remove(target); // 타겟 제거
        }
 
        /// <summary>
        /// 지정된 유닛과 현재 저장할 타겟을 기반으로 가장 가까운 적절한 타겟을 반환합니다.
        /// </summary>
        /// <param name="sender">타겟을 찾는 유닛</param>
        /// <param name="currentTarget">결과로 저장할 타겟</param>
        /// <returns>가장 가까운 타겟, 없으면 null 반환</returns>
        public ITargetable GetClosestTargetWithDifferentFaction(ITargetable sender, ITargetable currentTarget)
        {
            EnsureInitialized(); // 초기화 확인
 
            Vector3 position = sender.GetTargetTransform().position;
            Faction senderFaction = sender.GetFactionDetails().GetFaction(); // Sender의 Faction
 
            List<ITargetable> potentialTargets = quadTree.Retrieve(position); // 잠재적 타겟 검색
            //Debug.Log($"검색된 잠재적 타겟 수: {potentialTargets.Count}");
 
 
            ITargetable closestTarget = null;
            float closestDistance = float.MaxValue;
 
            foreach (ITargetable potentialTarget in potentialTargets)
            {
                Faction targetFaction = potentialTarget.GetFactionDetails().GetFaction(); // 잠재적 타겟의 Faction
                //Debug.Log($"잠재적 타겟: {potentialTarget}, Faction: {potentialTarget.GetFactionDetails().GetFaction()}");
 
                if (targetFaction == senderFaction)
                {
                    //Debug.Log($"[타겟 검색] 타겟이 같은 Faction입니다: {targetFaction}, 건너뜀.");
                    continue// 같은 Faction의 타겟은 건너뜀
                }
                //Debug.Log($"[타겟 발견] 다른 Faction 발견! 타겟: {potentialTarget}, Faction: {targetFaction}");
 
                float distance = Vector3.Distance(position, potentialTarget.GetTargetTransform().position);
                if (distance < closestDistance)
                {
                    closestDistance = distance;
                    closestTarget = potentialTarget;
                    //Debug.Log($"[타겟 검색] 새로운 가장 가까운 타겟: {closestTarget}, 거리: {closestDistance}");
 
                }
            }
 
            currentTarget = closestTarget; // 가장 가까운 타겟을 currentTarget에 저장
            Debug.Log($"최종 반환할 타겟: {currentTarget}");
            return currentTarget; // 가장 가까운 타겟을 반환
        }
 
 
        /// <summary>
        /// 지정된 위치에서 현재 유닛과 같은 팩션에 속하지 않은 또는 팩션이 없는 가장 가까운 타겟을 반환합니다.
        /// </summary>
        /// <param name="sender">타겟을 찾는 유닛</param>
        /// <param name="currentTarget">결과로 저장할 타겟</param>
        /// <returns>가장 가까운 타겟, 없으면 null 반환</returns>
        public ITargetable GetClosestTargetWithDifferentOrNoFaction(ITargetable sender, ref ITargetable currentTarget)
        {
            EnsureInitialized(); // 초기화 확인
 
            Vector3 position = sender.GetTargetTransform().position;
            Faction currentFaction = sender.GetFactionDetails().GetFaction();
 
            List<ITargetable> potentialTargets = quadTree.Retrieve(position); // 잠재적 타겟 검색
 
            ITargetable closestTarget = currentTarget;
            float closestDistance = currentTarget != null ? Vector3.Distance(position, currentTarget.GetTargetTransform().position) : float.MaxValue;
 
            foreach (ITargetable potentialTarget in potentialTargets)
            {
                if (potentialTarget.GetFactionDetails().GetFaction() != currentFaction) // 같은 팩션이 아닌 경우
                {
                    float distance = Vector3.Distance(position, potentialTarget.GetTargetTransform().position);
                    if (distance < closestDistance)
                    {
                        closestDistance = distance;
                        closestTarget = potentialTarget;
                    }
                }
            }
 
            currentTarget = closestTarget; // 가장 가까운 타겟을 currentTarget에 저장
 
            return closestTarget; // 가장 가까운 타겟을 반환
        }
 
    }
}
 
cs