ILRuntime, um die Vor- und Nachteile von Hot Update zu realisieren!

Heißes Update

Frage 1: Wie machbar ist es, ILRuntime zur Implementierung heißer Updates zu verwenden? Haben Sie Erfahrungen ausgetauscht?

Im Allgemeinen sind Hot-Updates in zwei Teile unterteilt: Code + Ressourcen, und Ressourcen-Hots werden fast alle über AssetBundle ausgeführt. Code-Hots können mit einer Art Interpreter + Interpreter-Ausführungssprache durchgeführt werden. Die Auswahlmöglichkeiten sind Lua, as3, Python, js, C # usw. Soweit ich weiß, ist der Mainstream Lua und der Sub-Mainstream ist C #.

In Bezug auf die Auswahl von Hot-Updates wurde der gesamte Code unseres Projekts ursprünglich in C # geschrieben, und Hot-Updates wurden nicht berücksichtigt. Da niemand im Team Unity3D kennt, lernt alles dabei, und "es herauszufinden" ist die erste Priorität. Nach dem Online-Betrieb kann es dem Betriebsdruck natürlich nicht standhalten: Bei vielen Android-Kanälen in China ist diese Nachfrage nach Betrieb angemessen, da es sonst für jeden Kanal sehr schwierig ist, den Startzeitpunkt zu überprüfen und zu synchronisieren jedes Mal, wenn die Version aktualisiert wird.

Dann verwenden wir zuerst XLua, um den Fehler zu patchen und zu beheben: Die Kosten sind am niedrigsten. Später erfordert der Vorgang, dass er durch Hitze funktionsfähiger ist, anstatt nur den Fehler zu ändern. Verwenden Sie dann entweder Lua, um den gesamten Code zu schreiben Möglicherweise wird ein Hot-Update durchgeführt, für das eine große Menge des vorhandenen C # -Codes übersetzt werden muss, oder es wird ein Weg gefunden, ein C # -Hick-Update durchzuführen. Daher ist es selbstverständlich, Letzteres + ILRuntime zu wählen.

Die endgültige technische Lösung lautet:

1. Grundlegende Einschränkungen.
Einige der Codes erben MonoBehaviour nicht, dh sie haben keine Skripte. Nicht heiße Teile sind kostenlos: Regent unterstützt MonoBehaviour und andere spezielle Dinge. Es ist sehr problematisch. Entweder brauchen Sie es nicht oder es ist nur ein Kinderspiel. Hot Message Forwarding Layer: Hängen Sie das Skript entweder während der Entwicklung auf und verwenden Sie eine spezielle Methode, um es während des Packens in eine dynamische AddComponent im Code umzuwandeln.

2. Android
benötigt kein Hot-Change-Programm eines Drittanbieters, verwendet C # -Reflexion zum Ausführen der DLL. Leistung und Code-Schreiben sind im Grunde die gleichen wie bei reinem C #.
Google Pay schreibt vor, dass alle Apps vor August 2019 64-Bit unterstützen. Die Lösung von Unity ist Android IL2cpp. Derzeit ist keine Unterstützung für 64-Bit-Mono-Backend geplant. Daher kann es nur IL2CPP + ILRuntime sein, und die Leistung wird viel schlechter sein, hauptsächlich aufgrund von ILRuntime.

3.
Interpretation und Ausführung von iOS ILRuntime + DLL natürlich unter IL2CPP.

