Zeiger in C # Unity

8

Hey, ich habe kürzlich etwas über Zeiger gelernt und frage mich, wie ich sie in c # (ich habe sie gerade in c ++ kennengelernt) in Einheit verwenden kann. Ich habe allerdings einige Fragen.

  1. Zeiger verwenden die Programmierung auf niedriger Ebene, um Positionen mit unterschiedlichen Werten auf dem Computer zu finden. Bedeutet dies, dass Sie von jedem Skript aus einfach auf den Wert einer Variablen zugreifen können?
  2. Wenn ja, wie rufe ich einfach einen Speicherort einer Variablen mit nur ihrem Standortcode auf?
  3. Gibt es erkennbare Unterschiede zwischen Zeigern in C # und C ++, die ich kennen sollte?
  4. Wie kann ich Zeiger mit den Variablentypen in Unity verwenden (Vector3s, Transforms, GameObjects usw.)?

Es gibt so viele weitere Fragen, die ich wahrscheinlich stellen sollte und möchte, wenn Sie zusätzliche Informationen oder Quellen haben.

Ryan Henry
quelle

Antworten:

6

Im Allgemeinen für C # und speziell für Unity würde ich davon abraten ... aber wenn Sie wirklich wollten oder guten Grund hatten, könnten Sie.

In C # müssten Sie sich mit dem so genannten unsicheren Code vertraut machen . Noch Angst?

In Unity müssten Sie den unsicheren Kompilierungsmodus aktivieren, damit Sie den Web-Player nicht verwenden können, wenn Sie dies geplant haben. Sie können hier oder hier mehr lesen .

Also im Grunde C # wurde mit einem entworfen Garbage Collector so viele Skriptsprachen sind. Die allgemeine Idee besteht darin, den Begriff der Speicherverwaltung zu abstrahieren, um die Entwicklung zu vereinfachen. Es kann immer noch zu Ressourcenlecks kommen, wenn Sie Ihre Objekte nicht aufheben. Ich bin ehrlich gesagt kein großer Befürworter von GCs und würde stattdessen RAII- Methoden bevorzugen , aber dies ist die Welt, in der wir leben.

Die meisten C ++ - Entwickler würden jedoch auch zustimmen, dass Sie Zeiger sowieso nicht direkt verwenden sollten und es vorziehen sollten, einen von RAII entworfenen Typ, auch bekannt als intelligente Zeiger, zu verwenden . Wenn Sie sich in C-Land befinden, sind Zeiger für Sie wahrscheinlich eine Selbstverständlichkeit, aber selbst dann hilft es, sie bis zu einem gewissen Grad zu abstrahieren.

Wenn Sie sie in C # verwenden, beachten Sie nur, dass es ein sehr reales Potenzial gibt, dass Sie Sicherheitslücken hinzufügen oder wirklich böse und schwer zu lokalisierende Fehler finden können. Sie müssen auch berücksichtigen, dass Sie darauf achten müssen, keine Objekte zu referenzieren, die vom GC verschoben werden können. Beachten Sie die Verwendung der festen Aussage hier .

Sie können Zeiger auch in Unity verwenden, indem Sie ein natives Plugin schreiben . Dies schließt Webplayer-Builds erneut aus, aber die neue HTML5-Funktion basiert auf emscripten. Wenn Sie dies verwenden möchten , können Sie dies wahrscheinlich tun , wenn Sie vorsichtig sind. Mit nativen Plugins können Sie Unity plattformübergreifend erweitern. Ich habe ein natives Plugin geschrieben, um beispielsweise über eine serielle Verbindung mit einigen Mikrocontrollern zu kommunizieren.

Zusammenfassend sollten Sie sich also auf jeden Fall fragen, warum ich in Unity Zeiger in C # verwenden möchte. Wenn du es nur zum Spaß machen willst ... Knock dich aus.

Edit: Es tut mir leid, wenn ich jemanden beleidigt habe, da ich weiß, dass meine Gedanken zu GC momentan nicht der populären Meinung sind.

Wenn Sie meine Antwort wirklich lesen, werden Sie feststellen, dass ich C # nicht als Skriptsprache bezeichne. Ich vergleiche es mit "vielen Skriptsprachen", aber im Kontext von Unity wird es sehr häufig als Skriptsprache verwendet. Es ist eine Art DSL für Unity, wenn Sie so wollen. Oft wird es in diesem Zusammenhang sogar als Unity-Skript bezeichnet (dies bezieht sich hauptsächlich auf die Javascript-Alternative von Unity zu C #). Wenn Sie LLVM in Ihre Pipeline aufnehmen, können Sie es einfach direkt in nativen Code für die Plattform kompilieren ... wie würden Sie es dann nennen? Also wollte ich hier wirklich keine Haare spalten.

