question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] A few questions about usage and typical setup

See original GitHub issue

– Edit: It feels like something is missing from this package to tie it all together. Did you perhaps forget to upload something? I have been checking your other repos that you have, and I see one of them has a TagCreator, a TagType, and an interface called IBranch (in which I can’t find the actual implementation anyhere) that this repo doesn’t have. I cannot figure out how I am supposed to reference the actual tags in code to check, add, remove them, etc aside from manually placing them into the container or onto a GameObject that has the taggable class.

Hey there, I came across this and thought it sounded like really good idea, especially for my use case of checking tags on hundreds of waypoints in the editor to draw different things for my waypoint tools. I am trying to piece together exactly how to use it, though. I would venture a guess that I need to modify it slightly, probably adding [ExecuteInEditMode] for some of it to work in the editor.

I took the included “New Tag” and called it “Waypoint”, added it in the TagContainer, added the “Taggable” script to a waypoint and then added the Waypoint tag object to it. I had a few questions from here, though.

My first one is, I see that there is the ability to make multiple tag containers, and there is a HasTags method that takes in a container, which looks like it checks the container for an entity. What is an example scenario in which you might use multiple containers? Do you reuse the already created tags within multiple containers? If so, it sort of sounds like ECS’s Archetypes.

My second question is, do you have a quick example of the proper use to check/add tags? My first instinct was to do waypointList[i].GetComponent<Taggable>() as I was looping through my waypoints but I feel like that sort of defeats the purpose and I could just check for my Waypoint class that is already there, so I would imagine there is a different/better way to do this that I am just not aware of? I tried to do

TagExtensions.HasTag(waypointList[i].gameObject, ?? );

I am not sure exactly where I am supposed to get the reference to a specific tag from, in order to pass it in?

I definitely appreciate your work on this, I am excited to see if it might help out a bit on performance instead of checking all of the normal built-in tags. Thanks for your time, -MH

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:14 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
IntoTheDevcommented, Jul 31, 2020

Install the package again and change the code of these scripts. I hope this helps.

Taggable

using Sirenix.OdinInspector;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace ToolBox.Tags
{
	[DisallowMultipleComponent]
	public sealed class Taggable : MonoBehaviour
	{
		[SerializeField, Required, AssetList] private Tag[] _tags = default;

		private int _hash = 0;

		private void Awake() =>
			_hash = gameObject.GetHashCode();

#if UNITY_EDITOR
		private void OnValidate()
		{
			var obj = gameObject;

			if (!obj.activeInHierarchy)
				return;

			int hash = obj.GetHashCode();
			for (int i = 0; i < _tags.Length; i++)
				_tags[i].Add(hash);
		}

		private void OnDestroy()
		{
			int hash = gameObject.GetHashCode();

			for (int i = 0; i < _tags.Length; i++)
				_tags[i].Remove(hash);
		}
#endif

		private void OnEnable()
		{
			for (int i = 0; i < _tags.Length; i++)
				_tags[i].Add(_hash);
		}

		private void OnDisable()
		{
			for (int i = 0; i < _tags.Length; i++)
				_tags[i].Remove(_hash);
		}

#if UNITY_EDITOR
		public void UpdateTags()
		{
			var tags = Resources.FindObjectsOfTypeAll<Tag>();
			int hash = gameObject.GetHashCode();

			foreach (var tag in tags)
			{
				bool hasTag = tag.HasEntity(hash);
				bool inArray = ArrayUtility.Contains(_tags, tag);

				if (!hasTag && inArray)
				{
					ArrayUtility.Remove(ref _tags, tag);
					continue;
				}

				if (hasTag && !inArray)
				{
					ArrayUtility.Add(ref _tags, tag);
					continue;
				}
			}
		}
#endif
	}
}

TagEditor

