如何根据组件的属性过滤游戏对象?

时间:2019-12-23 14:57:17

标签: c# unity3d

enter image description here 我目前有一个玩家的“感知能力”,可以通过 Animation animation; AnimationController animationController; HomeScreenState(); @override void initState() { super.initState(); animationController = AnimationController(vsync: this,duration: Duration(seconds: 1),/*lowerBound,upperBound*/); animationController.addListener((){ if(animationController.isCompleted){ animationController.reverse(); } else if(animationController.isDismissed){ animationController.forward(); } setState(() { }); }); animationController.forward(/*from:*/); } @override Widget build(BuildContext context) { animation = CurvedAnimation(parent: animationController, curve: Curves.easeInOut); animation = Tween(begin: -0.5,end: 0.5).animate(animation); //other code

检测附近的敌人

敌人有一个具有其一般属性的成分:

Physics2D.OverlapCircleAll()

现在我想基于属性using UnityEngine; public class EnemyProperties : MonoBehaviour { public WorldColors color; public bool hookable; public bool isLast; }

将那些敌人过滤掉

到目前为止,我设法根据组件对它们进行过滤:

hookable == true
public static void GetObjectsWithComponent(Transform srcTransform, float checkRadius, LayerMask checkLayers, Type myType)
{
    Collider2D[] colliders = Physics2D.OverlapCircleAll(srcTransform.position, checkRadius, checkLayers);
    Collider2D[] collidersWithComponent = Array.FindAll(colliders, collider => collider.gameObject.TryGetComponent(myType, out Component component));
    // Collider2D[] collidersWithComponentAttribute = ??
}

如何基于布尔private void Update() { Sense.GetObjectsWithComponent(this.transform, checkRadius, checkMask, typeof(EnemyProperties)); } 进一步过滤它们?

2 个答案:

答案 0 :(得分:4)

您可以使用C#泛型和Linq使您的生活更轻松...

Number

并在更新中:

public static IEnumerable<TType> GetComponentsWithAttributeInCircle<TType>(Transform srcTransform, float checkRadius, LayerMask checkLayers, Func<TType, bool> filter)
{
    Collider2D[] colliders = Physics2D.OverlapCircleAll(srcTransform.position, checkRadius, checkLayers);
    IEnumerable<TType> colliderWithComponentAttribute = colliders.Select(collider => collider.gameObject.GetComponent<TType>()).Where(component => component != null).Where(filter);
    return colliderWithComponentAttribute;
}

作为对您的其他评论的评论,Linq已经相当通用。如果您学会使用它,则可以立即设置像这样的简单过滤器。并且它与编译时间类型一起很好地工作。如果您想在不编译类型信息的情况下做同样的事情,则必须使用反射。

反射通常很慢,而且不容易理解,因此,如果您坚持使用Linq和泛型,可能会做得更好。

答案 1 :(得分:0)

Array类的方法FindAll的原型如下:

public static T[] FindAll<T> (T[] array, Predicate<T> match);

因此,第二个参数实际上是一个函数或lambda。 match参数需要返回一个布尔值。如果返回true,则将元素添加到结果数组中。如果返回false,则不会。

因此,您可以使用&&运算符来过滤组件EnemyProperties hookable == true

它看起来像这样:

Collider2D[] collidersWithComponent = Array.FindAll(colliders, collider => (collider.gameObject.TryGetComponent(myType, out Component component) && collider.gameObject.GetComponent<EnemyProperties>().hookable == true));