服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - Unity给物体添加多个Tag的实现

Unity给物体添加多个Tag的实现

2022-11-15 14:22legroft C#

这篇文章主要介绍了Unity给物体添加多个Tag的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在unity中,我们经常通过给物体添加标签来判断这个物体是不是我们想要的

Unity给物体添加多个Tag的实现

但是unity默认只能添加一个标签,那如果我们要给一个物体添加多个标签应该怎么办

首先,我们定义一个Tag.cs类,这个类用来存储物体的tag信息

public class Tags : MonoBehaviour{
    public List<string> tags=new List<string>();
}

然后创建一个单例类TagManager.cs用来管理tag

public class TagManager : MonoBehaviour {
   public static TagManager Instance { get; private set; }
   private void Awake() {
      if (Instance == null) {
         Instance = (TagManager) this;
         DontDestroyOnLoad(gameObject);
      }
      else {
         Destroy(gameObject);
      }
   }
}

在TagManager中增加存储tag的list和对应物体的dictionary

public List<string> tagsList = new List<string>();
[ShowInInspector]
public Dictionary<string, List<GameObject>> tagsDictionary = new Dictionary<string, List<GameObject>>();

但是inspector窗口中修改dictionary中的值后,播放时会自动清除数据,所以还要给dictionary赋值

private void InitTags() {
   int length = tagsList.Count;
   tagsDictionary = new Dictionary<string, List<GameObject>>(length);
   for (int i = 0; i < length; i++) {
      tagsDictionary.Add(tagsList[i], new List<GameObject>());
   }
}

然后我们通过在inspector窗口修改list来修改物体的taf

Unity给物体添加多个Tag的实现

新建一个Extensions.cs,我们在这个类里面写一些扩展方法

public static class Extensions {
   //包含所有的 tag 返回true
   public static bool HasTag(this GameObject gameObject, params string[] tag) {
      if (gameObject.TryGetComponent<Tags>(out Tags t)) {
         for (int i = 0; i < tag.Length; i++) {
            if (!t.tags.Contains(tag[i])) {
               Debug.Log(gameObject.name+"不存在"+tag+"标签");
               return false;
            }
         }
      }
      return true;
   }
   //给物体增加 tag
   public static void AddTag(this GameObject gameObject, params string[] tags) {
      if (gameObject.TryGetComponent<Tags>(out Tags t)) {
         foreach (var tag in tags) {
            if (!TagManager.Instance.tagsList.Contains(tag)) {
               Debug.Log("增加一个tag:" + tag);
               TagManager.Instance.tagsDictionary.Add(tag, new List<GameObject>());
               Debug.Log(tag + "增加一个物体" + gameObject.name);
               TagManager.Instance.tagsDictionary[tag].Add(gameObject);
            }
            else {
               Debug.Log(tag + "增加一个物体" + gameObject.name);
               TagManager.Instance.tagsDictionary[tag].Add(gameObject);
            }
         }
      }
   }
   //给物体删除tag
	public static void RemoveTag(this GameObject gameObject,params string[] tags) {
		for (int i = 0; i < tags.Length; i++) {
			if (gameObject.HasTag(tags[i])) {
				gameObject.GetComponent<Tags>().tags.Remove(tags[i]);
				Debug.Log(gameObject.name+"移除"+tags+"标签");
				TagManager.Instance.tagsDictionary[tags[i]].Remove(gameObject);
			}
			else {
				Debug.LogWarning(gameObject.name+"不存在"+tags[i]+"标签");
			}
		}
	}
}

这样像下面这样直接调用即可

gameObject.AddTag("Player","Tag1");
gameObject.HasTag("Player","Tag1");
gameObject.RemoveTag("Player");

最后TagManager.cs中通过标签获取所有物体

public List<GameObject> FindObjsWithTag(string tag) {
    if (tagsDictionary.ContainsKey(tag)) {
        return tagsDictionary[tag];
    }
    Debug.Log("不存在标签为" + tag + "的物体");
    return null;
}

测试一下

创建两个挂有Tags.cs脚本的物体

public class Tags : MonoBehaviour{
    public List<string> tags=new List<string>();
    void Start() {
        gameObject.AddTag(tags.ToArray());
        gameObject.HasTag("Player");
    }
    void Update(){
        if (Input.GetKeyDown(KeyCode.A)) {
            gameObject.RemoveTag("Player","tag1");
        }
    }
}

两个物体具有的tag分别为tag1,tag2和tag1

TagManager只有tag1

Unity给物体添加多个Tag的实现

运行

Unity给物体添加多个Tag的实现

但是这样当退出Play模式后,List中的数据会被清空,所以可以使用ScriptableObject进行持久化存储也可以使用Odin等插件直接对字典进行序列化

使用ScriptableObject

新建一个TagsAsset.cs

[CreateAssetMenu]
public class TagsAsset : ScriptableObject{
    public List<string> tags=new List<string>();
}

将原先代码中tagsList相关的代码修改为tagsAsset.tags并修缮一下即可

使用Odin

导入Odin插件,使TagManager继承自SerializedMonoBehaviour

[NonSerialized, OdinSerialize]
public Dictionary<string, List<GameObject>> tagsDictionary = new Dictionary<string, List<GameObject>>();

关于Odin的进阶可以看https://zhuanlan.zhihu.com/p/268324619

到此这篇关于Unity给物体添加多个Tag的实现的文章就介绍到这了,更多相关Unity 物体添加多个Tag内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_25969985/article/details/116064238

延伸 · 阅读

精彩推荐
  • C#C#对Windows服务组的启动与停止操作

    C#对Windows服务组的启动与停止操作

    这篇文章主要为大家详细介绍了C#对Windows服务组的启动与停止操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    马洪彪10432022-02-21
  • C#C#中的虚方法和抽象方法的运用

    C#中的虚方法和抽象方法的运用

    这篇文章主要介绍了C#中的虚方法和抽象方法的运用,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    微笑在嘴边7212022-09-28
  • C#谈一谈autofac组件的实例范围

    谈一谈autofac组件的实例范围

    这篇文章主要和大家聊一聊autofac组件的实例范围,探讨autofac组件的实例范围,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    东北风!3902021-12-09
  • C#C# Winform 子窗体访问父级窗体的控件和属性

    C# Winform 子窗体访问父级窗体的控件和属性

    本文主要介绍两种子窗体访问父窗体控件和属性的方法,大家可以参考一下,本人比较偏向第二种,把父窗体作为属性传递,一劳永逸,想访问父窗体的什...

    xch_yang10102021-11-19
  • C#C#泛型设计需要注意的一个小陷阱

    C#泛型设计需要注意的一个小陷阱

    这篇文章主要给大家介绍了关于C#泛型设计需要注意的一个小陷阱,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    詹姆斯.辛11232022-07-11
  • C#C#实现Windows Form调用R进行绘图与显示的方法

    C#实现Windows Form调用R进行绘图与显示的方法

    众所周知R软件功能非常强大,可以很好的进行各类统计,并能输出图形。下面介绍一种R语言和C#进行通信的方法,并将R绘图结果显示到WinForm UI界面上的方...

    JackWang-CUMT8882021-12-27
  • C#C# 实现Table的Merge,Copy和Clone

    C# 实现Table的Merge,Copy和Clone

    这篇文章主要介绍了C# 实现Table的Merge,Copy和Clone,帮助大家更好的利用c#处理文件,感兴趣的朋友可以了解下...

    農碼一生6092022-10-21
  • C#C#实现JSON字符串序列化与反序列化的方法

    C#实现JSON字符串序列化与反序列化的方法

    在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象。...

    笨笨丁6212021-12-18