Skip to content

Commit d8d39dd

Browse files
committed
Equivalent of Unity's FindGameObjectsWithTag and refactoring
Do not update if you're using Tags for editor
1 parent f6b7129 commit d8d39dd

File tree

8 files changed

+83
-182
lines changed

8 files changed

+83
-182
lines changed

Runtime/Tag.cs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,46 @@ public sealed class Tag : ScriptableObject
1515
#if ODIN_INSPECTOR
1616
[ShowInInspector, ReadOnly]
1717
#endif
18-
private HashSet<int> _entities = new HashSet<int>();
18+
private readonly HashSet<int> _instancesHash = new HashSet<int>();
19+
private readonly List<GameObject> _instances = new List<GameObject>(128);
1920

20-
public void Add(int entity) =>
21-
_entities.Add(entity);
21+
public void Add(GameObject instance)
22+
{
23+
int hash = instance.GetHashCode();
2224

23-
public void Remove(int entity) =>
24-
_entities.Remove(entity);
25+
if (!_instancesHash.Contains(hash))
26+
{
27+
_instances.Add(instance);
28+
_instancesHash.Add(hash);
29+
}
30+
}
2531

26-
public bool HasEntity(int entity) =>
27-
_entities.Contains(entity);
32+
public void Remove(GameObject instance)
33+
{
34+
int hash = instance.GetHashCode();
35+
36+
if (_instancesHash.Contains(hash))
37+
{
38+
_instances.Remove(instance);
39+
_instancesHash.Remove(hash);
40+
}
41+
}
42+
43+
public bool HasInstance(int instanceHash) =>
44+
_instancesHash.Contains(instanceHash);
45+
46+
public IReadOnlyList<GameObject> GetInstances()
47+
{
48+
for (int i = _instances.Count - 1; i >= 0; i--)
49+
{
50+
var instance = _instances[i];
51+
52+
if (instance == null)
53+
_instances.RemoveAt(i);
54+
}
55+
56+
return _instances.AsReadOnly();
57+
}
2858
}
2959
}
3060

Runtime/Tag.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/TagExtensions.cs

