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

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

但是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

新建一个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分别为tag1tag2tag1

TagManager只有tag1

运行

但是这样当退出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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Unity 实现给物体动态添加事件

    介绍一个方法给物体动态的添加事件(点击 拖拽等) using System.Events; using System.EventSystems; //_go is the gameobject which need add event //_go 是物体,因为EventTrigger是unity中的一个组件,我们要用添加组件的方式来给物体添加事件触发组件 //_type is the EventTriggerType(point , drag , clickdown...... //_type

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

    在unity中,我们经常通过给物体添加标签来判断这个物体是不是我们想要的 但是unity默认只能添加一个标签,那如果我们要给一个物体添加多个标签应该怎么办 首先,我们定义一个Tag.cs类,这个类用来存储物体的tag信息 public class Tags : MonoBehaviour{ public List<string> tags=new List<string>(); } 然后创建一个单例类TagManager.cs用来管理tag public class TagMana

  • Unity实现物体沿自身的任意轴向旋转

    本文实例为大家分享了Unity实现物体沿任意轴向旋转,供大家参考,具体内容如下 一.创建一个需要旋转的物体 二.编写控制该物体的脚本 using UnityEngine; using System.Collections; public class Test_ElectricFan : MonoBehaviour { public bool isOpen=false; //是否开始旋转 public int speed=2; //旋转的速度 // Use this for initializat

  • Unity实现物体跟随鼠标移动

    本文实例为大家分享了Unity实现物体跟随鼠标移动的具体代码,供大家参考,具体内容如下 相关函数 Vector3.Lerp 线性插值C# => static Vector3 Lerp(Vector3 from, Vector3 to, float t); Vector3.MoveTpwards 移向C# => static function MoveTowards(current: Vector3, target: Vector3, maxDistanceDelta: float): Vect

  • Unity实现物体左右移动效果

    本文实例为大家分享了Unity实现物体左右移动效果的具体代码,供大家参考,具体内容如下 效果如下 代码: using UnityEngine; using System.Collections; //Add this script to the platform you want to move. //左右移动的平台 public class MovingPlatform : MonoBehaviour { //Platform movement speed.平台移动速度 public floa

  • unity实现物体延时出现

    本文实例为大家分享了unity实现物体延时出现的具体代码,供大家参考,具体内容如下 新建一个cube和plane,隐藏cube,脚本挂在plane上. 1. update计时器实现 using System.Collections; using System.Collections.Generic; using UnityEngine; //一个隐藏的物体等待t秒后显示,updata计时器实现 public class activeShow : MonoBehaviour { public Ga

  • Unity实现物体运动时画出轨迹

    本文实例为大家分享了Unity实现物体运动时画出轨迹的具体代码,供大家参考,具体内容如下 1.新建空物体,上赋LineRenderer 2.新建空物体,把轨迹画出来,设计和脚本. 3.LineMark的脚本是 using System.Collections; using System.Collections.Generic; using UnityEngine; public class LineMark : MonoBehaviour { private GameObject clone;

  • Unity脚本自动添加头部注释的全过程

    目录 Unity脚本自动添加头部注释 1. 修改Unity模板 2. 通过代码修改为动态的 结语 Unity脚本自动添加头部注释 就是创建.cs文件时自动添加作者名,创建时间,文件名等 看示例,我们在Unity的project面板下先创建一个Scripts文件夹,然后在Scripts文件夹下创建一个脚本,命名为:Test.cs 然后就是这样: 因为这个是我已经成功的设置过了才会有这样的头部注释 1. 修改Unity模板 首先找到你的Unity的安装路径,找到这样的文件夹,文件名字是和版本相关的

  • Unity为软件添加使用有效期的具体步骤

    功能需求:为软件设定一个使用有效期,当超过指定时间后,程序无法运行. 实现思路:定义一个常量,用于记录一个时间,我们称之为标记时间,使用当前时间减去标记时间,如果时间间隔大于设定的有效期,退出程序. 具体步骤: 1.定义标记时间常量: //标记时间 private const string flag = "2022-03-17 17:11:25"; 使用DateTime.Parse可将其转换为DateTime类型: DateTime flagTime = DateTime.Parse(

  • Unity实现物体运动轨迹的绘制

    本文实例为大家分享了unity物体运动轨迹绘制的具体代码,供大家参考,具体内容如下 ① create empty,命名为LineRender ② 在Assects中新建材质,选择Shader为Sprites/Default,并设置轨迹颜色,如下图: ③ 选择①中创建的object,添加Line Render属性,然后将②中新建的材质赋给该object,如下图: 展开Line Render,拖动Width可设置轨迹宽度 ④ 创建c#脚本,拖至运动物体上,代码如下: using System.Col

  • Unity实现物体弧线运动到规定的坐标

    本文实例为大家分享了Unity实现以弧线的形式运动到规定坐标的具体代码,供大家参考,具体内容如下 1.u3d场景的设置 2. Run 脚本 using UnityEngine; using System.Collections; public class Run : MonoBehaviour { public GameObject target; //要到达的目标 public float speed = 10; //速度 private float distanceToTarget; //两

随机推荐