Viele großartige Referenzen zum Software-Engineering sind mit Meinungen gefüllt:

Effektives C ++ , effektiveres C ++ , häufig gestellte Fragen zu C ++ , effektives C # , modernes C ++ - Design , Designmuster ... und unzählige andere. Ich glaube nicht, dass dies die Argumente weniger glaubwürdig macht, wenn ihnen eine nachdenkliche Erklärung folgt.

Ich habe nicht wirklich alles gesagt "Benutze niemals Zeiger !!" . Tatsächlich benutze ich sie gelegentlich immer noch nackt. Ich sagte "im Allgemeinen" wie in "Verwenden Sie lieber sicheren Code als unsicheren Code in C #". Es gibt Situationen, in denen dies von Vorteil sein kann, und dies ist eine der wirklich leistungsstarken Funktionen von C #, um Ihre Werkzeuge auszuwählen. Mit C # können Sie sogar bis zu einem gewissen Grad Transparenz im GC-Prozess haben, Sprachen wie Dart nicht und dies kann sehr leicht zu Ressourcenlecks führen. Sicher, wenn Sie der einzige Entwickler eines kleinen Projekts sind, ist dies wahrscheinlich kein Problem. Wenn Sie in einem Team von beispielsweise 10+ mit Hunderttausenden von Codezeilen arbeiten, kann dies schwierig werden.

Ich wollte einfach, dass der Leser Vorsicht walten lässt, wenn er nackte Zeiger verwendet. Es ist fast so, als würde man sehr vorsichtig sein, wenn man mit Netzstrom arbeitet. Ich sage nicht, dass Sie kein Elektriker sind, nur dass Sie tot sind, wenn Sie den falschen Schritt machen und ihn nicht mit Respekt behandeln.

Ich mag das Beispiel von Lasse, in dem die Leistung die Notwendigkeit diktiert haben könnte.

Matthew Sanders
quelle
1
C # ist keine Skriptsprache, obwohl es dafür verwendet werden kann. Java hat auch einen GC und es ist auch keine Skriptsprache. Mit Ihrer eigenen Meinung zu antworten, was im Allgemeinen am besten ist, ist nicht die objektive Antwort, die wir auf dieser Website suchen. Für einen bestimmten Zweck können so etwas wie unsicherer Code und Zeiger sehr effizient sein.
Lasse
1
Ich verstehe nicht, warum diese Antwort abgelehnt wird - sie ist sehr informativ und zeigt viel Forschung / Wissen und Links zur weiteren Lektüre. Besonders für @Lasse, was ist Skriptsprache? Natürlich wäre es präziser zu sagen, "Sprache, die für das Schreiben von Skripten in Einheit verwendet wird", aber ich sehe keinen Grund zur Ablehnung, da Matthew 7 offensichtliche Wörter weggelassen und einen (über) vereinfachten Begriff verwendet hat.
Wondra
@wondra Ich habe nicht gewählt, weil die Antwort nicht offensichtlich macht, dass es Stellen gibt, an denen Zeiger sehr gut in C # verwendet werden können. Es hängt alles vom Zweck und der Zielplattform ab. Tatsächlich versucht die Antwort, alle von der Verwendung von Zeigern abzuhalten.
Lasse
1
@wondra Diese Antwort beantwortet die Frage kaum. Alles, was es tut, ist zu sagen, keine Zeiger zu verwenden. Dieser Kommentarbereich ist kein geeigneter Ort, um dies zu diskutieren. Sie können dem Chat beitreten, wenn Sie glauben, mehr Argumente zu haben.
Lasse
1
@Lasse kann dich nicht überzeugen und es ist nicht mein Kampf, aber deine Antwort zu sehen - du hast genau das gleiche geschrieben wie diese Antwort (die früher gepostet wurde), außerdem hast du sogar nur eine Teilmenge (= weniger Informationen) zum Thema aufgenommen, wie diese Antwort.
Wondra
6

C # verwendet Verweise , um Objekte weiterzugeben, die keine Werttypen sind . Dies bedeutet, dass normalerweise alles als Referenz übergeben wird. Wenn Sie einen Werttyp als Referenz übergeben möchten, können Sie das Schlüsselwort ref verwenden . Der Unterschied zwischen einem Referenztyp und einem Werttyp besteht darin, dass abhängig von der Größe des Werttyps normalerweise mehr Speicher benötigt wird, wenn er an eine Funktion übergeben wird. Eine Referenz ist nur 32 Bit oder 64 Bit oder 4 Bytes oder 8 Bytes. Sie können mehr Leistung aus Ihrem Code in sehr engen Schleifen herausholen, wenn Sie Referenzen verwenden, anstatt nur alle Daten zu kopieren, die die werttypisierten Variablen enthalten, vorausgesetzt, sie sind größer als 4 oder 8 Bytes.

