Răsfoiți Sursa

增加ECS多组件筛选功能

tanghai 7 ani în urmă
părinte
comite
feb5676b86

+ 8 - 8
Unity/Assets/Scripts/Base/Object/Entity.cs

@@ -52,7 +52,7 @@ namespace ETModel
 			this.componentDict.Clear();
 		}
 		
-		public Component AddComponent(Component component)
+		public virtual Component AddComponent(Component component)
 		{
 			Type type = component.GetType();
 			if (this.componentDict.ContainsKey(type))
@@ -70,7 +70,7 @@ namespace ETModel
 			return component;
 		}
 
-		public Component AddComponent(Type type)
+		public virtual Component AddComponent(Type type)
 		{
 			if (this.componentDict.ContainsKey(type))
 			{
@@ -87,7 +87,7 @@ namespace ETModel
 			return component;
 		}
 
-		public K AddComponent<K>() where K : Component, new()
+		public virtual K AddComponent<K>() where K : Component, new()
 		{
 			Type type = typeof (K);
 			if (this.componentDict.ContainsKey(type))
@@ -105,7 +105,7 @@ namespace ETModel
 			return component;
 		}
 
-		public K AddComponent<K, P1>(P1 p1) where K : Component, new()
+		public virtual K AddComponent<K, P1>(P1 p1) where K : Component, new()
 		{
 			Type type = typeof (K);
 			if (this.componentDict.ContainsKey(type))
@@ -123,7 +123,7 @@ namespace ETModel
 			return component;
 		}
 
-		public K AddComponent<K, P1, P2>(P1 p1, P2 p2) where K : Component, new()
+		public virtual K AddComponent<K, P1, P2>(P1 p1, P2 p2) where K : Component, new()
 		{
 			Type type = typeof (K);
 			if (this.componentDict.ContainsKey(type))
@@ -141,7 +141,7 @@ namespace ETModel
 			return component;
 		}
 
-		public K AddComponent<K, P1, P2, P3>(P1 p1, P2 p2, P3 p3) where K : Component, new()
+		public virtual K AddComponent<K, P1, P2, P3>(P1 p1, P2 p2, P3 p3) where K : Component, new()
 		{
 			Type type = typeof (K);
 			if (this.componentDict.ContainsKey(type))
@@ -159,7 +159,7 @@ namespace ETModel
 			return component;
 		}
 
-		public void RemoveComponent<K>() where K : Component
+		public virtual void RemoveComponent<K>() where K : Component
 		{
 			if (this.IsDisposed)
 			{
@@ -178,7 +178,7 @@ namespace ETModel
 			component.Dispose();
 		}
 
-		public void RemoveComponent(Type type)
+		public virtual void RemoveComponent(Type type)
 		{
 			if (this.IsDisposed)
 			{

+ 16 - 0
Unity/Assets/Scripts/Module/Filter/FilterAttribute.cs

@@ -0,0 +1,16 @@
+using System;
+
+namespace ETModel
+{
+	[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+	public class FilterAttribute: BaseAttribute
+	{
+		// 指定管理器的类型名
+		public string ManagerTypeName { get; }
+
+		public FilterAttribute(string managerTypeName)
+		{
+			this.ManagerTypeName = managerTypeName;
+		}
+	}
+}

+ 150 - 0
Unity/Assets/Scripts/Module/Filter/FilterComponent.cs

@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using MongoDB.Bson.Serialization.Attributes;
+
+namespace ETModel
+{
+	[ObjectSystem]
+	public class FilterAwakeSystem : AwakeSystem<FilterComponent>
+	{
+		public override void Awake(FilterComponent self)
+		{
+			self.Load();
+		}
+	}
+
+	[ObjectSystem]
+	public class FilterLoadSystem : LoadSystem<FilterComponent>
+	{
+		public override void Load(FilterComponent self)
+		{
+			self.Load();
+		}
+	}
+	
+	
+	[BsonIgnoreExtraElements]
+	public class FilterComponent: Component
+	{
+		// 一个Filter过滤了哪些组件
+		public UnOrderMultiMap<string, Type> filterComponets = new UnOrderMultiMap<string, Type>();
+		
+		// 一个组件被哪些Filter过滤
+		public UnOrderMultiMap<Type, string> componentFilters = new UnOrderMultiMap<Type, string>();
+		
+		
+		
+		// 满足该Filter的所有entity
+		public UnOrderMultiMap<string, Entity> filterEntitys = new UnOrderMultiMap<string, Entity>();
+		
+		// 一个entity满足哪些Filter
+		public UnOrderMultiMap<Entity, string> entityFilters = new UnOrderMultiMap<Entity, string>();
+
+		// 尽量不要在服务端热更增加或减少Filter
+		public void Load()
+		{
+			this.filterComponets.Clear();
+			this.componentFilters.Clear();
+
+			Type parentType = this.Parent.GetType();
+			List<Type> types = Game.EventSystem.GetTypes(typeof(FilterAttribute));
+			foreach (Type type in types)
+			{
+				object[] attrs = type.GetCustomAttributes(typeof(FilterAttribute), false);
+				if (attrs.Length == 0)
+				{
+					continue;
+				}
+				
+				FilterAttribute filterAttribute = attrs[0] as FilterAttribute;
+				if (filterAttribute.ManagerTypeName != parentType.Name)
+				{
+					continue;
+				}
+				
+				string filterName = type.Name;
+				IFilter filter = Activator.CreateInstance(type) as IFilter;
+				if (filter == null)
+				{
+					Log.Error($"filterSystem: {type.Name} 需要继承 IFilterSystem");
+					continue;
+				}
+
+				foreach (Type filterComponent in filter.GetFilter())
+				{
+					this.filterComponets.Add(filterName, filterComponent);
+					this.componentFilters.Add(filterComponent, filterName);
+				}
+			}
+		}
+
+		// 热更后挂载Filter的管理器需要清理FilterComponent,重新add entity进来
+		public void Clear()
+		{
+			this.filterEntitys.Clear();
+			this.entityFilters.Clear();
+		}
+
+		public List<Entity> GetByFilter(Type type)
+		{
+			List<Entity> list = this.filterEntitys[type.Name];
+			return list;
+		}
+
+		public void Add(Entity entity)
+		{
+			foreach (var kv in this.filterComponets.GetDictionary())
+			{
+				string systemType = kv.Key;
+				bool hasAllComponents = true;
+				foreach (Type type in kv.Value)
+				{
+					if (entity.GetComponent(type) != null)
+					{
+						continue;
+					}
+
+					hasAllComponents = false;
+					break;
+				}
+
+				if (!hasAllComponents)
+				{
+					continue;
+				}
+
+				this.filterEntitys.Add(systemType, entity);
+				this.entityFilters.Add(entity, systemType);
+			}
+		}
+
+		public void Remove(Entity entity)
+		{
+			List<string> systemTypes = this.entityFilters[entity];
+			foreach (string systemType in systemTypes)
+			{
+				this.filterEntitys[systemType].Remove(entity);
+			}
+		}
+
+		public void OnRemoveComponent(Entity entity, Type componentType)
+		{
+			List<string> systemTypes = this.componentFilters[componentType];
+			foreach (string systemType in systemTypes)
+			{
+				this.filterEntitys.Remove(systemType, entity);
+				this.entityFilters.Remove(entity, systemType);
+			}
+		}
+		
+		public void OnAddComponent(Entity entity, Type componentType)
+		{
+			List<string> systemTypes = this.componentFilters[componentType];
+			foreach (string systemType in systemTypes)
+			{
+				this.filterEntitys.Add(systemType, entity);
+				this.entityFilters.Add(entity, systemType);
+			}
+		}
+	}
+}

+ 54 - 0
Unity/Assets/Scripts/Module/Filter/FilterEntity.cs

@@ -0,0 +1,54 @@
+using System;
+
+namespace ETModel
+{
+    public class FilterEntity: Entity
+    {
+        public override Component AddComponent(Component component)
+        {
+            base.AddComponent(component);
+            this.Parent.GetParent<FilterComponent>().OnAddComponent(this, component.GetType());
+            return component;
+        }
+
+        public override K AddComponent<K>()
+        {
+            Component component = base.AddComponent<K>();
+            this.Parent.GetParent<FilterComponent>()?.OnAddComponent(this, component.GetType());
+            return (K)component;
+        }
+
+        public override K AddComponent<K, P1>(P1 p1)
+        {
+            Component component = base.AddComponent<K, P1>(p1);
+            this.Parent.GetParent<FilterComponent>()?.OnAddComponent(this, component.GetType());
+            return (K)component;
+        }
+        
+        public override K AddComponent<K, P1, P2>(P1 p1, P2 p2)
+        {
+            Component component = base.AddComponent<K, P1, P2>(p1, p2);
+            this.Parent.GetParent<FilterComponent>()?.OnAddComponent(this, component.GetType());
+            return (K)component;
+        }
+
+        public override K AddComponent<K, P1, P2, P3>(P1 p1, P2 p2, P3 p3)
+        {
+            Component component = base.AddComponent<K, P1, P2, P3>(p1, p2, p3);
+            this.Parent.GetParent<FilterComponent>()?.OnAddComponent(this, component.GetType());
+            return (K)component;
+        }
+
+        public override void RemoveComponent(Type type)
+        {
+            base.RemoveComponent(type);
+            this.Parent.GetParent<FilterComponent>()?.OnRemoveComponent(this, type);
+        }
+
+        public override void RemoveComponent<K>()
+        {
+            base.RemoveComponent<K>();
+            this.Parent.GetParent<FilterComponent>()?.OnRemoveComponent(this, typeof(K));
+        }
+    }
+}

+ 49 - 0
Unity/Assets/Scripts/Module/Filter/IFilter.cs

@@ -0,0 +1,49 @@
+using System;
+
+namespace ETModel
+{
+    public interface IFilter
+    {
+        Type[] GetFilter();
+    }
+    
+    public abstract class AFilter<A>: IFilter
+    {
+        public Type[] GetFilter()
+        {
+            return new[] { typeof (A) };
+        }
+    }
+    
+    public abstract class AFilter<A, B>: IFilter
+    {
+        public Type[] GetFilter()
+        {
+            return new[] { typeof (A), typeof(B) };
+        }
+    }
+    
+    public abstract class AFilter<A, B, C>: IFilter
+    {
+        public Type[] GetFilter()
+        {
+            return new[] { typeof (A), typeof(B), typeof(C) };
+        }
+    }
+    
+    public abstract class AFilter<A, B, C, D>: IFilter
+    {
+        public Type[] GetFilter()
+        {
+            return new[] { typeof (A), typeof(B), typeof(C), typeof(D) };
+        }
+    }
+    
+    public abstract class AFilter<A, B, C, D, E>: IFilter
+    {
+        public Type[] GetFilter()
+        {
+            return new[] { typeof (A), typeof(B), typeof(C), typeof(D), typeof(E) };
+        }
+    }
+}

+ 4 - 0
Unity/Unity.csproj

@@ -362,6 +362,10 @@
     <Compile Include="Assets\Scripts\Module\Config\ConfigComponent.cs" />
     <Compile Include="Assets\Scripts\Module\Config\ConfigHelper.cs" />
     <Compile Include="Assets\Scripts\Module\Config\IConfig.cs" />
+    <Compile Include="Assets\Scripts\Module\Filter\FilterComponent.cs" />
+    <Compile Include="Assets\Scripts\Module\Filter\FilterAttribute.cs" />
+    <Compile Include="Assets\Scripts\Module\Filter\FilterEntity.cs" />
+    <Compile Include="Assets\Scripts\Module\Filter\IFilter.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\AnimatorComponent.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\CameraComponent.cs" />
     <Compile Include="Assets\Scripts\Module\FrameSync\ClientFrameComponent.cs" />