In meine Spielebibliothek möchte ich eine ähnliche Hierarchie der Transform-Komponenten einbauen, wie sie in Unity zu finden ist. Dafür hab ich folgende properties:
- position -> globale Position im Raum (Scale mit einberechnet)
- localPosition -> relative Position zum Ursprung der Parent (Scale nicht mit einberechnet, also relative Position bei einer globalen Skalierung von 1x)
- rotation -> globale Rotation im Raum
- localRotation -> relative Rotation zum Parent
- scale -> globale Skalierung der Größe und relativen Position aller Children
- localScale -> lokale Skalierung gegenüber dem Parent
- parent -> Transform-Komponente des Parent-Objektes, wenn null, dann kein parent -> root
- children -> Liste aller Transform-Komponenten der direkt untergeordneten Objekte (keine grand children)
- root -> Transform-Komponente des obersten Objectes der Hierarchie, zu dem diese Transform-Komponente zugehörig ist
Dies habe ich jetzt in einer Transform-Klasse umgesetzt (C#), allerdings bin ich mir nicht sicher ob meine Lösung so effizient ist, und da die Transform-Komponenten mit ihren Informationen als Basis für so ziemlich alles dienen, sollte diese Klasse bis ins kleinste Bisschen optimiert werden, um effizientes und schnelles rendering,etc. zu gewährleisten. Daher wollte ich frage ob ihr irgendwelche Optimierungsvorschläge habt.
Hier die wichtigsten Ausschnitte der Klasse:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96:
| public sealed class Transform : Component, IEnumerable { public Vector2 position { get => INTERNAL_get_position(); set { Translate(value - position); } }
public Vector2 localPosition { get; set; }
public float rotation { get => INTERNAL_get_rotation(); set { float delta = value - rotation; localRotation += delta; Rotate(delta); } }
public float localRotation { get; set; } public Vector2 globalScale => INTERNAL_get_globalScale(); public Vector2 scale { get; set; }
public Vector2 right => Vector2.right * Matrix3x3.GetRotationMatrix(rotation); public Vector2 up => Vector2.up * Matrix3x3.GetRotationMatrix(rotation);
public Transform parent { get => parentInternal; set { SetParent(value); } }
private Transform parentInternal { get; set; } public Transform root => INTERNAL_get_root(); public State state { get; internal set; } internal List<Transform> children = new List<Transform>();
public void SetParent(Transform parent) { this.SetParent(parent, true); }
public void SetParent(Transform parent, bool keepWorldPosition) { Vector2 pos = Vector2.zero;
if (keepWorldPosition) pos = position;
this.parent?.children.Remove(this);
parent?.children.Add(this); parentInternal = parent;
if (keepWorldPosition) { Vector2 vecToNewPos = position - pos; Translate(vecToNewPos); } }
#region INTERNAL_Get_Set private Vector2 INTERNAL_get_position() => parent != null ? localPosition * Matrix3x3.GetScaleMatrix(parent.globalScale) + parent.position : localPosition; private float INTERNAL_get_rotation() => parent != null ? localRotation + parent.rotation : localRotation;
private Vector2 INTERNAL_get_globalScale() { Vector2 scale = this.scale;
for (Transform parent = this.parent; parent != null; parent = parent.parent) scale *= Matrix3x3.GetScaleMatrix(parent.scale);
return scale; }
private Transform INTERNAL_get_root() { if (parentInternal == null) return this; else return parentInternal.INTERNAL_get_root(); } #endregion
public void Translate(Vector2 translation) { localPosition += translation; }
public void Translate(float x, float y) { Translate(new Vector2(x, y)); }
public void Rotate(float angle) { localPosition *= Matrix3x3.GetRotationMatrix(angle); RotateChildren(angle); }
private void RotateChildren(float angle) { foreach(Transform child in this) child.Rotate(angle); }
public IEnumerator GetEnumerator() => new TransformEnumerator(this); } |