In Unity ist beispielsweise jedes MonoBehaviour-Objekt (Klassenobjekt) ein Referenztyp, und jedes Vector3-Objekt (Strukturobjekt) ist ein Werttyp.

Es gibt auch unsichere Codeblöcke , mit denen Sie Code eingeben können, mit dem Sie Daten unsicher erstellen und ändern können. Um unsicheren Code zu verwenden, müssen Sie den Compiler so einstellen, dass unsicherer Code zugelassen wird. Zeiger können auf diese Weise verwendet werden. Durch die Verwendung von unsicherem Code werden bestimmte Prüfungen mit sicherem Code nicht verwendet, wodurch es schwieriger wird, unsicheren Code fehlerfrei zu schreiben. Es gibt nur sehr wenige Orte , die von unsicherem Code in C # profitieren können. Unter Unity wird unsicherer Code nicht auf allen Plattformen unterstützt. Normalerweise reicht es aus, Referenzen anstelle unsicherer Zeiger zu verwenden, wenn Sie mit Unity arbeiten.

Hier ist ein Beispiel ( Quelle ) für die Verwendung unsicherer Codezeiger in C # mit Unity:

public static class Rope
{
    // C# function declaration to match C++
    [DllImport(SlingshotImport.c_libName)]
    static unsafe extern void UpdateRopeParticlesUnsafe(
        Vector3* oldNew,
        Vector3* curr,
        int numParticles);

    // C# wrapper function for Unity C# script
    static void UpdateRopeParticles(
        Vector3[] oldNew,
        Vector3[] curr,
        int numParticles)
    {
        unsafe
        {
            fixed (Vector3* oldNewPtr = oldNew)
            fixed (Vector3* currPtr = curr)
            {
                UpdateRopeParticlesUnsafe(oldNewPtr, currPtr, numParticles);
            }
        }
    }
}
Lasse
quelle
Ich finde es interessant, dass Sie meine Antwort kritisieren und dieselben Argumente verwenden, abzüglich anderer relevanter Informationen, und nur eine kurze Diskussion von Wert und Referenztypen einschließen. Sie könnten zumindest Boxing erwähnen , JIT-Optimierungen, die manchmal den Kopieraufwand für Werttypen beseitigen könnten, wie man unsicheres Marshalling vermeidet oder vielleicht, dass unsicherer Code nicht immer schneller als sicher ist
Matthew Sanders
Es tut mir leid, wenn Sie sich angegriffen oder beleidigt fühlen. Es war nicht meine Absicht. Ich habe Ihre Antwort dafür kritisiert, dass sie mir eher meinungsbasiert als faktenbasiert erschien. Ich habe Antworten auf die gestellten Fragen zusammen mit einem Beispielcode bereitgestellt. Aufgrund Ihrer Antwort konnte ich die Dinge, die ich in meiner Antwort erklärte, nicht verstehen, was meiner Meinung nach für die gestellte Frage relevanter war. Ich sehe nicht, wie GC etwas mit "Wie verwende ich Zeiger?" Zu tun hat. oder ich habe nicht gesehen, dass Sie erwähnt haben, wie Referenzen auf C # funktionieren, da die Frage davon auszugehen schien, dass Variablen in C # und C ++ auf die gleiche Weise funktionieren.
Lasse
1
Keine Sorge. Vielen Dank für Ihre Entschuldigung. Ich habe den GC erwähnt, da Sie sich bewusst sein müssen, dass das Übergeben von Zeigern an verwaltete Typen Probleme verursachen kann, wenn der GC das Objekt plötzlich verschiebt. Ich nahm an, dass der Leser das C # -Typsystem und die Verwendung von Referenz- und Werttypen kannte.
Matthew Sanders
Ihr macht es wirklich schwer, eine Antwort zu akzeptieren. Sie haben mir beide viele Informationen zur Verfügung gestellt, die benötigt wurden, damit ich Sie beide abstimmen und die erste akzeptieren kann. Ich meine nichts damit. Es fällt mir nur schwer, mich zu entscheiden, und ich mache mir keine Sorgen, wenn ich mich von "unsicherem Code" abschrecken lasse. Ich war sowieso nie derjenige, der sich einer Herausforderung entzogen hat. Obwohl ich jetzt weiß, dass das Arbeiten mit Zeigern unpraktisch ist, da es sich um die Entwicklung mehrerer Plattformen handelt. Ich möchte Ihnen allen für Ihre Zeit und Ihre Meinung danken. und es tut mir leid, dass ich mit dem dritten Weltkrieg angefangen habe.
Ryan Henry