4. Vorteile Die
Sprache (C #) \ Entwicklungsumgebung \ Toolkette ist vereinheitlicht und kann zu einem Formular werden, das zu keinem Zeitpunkt ein Hot-Update unterstützt, wenn Apple in Zukunft keine Interpretation und Ausführung zulässt.

Nachdem das Framework erstellt wurde, werden einige Einschränkungen erfüllt (nicht harte Einschränkungen, hauptsächlich zur Vermeidung von Problemen, die Einschränkung ist hauptsächlich eine, der Hot-Changing-Teil des Codes sollte den nicht-Hot-Changing-Code nicht erben, und der Non-Change-Code Das Erben von MonoBehaviour ist eine Teilmenge dieser Einschränkung. Die Entwicklungsmethode von Schülern, die Logik schreiben, ist genau die gleiche wie die der nativen C # -Entwicklung, einschließlich des Debuggens.

Plug-Ins von Drittanbietern sind direkt verfügbar (die meisten Plug-Ins basieren auf C #).

5. Nachteile
Es gibt immer noch einige Fallstricke bei der Stabilität: Sie treten normalerweise in einigen relativ hohen Sprachmerkmalkombinationen auf, insbesondere bei verschiedenen Reflexionscodes. Darüber hinaus sollte die aktuelle Version, die von .net4.6s async \ wait unterstützt wird, nicht stabil genug sein. Die reine Rechenleistung ist schwächer als die von Lua, und der rechenintensive Code sollte im nicht-heißen Update-Teil platziert werden.

Die Geschichte ist kurz, es gibt nur wenige Git-Mitwirkende und nur wenige Projekttests (soweit ich weiß, liegen kommerzielle Projekte auf der Linie zwischen x-1x, bestimmte Projekte umfassen MMO, SLG, Freizeit sowie Schach und Karten). Im Prinzip Es gibt keinen großen Optimierungsspielraum. Es gibt immer noch einen kleinen Optimierungsbereich. Außerdem gibt es nur wenige Frameworks, die verschiedene gemeinsame Funktionen integrieren.


Machen

F2: Wir wissen, dass der von Unity erstellte Würfel 24 statt 8 Eckpunkte hat. Wir haben einen Cube in Max erstellt und ihn ohne UV-Verarbeitung in Polygon konvertiert. Wir hoffen, dass die Anzahl der exportierten Scheitelpunkte gesteuert werden kann (kann 8 sein), aber wir haben festgestellt, dass die Anzahl der standardmäßig exportierten FBX-Scheitelpunkte 24 betragen muss. Warum? Wie kann man seine Nummer genau steuern?

UWA: Diese Frage hängt hauptsächlich davon ab, ob die Eckpunkte benachbarter Flächen normale Linien im Modell teilen können. Wenn dies möglich ist, wird nur ein Scheitelpunkt benötigt, um ihn darzustellen. Wenn nicht, muss er in zwei Scheitelpunkte unterteilt werden (die Position ist dieselbe, aber die Normalen sind unterschiedlich). Und "ob normale Linien geteilt werden können" kann durch die Glättungsgruppe in Max und durch den Glättungswinkel in Einheit gesteuert werden (ähnlich der allgemeinen Regel, wenn der Winkel zwischen benachbarten Flächen kleiner als wie viel ist).

Daher kann der Betreff versuchen, Max eine Glättungsgruppe hinzuzufügen und diese zu exportieren, oder nach dem Import in Unity das Element Normal auf Berechnen und über den Glättungswinkel steuern. Um den Einfluss der Zusammenführung von Normalen auf den Lichteffekt besser zu veranschaulichen, zeigt das linke Bild, dass der Glättungswinkel 0 ist (im Grunde werden keine Normalen zusammengeführt, die Anzahl der Eckpunkte ist am höchsten, 7676), das rechte Bild ist 1 ( das Maximum der zusammengeführten Normalen, die Anzahl der Eckpunkte Das Minimum ist 3260).


Machen

F3: Wie realisieren Sie die alternative Tag- und Nachtmethode in Handyspielen? Ich habe überlegt, die Lightmap dynamisch zu laden, aber der Übergang der allmählichen Änderungen würde abrupt erscheinen. Wenn es Echtzeitlicht ist, ist der Leistungsdruck relativ hoch. Welche Ideen haben Sie für die Implementierung von Tag und Nacht auf dem mobilen Terminal? Danke vielmals!

Art backe zwei oder mehr Lightmaps, mische dann die beiden Lightmaps dynamisch über RenderToTexture, während das Spiel läuft, und verwende dann das Ergebnis. Wechsle nach Abschluss des Blends zur offiziellen Lightmap, und die vorübergehende Lightmap kann verloren gehen.

Möglicherweise muss beachtet werden, dass das Codierungsformat von Lightmap vor dem Mischen decodiert und nach dem Mischen wieder zurückcodiert werden muss. Kurz gesagt, es gibt einige Fehler, nachdem das Komprimierungsformat unter der mobilen Plattform gemischt wurde, aber es ist akzeptabel.

Es gibt einen Nachahmer-Ansatz, das heißt, die Kunst muss zwei Sätze von Tag und Nacht backen (wenn es mehrere natürliche Umgebungen gibt, können Sie mehrere Sätze backen).

1) Laden Sie die in der nächsten natürlichen Umgebung verwendete Lichtkarte dynamisch als globale Karte.

2) Verwenden Sie die Zeit, um einen Koeffizienten zu erstellen. Wenn die Lichtkarte dekodiert ist, interpolieren Sie einfach die aktuelle Lichtkarte und die in Teil 1 geladene Lichtkarte. (Von Tag zu Nacht konvertieren), der Ort der Dekodierung befindet sich in der Funktion UnityGlobalIllumination;

3) Verwenden Sie die Zeit, um einen Koeffizienten zu erstellen, und passen Sie das Umgebungslicht entsprechend an.

