Динамическое приведение типа

Никак не могу разобраться с приведениями типов.

Написал метод:

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 шт):

Автор решения: RiotBr3aker

Вообще вариантов несколько, начиная от самого примитивного:

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;
→ Ссылка