Lines changed: 23 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,105 +4,48 @@ namespace ToolBox.Tags
44
{
55
public static class TagExtensions
66
{
7-
public static void AddTag(this GameObject entity, Tag tag)
8-
{
9-
#if UNITY_EDITOR
10-
var taggable = entity.GetComponent<Taggable>();
11-
12-
if (taggable == null)
13-
taggable = entity.AddComponent<Taggable>();
14-
15-
taggable.AddTagInEditor(tag);
16-
#endif
17-
18-
tag.Add(entity.GetHashCode());
19-
}
20-
21-
public static void RemoveTag(this GameObject entity, Tag tag)
22-
{
23-
#if UNITY_EDITOR
24-
var taggable = entity.GetComponent<Taggable>();
25-
26-
if (taggable == null)
27-
taggable = entity.AddComponent<Taggable>();
28-
29-
taggable.RemoveTagInEditor(tag);
30-
#endif
7+
public static void AddTag(this GameObject instance, Tag tag) =>
8+
tag.Add(instance);
319

32-
tag.Remove(entity.GetHashCode());
33-
}
10+
public static void RemoveTag(this GameObject instance, Tag tag) =>
11+
tag.Remove(instance);
3412

3513
public static bool HasTag(this GameObject entity, Tag tag) =>
36-
tag.HasEntity(entity.GetHashCode());
14+
tag.HasInstance(entity.GetHashCode());
3715

38-
public static void AddTags(this GameObject entity, Tag[] tags)
16+
public static void AddTags(this GameObject instance, Tag[] tags)
3917
{
40-
int hash = entity.GetHashCode();
41-
#if UNITY_EDITOR
42-
var taggable = entity.GetComponent<Taggable>();
43-
44-
if (taggable == null)
45-
taggable = entity.AddComponent<Taggable>();
46-
#endif
47-
4818
for (int i = 0; i < tags.Length; i++)
49-
{
50-
var tag = tags[i];
51-
tag.Add(hash);
52-
#if UNITY_EDITOR
53-
taggable.AddTagInEditor(tag);
54-
#endif
55-
}
19+
tags[i].Add(instance);
5620
}
5721

58-
public static void RemoveTags(this GameObject entity, Tag[] tags)
59-
{
60-
int hash = entity.GetHashCode();
61-
#if UNITY_EDITOR
62-
var taggable = entity.GetComponent<Taggable>();
63-
64-
if (taggable == null)
65-
taggable = entity.AddComponent<Taggable>();
66-
#endif
22+
public static void AddTags(this GameObject instance, TagsContainer container) =>
23+
container.Add(instance);
6724

25+
public static void RemoveTags(this GameObject instance, Tag[] tags)
26+
{
6827
for (int i = 0; i < tags.Length; i++)
69-
{
70-
var tag = tags[i];
71-
tag.Remove(hash);
72-
#if UNITY_EDITOR
73-
taggable.RemoveTagInEditor(tag);
74-
#endif
75-
}
28+
tags[i].Remove(instance);
7629
}
7730

78-
public static bool HasTags(this GameObject entity, Tag[] tags, bool allRequired)
31+
public static void RemoveTags(this GameObject instance, TagsContainer container) =>
32+
container.Remove(instance);
33+
34+
public static bool HasTags(this GameObject instance, Tag[] tags, bool allRequired)
7935
{
80-
int hash = entity.GetHashCode();
36+
int hash = instance.GetHashCode();
8137

82-
if (allRequired)
38+
for (int i = 0; i < tags.Length; i++)
8339
{
84-
for (int i = 0; i < tags.Length; i++)
85-
{
86-
if (!tags[i].HasEntity(hash))
87-
return false;
88-
}
89-
90-
return true;
40+
if (tags[i].HasInstance(hash) == !allRequired)
41+
return !allRequired;
9142
}
92-
else
93-
{
94-
for (int i = 0; i < tags.Length; i++)
95-
{
96-
if (tags[i].HasEntity(hash))
97-
return true;
98-
}
9943

100-
return false;
101-
}
44+
return allRequired;
10245
}
10346

104-
public static bool HasTags(this GameObject entity, TagsContainer tagsContainer, bool allRequired) =>
105-
tagsContainer.HasEntity(entity, allRequired);
47+
public static bool HasTags(this GameObject instance, TagsContainer container, bool allRequired) =>
48+
container.HasInstance(instance, allRequired);
10649
}
10750
}
10851

Runtime/TagExtensions.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Taggable.cs

Lines changed: 5 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,28 @@
11
#if ODIN_INSPECTOR
22
using Sirenix.OdinInspector;
33
#endif
4-
#if UNITY_EDITOR
5-
using UnityEditor;
6-
#endif
74
using UnityEngine;
85

96
namespace ToolBox.Tags
107
{
11-
[DisallowMultipleComponent, DefaultExecutionOrder(-9000), ExecuteInEditMode]
8+
[DisallowMultipleComponent, DefaultExecutionOrder(-9000)]
129
public sealed class Taggable : MonoBehaviour
1310
{
1411
#if ODIN_INSPECTOR
1512
[Required, AssetList]
1613
#endif
1714
[SerializeField] private Tag[] _tags = default;
1815

19-
#if UNITY_EDITOR
20-
private static Tag[] _all = null;
21-
#endif
22-
private int _hash = 0;
16+
private GameObject _instance = null;
2317

2418
private void Awake()
2519
{
26-
#if UNITY_EDITOR
27-
SetupEditorData();
28-
#endif
29-
30-
_hash = gameObject.GetHashCode();
31-
AddAll();
20+
_instance = gameObject;
21+
_instance.AddTags(_tags);
3222
}
3323

3424
private void OnDestroy() =>
35-
RemoveAll();
36-
37-
private void AddAll()
38-
{
39-
for (int i = 0; i < _tags.Length; i++)
40-
_tags[i].Add(_hash);
41-
}
42-
43-
private void RemoveAll()
44-
{
45-
for (int i = 0; i < _tags.Length; i++)
46-
_tags[i].Remove(_hash);
47-
}
48-
49-
#if UNITY_EDITOR
50-
public void AddTagInEditor(Tag tag)
51-
{
52-
if (!ArrayUtility.Contains(_tags, tag))
53-
ArrayUtility.Add(ref _tags, tag);
54-
}
55-
56-
public void RemoveTagInEditor(Tag tag)
57-
{
58-
if (ArrayUtility.Contains(_tags, tag))
59-
ArrayUtility.Remove(ref _tags, tag);
60-
}
61-
62-
// Handle Inspector Changes
63-
private void OnValidate()
64-
{
65-
SetupEditorData();
66-
var obj = gameObject;
67-
AddAll();
68-
69-
for (int i = 0; i < _all.Length; i++)
70-
{
71-
var tag = _all[i];
72-
73-
if (ArrayUtility.Contains(_tags, tag))
74-
{
75-
if (!obj.HasTag(tag))
76-
obj.AddTag(tag);
77-
}
78-
else
79-
{
80-
if (obj.HasTag(tag))
81-
obj.RemoveTag(tag);
82-
}
83-
}
84-
}
85-
86-
private void SetupEditorData()
87-
{
88-
if (_all == null)
89-
_all = Resources.FindObjectsOfTypeAll<Tag>();
90-
91-
if (_tags == null)
92-
{
93-
_tags = new Tag[0];
94-
}
95-
else
96-
{
97-
for (int i = _tags.Length - 1; i >= 0; i--)
98-
{
99-
var tag = _tags[i];
100-
101-
if (tag == null)
102-
ArrayUtility.RemoveAt(ref _tags, i);
103-
}
104-
}
105-
106-
if (_hash == 0)
107-
_hash = gameObject.GetHashCode();
108-
}
109-
#endif
25+
_instance.RemoveTags(_tags);
11026
}
11127
}
11228

Runtime/Taggable.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/TagsContainer.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,20 @@ public sealed class TagsContainer : ScriptableObject
1313
{
1414
[SerializeField] private Tag[] _tags = null;
1515

16-
public bool HasEntity(GameObject entity, bool allRequired) =>
17-
entity.HasTags(_tags, allRequired);
16+
public void Add(GameObject instance)
17+
{
18+
for (int i = 0; i < _tags.Length; i++)
19+
_tags[i].Add(instance);
20+
}
21+
22+
public void Remove(GameObject instance)
23+
{
24+
for (int i = 0; i < _tags.Length; i++)
25+
_tags[i].Remove(instance);
26+
}
27+
28+
public bool HasInstance(GameObject instance, bool allRequired) =>
29+
instance.HasTags(_tags, allRequired);
1830
}
1931
}
2032

Runtime/TagsContainer.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)