Die Voraussetzung dafür ist, dass die Anzahl der Lichtkarten in Ihrer Szene relativ gering ist, da dies sonst peinlicher wird.

Unser Projekt hat auch ein Tag- und Nachtsystem durchgeführt, das nicht von mir durchgeführt wurde. Ich habe die entsprechenden Kollegen zur Antwort eingeladen. Ich weiß nicht, ob ich Zeit habe. Lassen Sie mich mit ein paar Gedanken beginnen.

Wir haben die Idee von zwei Sätzen von Lichtkarten nicht übernommen. Die Vor- und Nachteile liegen auf der Hand: Der Vorteil besteht darin, dass mehrere Sätze von Lichtkarten bessere Ergebnisse erzielen können. Punktlichtquellen, GI und AO sind alle möglich, aber die Nachteil ist, dass der Verpackungskörper eine größere Menge und zu viel Platz einnimmt. Der Gradient ist etwas störend. Wenn es sich um ein ARPG handelt, ist es besser, die Szenen zu wechseln. Wenn sich Spieler in der großen Welt in derselben Szene befunden haben, kann dies etwas problematisch sein.

Die meisten Szenen, die wir ursprünglich entworfen haben, waren Feldszenen, und der Bedarf an Änderungen an Punktlichtquellen war sehr gering. Daher wurden bei der Idee des Tag- und Nachtsystems nicht mehrere Sätze von Lightmap-Lösungen ausgewählt, sondern die Lösung zum Ändern verwendet die Materialparameter.

1) In der ersten Version wird Lut verwendet, und der Farbverlauf wird mit dem Übergangsunterschied zwischen den beiden Lut-Texturen erstellt. Der Verbrauch ist grundsätzlich in Ordnung, aber da es sich um eine Vollbild-Nachbearbeitung handelt, gibt es keine HDR und keine Spezialeffekte wird auch abgedunkelt., Die Kunst ist nach einer Probezeit nicht zufrieden;

2) Die zweite Version basiert auf der Idee von Materialparametern. Das Kunstbacken ist die Wirkung des Tages, und das Ergebnis, das nachts in der PS erzielt wird, wird mit einem Farbwert multipliziert. Der Shader der Szene und der Charakter muss verarbeitet werden, und das Material des Spezialeffekts Ohne Verarbeitung kann der gesamte Verdunkelungseffekt erzielt werden. Der Grundeffekt ist nicht gut, kann aber die Anforderungen grundlegender mobiler Geräte erfüllen, und die Leistung ist akzeptabel.

3) Die Himmelsbox, die gerichtete Lichthelligkeit, das Umgebungslicht und der Zeichenreflexionswürfel werden so geschaltet, dass sie Tag und Nacht folgen, was hauptsächlich den Charakter betrifft.

4) Stellen Sie nachts die Intensität der selbstleuchtenden Teile von Fenstern und Laternen ein, die eine bessere Wirkung von Nachtlichtern zeigen können.

Die Idee unterscheidet sich von der Idee, Lightmaps zu wechseln. Als Referenz ist der Laufzeitverbrauch etwas größer als die Idee, Lightmaps zu wechseln. Der Vorteil ist, dass dadurch Kunstwerke und genug gespart werden, einige Pakete gespeichert werden und so weiter Es ist einfacher, zu viel zu tun, was für die Abenddämmerung praktisch ist. Diese Art von Effekt am Morgen, aber der Effekt ist nicht der beste, im Grunde genug für Handyspiele. Möglicherweise gibt es viele Details, die ich nicht verstehe. Rückblickend haben Kollegen Zeit, sie hinzuzufügen.