using Sirenix.OdinInspector;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace ToolBox.Tags
{
	[InitializeOnLoad]
	public class TagEditor
	{
		static TagEditor() =>
			Selection.selectionChanged += OnSelectionChanged;

		public static void OnSelectionChanged()
		{
			var obj = Selection.activeGameObject;

			if (obj == null)
				return;

			var taggable = obj.GetComponent<Taggable>();

			if (taggable != null)
				taggable.UpdateTags();
		}
	}
}

Tag

using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;

namespace ToolBox.Tags
{
	[CreateAssetMenu(menuName = "ToolBox/Tagging/Tag"), AssetSelector, Required]
	public sealed class Tag : ScriptableObject
	{
		[ShowInInspector, ReadOnly] private HashSet<int> _entities = new HashSet<int>();

		public void Add(int entity)
		{
			_entities.Add(entity);

#if UNITY_EDITOR
			TagEditor.OnSelectionChanged();
#endif
		}

		public void Remove(int entity)
		{
			_entities.Remove(entity);

#if UNITY_EDITOR
			TagEditor.OnSelectionChanged();
#endif
		}

		public bool HasEntity(int entity) =>
			_entities.Contains(entity);
	}
}


1reaction
MostHatedcommented, Aug 2, 2020

I figured out something else that was causing me issues which I didn’t realize at the time. I figured it might be a good idea to share it, just in case anyone else runs into something similar down the road.

My waypoints are all prefab variants and I am using Addressables, so a lot of my things are connected at the underlying prefab original level via AssetReferences, then the GameObjects are assigned to each other via script by finding the AssetReference’s instance.

I am assigning things programmatically, such as which tags the waypoints are supposed to have (if it’s a vehicle or pedestrian waypoint, etc) based on which waypoint container (unrelated to TagContainer) the waypoints are a child of, but when editing the waypoints I use a Scope asset that adds some convenience functions:

 using (var prefab = new LoadPrefabContentsScope(path))
{
	... edit prefab here
}
Scoped prefab editing
public sealed class LoadPrefabContentsScope : IDisposable
	{
		public string     PrefabPath { get; }
		public GameObject Prefab     { get; }

		public bool IsSave { get; set; } = true;

		public LoadPrefabContentsScope( string prefabPath )
		{
			PrefabPath = prefabPath;
			Prefab     = PrefabUtility.LoadPrefabContents( prefabPath );
		}

		public void Dispose()
		{
			if ( IsSave )
			{
				PrefabUtility.SaveAsPrefabAsset( Prefab, PrefabPath );
			}

			PrefabUtility.UnloadPrefabContents( Prefab );
		}
	}

Because of this, for some reason, whenever I was adding tags/containers to the prefab asset, the objects that were supposed to be selected/added to the _tags AssetList didn’t get saved to the original prefab. I would run my assignments and at the time the prefab instances being used would work just fine, but the waypoints original prefab asset would show zero items selected/in the _tags array, some of them might have one, when all of them should have had two, so when they would get reloaded next time, it would not have the correct tags/containers.

I removed AssetList and made a few other small changes, which then allowed the array to be properly updated on the original prefab, which then allowed the actual waypoint instances being used to have all of the proper tags and containers.

Read more comments on GitHub >

github_iconTop Results From Across the Web

31 Situational Interview Questions (With Example Answers)
Here are five situational interview questions and sample answers you can use to help craft your responses. 1. What would you do if...
Read more >
28 Questionnaire Examples, Questions, & Templates to ...
What makes a good questionnaire? Define the Goal; Make it Short and Simple; Use a Mix of Question Types; Proofread Carefully; Keep it...
Read more >
Good Survey Questions & Examples—Best Practices & Tips
Open up a conversation with this question. These are good survey questions to get more meaningful answers from as people have the opportunity...
Read more >
15 Questions About Remote Work, Answered
How should corporate leaders, managers, and individual workers shift to remote work in the midst of the coronavirus pandemic?
Read more >
Survey Questions: Tips & Examples in 2022
Typically, these last questions include demographic and other classification questions. 2. Use “Ringer” questions. In social settings, are you more introverted ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found