Динамическое приведение типа
Никак не могу разобраться с приведениями типов.
Написал метод:
public static Transform Transform(GameObject Object, string Name) {
Transform tm = Object.transform;
for (int i = 0; i < tm.childCount; ++i) {
Transform child = tm.GetChild(i);
if (child.name.Equals(Name, StringComparison.OrdinalIgnoreCase)) {
return child;
}
}
return null;
}
Смотрит нужный мне объект, в дереве родителя.
И мне захотелось сделать так, чтобы можно было через передачу нужного типа <T> привести к этому типу, который передали.
Написал также такой код:
private T Transform<T>(string Name) {
Transform trans = С.Transform(Obj, Name); // это метод выше
return Transform<T>(trans.gameObject);
}
public static T Transform<T>(object input, T defaultValue) {
return null == input ? defaultValue : (T)Convert.ChangeType(input, typeof(T));
}
public static T Transform<T>(object input) {
return Transform(input, default(T));
}
Но начало выбивать:
InvalidCastException: Object must implement IConvertible.
Чисто для себя интересно, как такое сделать.
А так, конечно можно использовать:
Button Name = Transform(obj, "Name").GetComponent<Button>();
Но хочется понять, как сделать именно вот так:
Button Name = Transform<Button>("Name");
И вообще без использования GetComponent.
Ответы (1 шт):
Вообще вариантов несколько, начиная от самого примитивного:
public static Transform Transform(GameObject @object, string name) {
Transform tm = @object.transform;
for (var child in transform){
if (child.name == name){
return child;
}
}
return null;
}
public static T Transform<T>(GameObject @object, string Name) where T : MonoBehaviour {
return Transform(@object, Name)?.GetComponent<T>() ?? null;
}
И заканчивая такой штукой:
static public T Transform<T>(GameObject @object, string name) where T : Component {
T[] childrenWithComponent = @object.transform.GetComponentsInChildren<T>(true);
foreach (var child in childrenWithComponent){
if (child.gameObject.name == name){
return child;
}
}
return null;
}
Причем теоретически второй подход будет быстрее, т.к. GetComponentsInChildren - функция с нативной стороны, так что вы сначала быстро получаете набор объектов с нужным компонентом, а уже потом по этому ограниченному набору ищете объект с нужным именем. Если во всей иерархии такой объект с таким компонентом один, то это практически гарантированно будет быстрее первого подхода (разве что только если все объекты будут содержать 1 ребенка).
Upd
Чтобы искать GameObject, а не компонент, нужно либо сделать отдельную реализацию:
static public GameObject Transform(GameObject @object, string name) {
Transform[] childrenWithComponent = @object.transform.GetComponentsInChildren<Transform>(true);
foreach (var child in childrenWithComponent){
if (child.gameObject.name == name){
return child.gameObject;
}
}
return null;
}
Что, по сути, дублирование кода. Можно просто вызывать изначальный метод и получать от него GameObject:
var trans = Transform<Transform>(gameObject, "name");
var gameObj = Transform<Transform>(gameObject, "name").gameObject;