Ressourcen Management

F4: Ist die AssetBundle Diff Patch-Lösung realisierbar? Mein ursprünglicher Update-Plan besteht darin, den Hash-Wert der AssetBundle-Datei zu vergleichen und das gesamte AssetBundle und das Manifest direkt zu ersetzen, um den Update-Effekt zu erzielen. Ich weiß nicht, ob es einen anderen Plan gibt, der dem Diff-Patch ähnelt und das Update-Paket reduzieren kann Wenn Sie Diff-Patch ausführen können, Ressourcen Gibt an, ob die Granularität ignoriert werden kann.

Derzeit gibt es keine ausgereiften Lösungen für die direkte Diff-Aktualisierung auf Basis von AssetBundle, aber nur einige der Ressourcen in der gesamten Ressourcenbibliothek wurden ausgewählt und aktualisiert. Es wurden zwei Projekte durchgeführt. Die Idee ist eigentlich sehr einfach:

1) Wenn das gesamte Paket freigegeben ist, verwenden Sie ScriptableObject, um die MD5-Codes aller freigegebenen Ressourcen in der AssetsDataBase aufzuzeichnen (der eigene Hash-Code der Einheit kann nicht verwendet werden).

2) Verwenden Sie das Tool, um aufzurufen, welche Assets dynamisch in den Code geladen werden, und teilen Sie sie in ein Ressourcenpaket auf. Ermitteln Sie die abhängigen Ressourcen dieser Ressourcen, teilen Sie sie in ein Freigabepaket auf und zeichnen Sie das AssetBundle-Paket auf, zu dem jedes Asset gehört ;;

3) Vergleichen Sie bei der Veröffentlichung des Patches, welche dynamischen Lastressourcen in der aktuellen AssetsDataBase erhöht und geändert wurden (gelöscht kann ignoriert werden), einschließlich der Ressourcen, von denen sie abhängen. Stellen Sie die Ressourcen des dynamischen Ladens im Code weiterhin in ResPatch und die Abhängigkeiten in SharePatch. Für Ressourcen, die nicht geändert wurden, wird der ursprüngliche AssetBundle-Name weiterhin beibehalten.

4) Aktualisieren Sie nach dem Aufzeichnen des Patches das AssetBundle-Paket, zu dem jedes Asset gehört.

5) Die Ressource und die Freigabe des nächsten Patches können von der Freigabe des vorherigen Patches abhängen.

6) Zur Laufzeit wird ein Wörterbuchindex für alle vom Patch eingegebenen Res erstellt. Beurteilen Sie beim Laden zunächst, ob sich das Asset im Res-Paket des Patches befindet. Wenn dies der Fall ist, lesen Sie das AssetBundle-Paket des Patches und verarbeiten Sie die abhängigen Pakete gemäß der Routine. Verwenden Sie andernfalls das integrierte Binärpaket.

Die Vorteile dieses Ansatzes sind:
1) Verwenden Sie die freigegebenen Ressourcen in der Version, um die Größe des Patch-Pakets zu reduzieren.

2) Die Verpackungsregeln des Patch-Pakets können die Regeln für die Vergabe von Unteraufträgen des Gesamtpakets fast ignorieren, was für den nachfolgenden Wurf praktisch ist.

Natürlich liegen auch die Nachteile auf der Hand:
1) Ist die große Tasche in der kompletten Tasche wirklich gut? Wenn alle Ressourcen in einem AssetBundle zusammengefasst sind, unterscheidet sich dies nicht von der Verwendung des Ressourcenverzeichnisses. Dies wird von Unity offiziell verhindert. Nach der eigentlichen Messung wurde ein 300 MB Res-Paket geöffnet, und iOS hat fast 40 MB Speicher zugewiesen ... (Tatsächlich widerspricht dieses Problem nicht dem Diff-Update. Jetzt sind auch die Ressourcen in unserem Binärpaket relativ klein, aber die Patch kann weiterhin die oben genannten Regeln verwenden).

2) Tools, Tools, Entwicklungs- und Wartungsressourcen MD5-Datenbank, Patch-Generierungsregel-Packager, es dauerte 5 Tage und 5 Nächte, um es richtig zu machen;

