c# - 只初始化一次变量,而函数多次调用自己
问题描述
这个函数多次调用自己——找到一个游戏对象的子对象,然后再次将该对象传递给它自己。
我想返回遍历时找到的游戏对象列表。我无法在函数本身中初始化列表,因为我只需要初始化一次。当多次调用它时,它将重新初始化。
关于如何获取已获取对象列表的任何想法?
public static List<GameObject> FindAllGameObjectsInGameObject<T>(GameObject gameObjectToTraverse)
{
List<GameObject> list;
foreach (Transform child in gameObjectToTraverse.transform)
{
if (list == null)
{
list = new List<GameObject>();
}
list.Add(child.gameObject);
FindAllGameObjectsInGameObject<T>(child.gameObject);
}
}
解决方案
与其自己做递归,为什么不简单地使用GameObject.GetComponentsInChildren
返回 GameObject 或其任何子对象中 Type 类型的所有组件。
Unity 在子游戏对象上递归搜索组件。这意味着它还包括目标 GameObject 的所有子 GameObject,以及所有后续子 GameObject。
并做例如
using System.Linq;
接着
public static List<GameObject> FindAllGameObjectsInGameObject(GameObject gameObjectToTraverse)
{
// This already gives you ALL transform components anywhere nested
// under the given object including inactive and disabled ones
// INCLUDING the given object itself
var allChildTransforms = gameObjectToTraverse.GetComponentsInChildren<Transform>(true);
// This uses Linq to rather get all the according GameObjects
// See https://docs.microsoft.com/dotnet/api/system.linq.enumerable.select
var allChildGameObjects = allChildTransforms.Select(t => t.gameObject);
// Optional if you don't want to return the original given object itself
// See https://docs.microsoft.com/dotnet/api/system.linq.enumerable.where
var onlyChildGameObjects = allChildGameObjects.Where(c => c!= gameObjectToTraverse);
return onlyChildGameObjects.ToList();
}
忘记递归,因为 Unity 已经为你做了它;)
那么实际上泛型参数是做什么T
用的呢?您可能想在第一次通话中使用它
var allChildComponents = gameObjectToTraverse.GetComponentsInChildren<T>(true);
为了宁愿只获得具有T
附加类型组件的对象。
只是为了实际回答您的尝试:您可以使用可选参数,例如
public static List<GameObject> FindAllGameObjectsInGameObject(GameObject gameObjectToTraverse, List<GameObject> list = new List<GameObject>())
{
foreach (Transform child in gameObjectToTraverse.transform)
{
list.Add(child.gameObject);
FindAllGameObjectsInGameObject(child.gameObject, list);
}
}
所以当你第一次调用它时,你就这样做
var objs = FindAllGameObjectsInGameObject(objectToTraverse);
在这种情况下,会自动创建一个新列表作为第二个参数。然后它在递归调用中在内部传递。
或者你可以稍微混淆一下,然后简单地将这两者分开:
public static List<GameObject> FindAllGameObjectsInGameObject(GameObject gameObjectToTraverse)
{
return FindAllGameObjectsInGameObjectInternal(objectToTraverse, new List<GameObject>());
}
private static List<GameObject> FindAllGameObjectsInGameObjectInternal(GameObject gameObjectToTraverse, List<GameObject> list)
{
foreach (Transform child in gameObjectToTraverse.transform)
{
list.Add(child.gameObject);
FindAllGameObjectsInGameObjectInternal(child.gameObject, list);
}
}
但是,使用可选参数解决方案,您可以让开发人员有机会重用已经存在的列表,而不是每次都创建一个新列表;)
推荐阅读
- python - 编辑同名文件
- google-maps - 谷歌地图 - 带孔和自定义背景的多边形
- php - html文档中的php表单在提交表单时避免重定向到顶部
- ruby-on-rails - Rails 5 集成测试失败,出现 NoMethodError:未定义方法 `[]=' for nil:NilClass when using Devise helper sign_in
- python - 如何确定活动监视器并获得其分辨率?
- html - 字体真棒一些图标现在出现
- python - 在扭曲中实现网络多人游戏循环
- django - Django,无法保存数据表单
- python - Python 多处理配置单元在 Linux 中挂起
- java - 碧玉报告中的时区转换和日期格式?