Интересно ваше мнение. Если нужно сделать GUI с анимационными кнопка, красивой сменой экранов(допустим, чтобы одни элементы улетали в одну сторону, а с другой стороны прилетали другие) и подобными эффектами, то как лучше сделать такое?
Я сейчас для каждого элемента делаю свой GameObject и на нем проигрывал анимации или просто смещаю его, а сам элемент рисуется, через GUILayout, но смещается\масштабируется в зависит от трансформации.
Но GameObject для каждого элемента не супер. Как бы вы это сделали?

public enum ScaleType {
ByWidth,
ByHeight,
ByWidthAndHeight,
ByAverageSize,
ByMinSize,
ByMaxSize
}
public abstract class GUIComponent : MonoBehaviour {
[SerializeField] private ScaleType scaleType = ScaleType.ByAverageSize;
[SerializeField] private float scale = 50;
[SerializeField] private float border = 5;
protected bool pressedDown = false;
private bool process = false;
public abstract bool Draw();
protected virtual void Update() {
if(pressedDown) process = true;
}
protected Rect GetRect(GUIContent content) {
float borderX = border * GetScaleX() / 100f;
float borderY = border * GetScaleY() / 100f;
Vector2 size = GUI.skin.button.CalcSize(content);
float aspect = size.x/size.y;
if(scaleType == ScaleType.ByWidthAndHeight) aspect = 1f;
float w = GetScaleX() * scale / 100f * aspect;
float h = GetScaleY() * scale / 100f;
Rect rect = GUILayoutUtility.GetRect( w+borderX*2, h+borderY*2, GUILayout.ExpandWidth(false) );
rect.x += borderX;
rect.y += borderY;
rect.width -= borderX*2;
rect.height -= borderY*2;
Vector2 center = rect.center;
rect.width *= transform.lossyScale.x;
rect.height *= transform.lossyScale.y;
rect.center = center;
return rect;
}
private float GetScaleX() {
switch(scaleType) {
case ScaleType.ByWidth : return Screen.width;
case ScaleType.ByHeight : return Screen.height;
case ScaleType.ByAverageSize : return (Screen.width+Screen.height)/2f;
case ScaleType.ByMinSize : return Mathf.Min(Screen.width, Screen.height);
case ScaleType.ByMaxSize : return Mathf.Max(Screen.width, Screen.height);
case ScaleType.ByWidthAndHeight : return Screen.width;
}
return 0f;
}
private float GetScaleY() {
switch(scaleType) {
case ScaleType.ByWidth : return Screen.width;
case ScaleType.ByHeight : return Screen.height;
case ScaleType.ByAverageSize : return (Screen.width+Screen.height)/2f;
case ScaleType.ByMinSize : return Mathf.Min(Screen.width, Screen.height);
case ScaleType.ByMaxSize : return Mathf.Max(Screen.width, Screen.height);
case ScaleType.ByWidthAndHeight : return Screen.height;
}
return 0f;
}
public bool IsPressedDown() {
return pressedDown;
}
public bool IsProcess() {
bool end = process && !animation.isPlaying;
if(end) process = false;
return end;
}
}
public class GUIButton : GUIComponent {
public string text;
public override bool Draw() {
Rect rect = GetRect( new GUIContent(text) );
return pressedDown = GUI.Button(rect, text);
}
}