3) Es ist auch das schwerwiegendste Problem. Bei Assets, die von vielen Ressourcen abhängig sind, enthält das Update-Paket nach dem Ändern eine Reihe von Ressourcen, die Waffen enthalten, z. B. UIAtlas-bezogene Dinge, Shader-Familie, Schriftarten usw ...

Bei Frage 3 ist es fast notwendig, die Idee zu verwenden, das gesamte Paket zu ersetzen, diese veränderbaren Assets auszuwählen und sie separat zu verpacken. Alle nachfolgenden Res und Shared verlassen sich auf sie. Wenn sich einer von ihnen ändert, wird das gesamte Basis-AssetBundle-Paket überschrieben und aktualisiert, und die von ihnen abhängigen Res werden nicht als geändert betrachtet.

In der Tat habe ich mich verstrickt, welches besser ist, das Differenz-Update oder den gesamten Paketersatz. Zu Beginn war der Hauptgrund für die Differenzaktualisierung, dass der Code im Projekt bei asynchroner Verarbeitung nicht ordnungsgemäß verarbeitet wurde und das AssetBundle-Paket mit kleinen, häufig geladenen Dateien sehr feststeckte. Daher habe ich ein großes Paket erstellt und war gezwungen, das zu verwenden Diff Lösung.

Unabhängig vom Verpackungsschema müssen Sie außerdem die Menge der redundanten Ressourcen im AssetBundle-Paket steuern [unabhängig davon, ob es sich um ein großes Paket oder ein Diff-Paket handelt, es kann aufgelöst werden]. Mein Endergebnis liegt innerhalb von 2% des tatsächliche Kapazität. An dieser Stelle kann das Online-Tool zur Erkennung von AssetBundle-Paketen von UWA sehr hilfreich sein. Vielen Dank!

Ich bin hier, um Sie zu überzeugen, sich zurückzuziehen. Das gesamte Paket von Diff, Flashyiyi, hat ein Schema geschrieben, das auf bsdiff https://zhuanlan.zhihu.com/p/31810166 basiert

Ich habe bsdiff verwendet, um den CPP in der Cocos2d-Ära zu aktualisieren. Es ist wirklich effektiv, die Größe des so zu reduzieren, aber warum sollte ich davon abraten?

1. Schwierig zu warten.
Diff besteht darin, den Unterschied zwischen zwei Dateien genau zu generieren . Dies erfordert, dass jeder Patch genau mit der vorherigen und der nächsten Version übereinstimmt. Bei mehreren Versionen besteht eine strikte lineare Beziehung: Es muss einzeln gepatcht werden. In der richtigen Reihenfolge installieren und zusammenführen. Und diese streng lineare Beziehung ist ein fataler Fehler.

Wenn es viele Versionen gibt, wenn eine Version in der Mitte fehlt oder ein Problem mit einem Patch in der Mitte vorliegt, liegt ein Problem in der gesamten Update-Kette vor. Zuverlässige Systeme müssen noch Fehlerbedingungen berücksichtigen.

2.
Die Routine zum Zusammenführen von Patches erfordert ein sorgfältiges Ersetzen von Dateien. Es scheint, dass der Patch groß sein wird, aber es ist natürlich, dass die wiederholten Änderungen mehrerer Versionen des Patches automatisch zusammengeführt werden, sodass die Gesamtzahl der Downloads nicht angezeigt wird, wenn die alten spieler oder die apk werden auf die neueste version aktualisiert. es wäre sehr übertrieben.

Die Diff-Lösung ist jedoch sehr problematisch. Obwohl die Diff-Zusammenführung durchgeführt werden kann, können Sie den Patch vor dem Zusammenführen nicht einfach löschen, wenn Sie ihn zusammenführen. Andernfalls ist für Spieler, die auf die Zwischenversion aktualisieren, kein Patch verfügbar. Sie müssen sehr strenge Entscheidungen treffen, um zusammengeführte Patches zu überspringen. Ein zuverlässiger Produktionsprozess ist auch erforderlich, um Probleme mit zusammengeführten Patches zu vermeiden.

3. Das Spielen eines großen AssetBundle führt zu einer langsamen
Zusammenführung. Dies liegt daran, dass Sie diese nacheinander zusammenführen müssen. Im Gegensatz dazu hat Yunfeng eine Lösung (Blog, kein Quellcode) geschrieben, die das Bundle entpackt und zur Laufzeit zusammenstellt. Zulongs Sechs Drachen kämpfen um die Hegemonie ist auch dieser Plan. Und sie spielen kein großes Bundle, sondern einen präzisen Ersatz in einem kleinen Bundle. Dies hängt nicht so sehr von der genauen Konsistenz der Version ab, und das Update-Paket kann sehr klein sein.

Aber es bringt ein neues Problem mit sich: Sobald das offizielle Format geändert wurde, muss auch der Code geändert werden. Das offizielle Format ist nicht Open Source, sondern von selbst geknackt (Sie können auf Open Source-Lösungen wie Unity Extractor verweisen), und die Schwierigkeit, der Sie folgen, liegt auf der Hand.

Wenn Sie sich also nicht wirklich für die Größe des Updates interessieren, ist es eigentlich eine gute Idee, die Datei zu ersetzen ... Wie auch immer, wir verwenden sie. Heutzutage sind die Spiele der großen Hersteller oft Dutzende von MB-Patches.


andere

F5: Das neueste Produkt, das von unserem Team auf den Markt gebracht wurde, ist Unity 4.6. Das neueste Projekt ist in Planung und es ist immer noch ein MMO-Produkt. Ich möchte fragen, wie viel ein Upgrade auf Unity 5 erforderlich ist. Da nach der Kürzung der Demo auf 5 einige zeitaufwändige Probleme zu lösen waren, befürchten wir, dass das Follow-up weitere Fallstricke verursachen wird. Ich denke, die wichtigsten neuen Funktionen von Unity 5, die ich kenne, sind: die Optimierung der AssetBundle-Verpackung, die Trennung von Partikeln vom Haupt-Thread, die PBR-Rendering-Methode usw., aber diese Dinge haben keinen großen Einfluss auf uns Vorerst.

UWA: Wenn es sich um ein neues Projekt handelt, muss Unity 5 aktualisiert werden. In Bezug auf neue Funktionen wird empfohlen, direkt zur Einführung von Unity 5 zu gehen, da viele online sind. Sprechen Sie über mehrere wichtige Aspekte der Leistungsverbesserung:

1) Höhere Ladeeffizienz. Selbst bei gleicher LZMA-Komprimierung und -Verpackung ist das Laden von AssetBundles mit demselben Inhalt vor Unity 5.3 schneller (5% ~ 15%). Darüber hinaus ist die Ladegeschwindigkeit für den neuen LZ4 AB nach Unity 5.3 schneller als zuvor. Natürlich lädt Unity 2017 ms schneller. Wir werden am UWA-Tag 2018 zusammenfassen und teilen.

2) Der AssetBundle-Ladespeicher belegt weniger Platz. Nach Unity 5.3 gibt es keinen Webstream, ein großer Segen. Sie müssen jedoch vor den Versionen 5.4.5 und 5.5.4 auf die "Grube" von 0,5 MB SerializedFile achten.

3) Zusätzlich zu dem im Thema erwähnten Partikelsystem ist das Animationsmodul auch für die Verarbeitung mit mehreren Threads ausgestattet, und die Effizienz wird erheblich verbessert (obwohl manchmal das problematische Problem des Hauptthreads, das auf die Unterfäden wartet, im Allgemeinen auftritt die Vorteile überwiegen die Nachteile);

4) Die UGUI wird nach der Unity 5.2-Version tendenziell verbessert, und es wurde eine Multithread-Verarbeitung hinzugefügt. In unserer Trendanalyse hat UGUI einen sehr klaren Trend, NGUI in Bezug auf Leistung und Reife einzuholen.

5) Nach der Unity 5.4-Version kann die Physik entsprechend der physischen Nutzung des Projekts entfernt werden, um das peinliche Problem des ständigen Leerlaufs zu vermeiden.

Darüber hinaus gibt es viele Leistungsverbesserungen. Es kann gesagt werden, dass die Leistungsverbesserung von Unity 5 in vielerlei Hinsicht noch besteht. Es wird empfohlen, ein Upgrade durchzuführen. Schließlich wird Unity 4 nicht mehr gewartet. Was ist, wenn in Zukunft ein Kompatibilitätsproblem mit einem Gerät oder System auftritt?

Ich denke du magst

Origin blog.csdn.net/mango9126/article/details/114131829
Empfohlen
Rangfolge