Jump to content
Unity Insider Forum
Kokujou

Codeüberprüfung und Feedback gesucht!

Recommended Posts

Also vielleicht sag ich es nochmal überdeutlich:

Ich hatte eine Card-Klasse, die ich in der Awake durch ihren Konstruktor gesetzt habe, typisch indem ich gesagt habe Eigenschaft A = x, B = y ...

Dann hab ich ja den lieben Tipp bekommen ScriptableObjects zu nehmen. Also schreib ich in der klasse das ScriptableObject hintendran. Jetzt ist ja nix mehr bei Konstruktoren. Es sind 48 Karten, es war mir also zu blöd jede einzeln neu zu schreiben, ich hab gesehen das geht auch im Skript also ich ganz clever, den Konstruktor einfach umbenannt und umgebastelt mit nem bisl Textediting. Sodass der Konstruktor jetzt das SO erzeugt und dei Variablen setzt. Allerdings war dann der Name des Assets auch der Name der Karte in einer eigenschaft.

Dann hab ich getestet und plötzlich so einen krankhaften grundbösen Fehler bekommen "GetName kann nur innerhalb des MainThreads aufgerufen werden" oder so. Also hab ich nach einer endlosen Kaskade an Flüchen und "wtf"s einfach ne neue Eigenschaft "Name" hinzugefügt. Dann hab ich die konstruktoren selbstverständlich alle gelöscht und musste nur in der ersten Awake aufrufen "foreach Cards in AllCards Name = name".

Und danach stand überhaupt gar nichts mehr über dieses ScriptableObject, dessen Beschreibung oder sonst irgendein Zugriff in meinem Code. Stattdessen Lade ich sie indem ich sie alle in eine öffentliche Variable gepackt habe und dann nochmal in eine statische Variable geschrieben habe zwecks Zugriff. Das siehst du in der Global.cs

Es wäre echt praktisch wenn ich die Card-Klasse auch direkt als Komponente hinzufügen könnte, aber so nice ist man dann wohl nicht bei Unity ^^ Darum hab ich diesen blöden Schnipsel CardRef. Schade dass man nicht von SO und MonoBehaviour erben kann

Share this post


Link to post
Share on other sites

Tipp: Liegt nicht an Unity. Du machst irgendetwas falsch :)

Diese Sache mit dem programmatischen Erstellen von Assets ist einfach nicht, wie man das macht. Wenn du dein ScriptableObject einfach so erstellst und da etwas einträgst, dann bleibt das auch. Du überschreibst den Titel locker irgendwo in deinem Code. Oder du überschreibst das ganze Objekt.

Share this post


Link to post
Share on other sites

Tu ich aber nicht :o Das Teil hat keinerlei Schreibreferenzen. Und das komische ist: Es passiert nicht nach Ausführung des Programms sondern nur wenn Unity geshclossen wird oder so der muss das irgendwie zurücksetzen oder... weiß der Geier.

 

Share this post


Link to post
Share on other sites

Und ganz nebenbei: einmal habich sogar einfach alles aus dem Git da wieder reingepastet. Auch das hat er ja wieder gelöscht. Ich garantiere dafür dass der Title nirgends im Code beschrieben wird. Ich hab es ja mal readonly gemacht. Im code hat er da nie gemeckert, was heißt: Keine Schreibbefehle. nur Unity hat es dann halt aus dem Asset ausgeschlossen.

Share this post


Link to post
Share on other sites

Ja, readonly-Variablen werden nicht serialisiert.

P.S. Denk dran, für Nachträge deine Beiträge haben einen Bearbeiten-Knopf ;)

Share this post


Link to post
Share on other sites

Bei computerbase werden sie automatisch zusammengefasst *maul*

Ich habs jetzt sogar mit SerializedObject.ApplyModifiedProperties versucht... nix >.>

Share this post


Link to post
Share on other sites

Du kannst nicht einfach irgendwelche Sachen einbauen über die du zufällig bei Google gestolpert bist, ohne zu analysieren wo das Problem liegt und zu verstehen, was diese Dinge tun.

Ach ja: Wo hast du denn überhaupt AssetDatabase.Blub und ApplyModifiedProperties eingebaut?

Share this post


Link to post
Share on other sites

woher sollichs denn wissen! XD

Es liegt NICHT in meinem Code. Ich glaube es hat was damit zutun, dass unity zwar das Objekt erstellth at, aber Änderungen nicht annimmt, darum hab ich nach Speichermethoden gesucht.

Share this post


Link to post
Share on other sites
vor 1 Minute schrieb Kokujou:

Es liegt NICHT in meinem Code.

Und das weißt du woher?

vor 2 Minuten schrieb Kokujou:

darum hab ich nach Speichermethoden gesucht.

Ja, aber du hast dich offenbar nicht informiert, wozu diese Sachen gut sind und wann man sie benutzt.

Ist vermutlich untergegangen, daher nochmal die Frage:

vor 6 Minuten schrieb Sascha:

Wo hast du denn überhaupt AssetDatabase.Blub und ApplyModifiedProperties eingebaut?

Ich bin mir ziemlich sicher, dass das Problem von der komischen Art kommt, wie du die Dinger erstellt hast.

Share this post


Link to post
Share on other sites

WEil es nunmal nicht bei Ausführung passiert sondern bei vom Skript unabhängigen Aktionen wie dem Laden einer Szene oder dem Schließen von unity

for (int i = 0; i < AllCards.Count; i++)
            {
                SerializedObject obj = new SerializedObject(allCards[i]);
                obj.Update();
                EditorUtility.SetDirty(allCards[i]);
                AllCards[i].Title = AllCards[i].name;
                obj.ApplyModifiedProperties();
            }
            for (int i = 0; i < allYaku.Count; i++)
            {
                SerializedObject obj = new SerializedObject(allYaku[i]);
                obj.Update();
                EditorUtility.SetDirty(allYaku[i]);
                allYaku[i].Title = allYaku[i].name;
                obj.ApplyModifiedProperties();
            }
            AssetDatabase.SaveAssets();

Also dass das Forum die VS Formate nicht unterstützt ist schon doof >.< keine Lust diese Leerzeichen einzeln zu löschen.

Das findet alles in der Awake()-Routine start... ja ich weiß es ist schrecklich aber ich hau jetzt alles rein da mir sonst nichts mehr einfällt XD

TATAAA ES HAT FUNKTIONIERT! Fürs erste zumindest >.< SetDirty war die Lösung. Weiß der Geier warum. Nagut n bisl nachvollziehen kann ichs. In meinem Code mach ich's nicht aber das SO soll wohl standardeinstellungen laden und dann für die Dauer eines Spiels gemoddet werden. Skripting als Massen-Text-Editing ist wohl nicht so das vordringliche Ziel XD

Share this post


Link to post
Share on other sites

So, da haben wir's doch. Warum zum Geier fummelst du da irgendwo in Awake herum? Die ScriptableObjects sollten zur Laufzeit bereits alle Informationen haben. Das SerializedObject ist auch völlig sinnlos.

Das "Title"-Feld ist dazu da, den Titel der Karte oder so einzutragen. Diese Verbindung zu .name sollte damit Vergangenheit sein, sonst nützt das überhaupt nix.

Share this post


Link to post
Share on other sites

Uff... Ich sagte doch dass ich das Ding nur benutze damit es schneller geht, oder hast du Lust die 48 Namen manuell einzutragen?
Ich hau den code da raus sobald er endlich die Änderungen behält. Aber SetDirty hat ja Gott sei Dank funktioniert ^^

Share this post


Link to post
Share on other sites

kommt drauf an. Am Ende häätte es nicht funktioniert und alles umsonst. Denn wie gesagt ich hatte ja sogar mal die völlig korrekten Files da reingepackt und auch die hatte er wieder überschrieben^^ stell dir mal du müsstest die Fummelei jedes mal machen. Da wird man wahnsinnig

Share this post


Link to post
Share on other sites

Mach sowas nächstes Mal als Editor-Script, nicht in Awake, das geht besser. Aber naja, dann ist das ja cuh abgehakt. Dann kannst du dich jetzt den anderen Problemen widmen :)

Share this post


Link to post
Share on other sites
vor 1 Minute schrieb Kokujou:

Editor-Skript? erzähl mal was ist das wie sieht das aus?

Es gibt Editorskripte, welche den Unity Editor um eigene Werkzeuge erweitern und Custom Inspector, womit Du den Inspector eines Objektes beeinflussen kannst. Ein guter Einstieg ist denke ich diese Seite https://unity3d.com/de/learn/tutorials/topics/scripting/introduction-editor-scripting

Share this post


Link to post
Share on other sites

Gibt verschiedene Sachen, die du im Editor machen kannst - von Scene View-Gizmos über eigene Inspektoren, PropertyDrawern und Editorfenstern zu ausführbaren Aktionen.

In deinem Fall ginge vermutlich sowas:

[MenuItem("Do Stuff/Set Yaku and Card Names")]
private static void SetYakuAndCardNames()
{
  // Do Stuff in Editor
}

 

  • Like 1

Share this post


Link to post
Share on other sites

Ah ich glaub das könnte mir später nützlich sein das Speicher ich mir mal weg, danke! :) Aber ob das die Sache geändert hatte... Es ging ja primär darum Änderungen am Objekt anzunehmen. Wichtig ist das auf Jeden Fall! :)

Share this post


Link to post
Share on other sites

Ist es eigentlich performant wenn ich mehrere Karten-GameObjekte habe  und die alle Raycasting in der update-Routine der Komponente ausführen lasse?

Oder wäre da eine übergeordnete die über einem Layer arbeitet besser?

Share this post


Link to post
Share on other sites

Es ist nicht davon auszugehen, dass du bei zehn Karten mit aktivem Raycasting Performance-Probleme kriegst, aber die Frage ist: Warum?

Der Witz am Raycast ist ja, dass du einfach mal irgendwo hinzielst und schaust, was da ist. Das heißt, ein einzelner Raycast gibt dir schon die Karte zurück, auf die man klickt. Mehrere Raycasts zu machen, um das Ergebnis dann wiederum in "war das denn ich" umzubauen, um diese Ergebnisse aller Karten dann wiederum zusammenzusetzen, um zu erfahren, welche Karte ausgewählt wurde, ist ein unschöner Umweg.

Share this post


Link to post
Share on other sites

Naja meine letzten Verbesserungen sind nur im Punkto Codequalität XD

Der schritt war weniger aufs Raycasting gemünzt aber es wäre halt cool wenn eine Karte die auf sie bezogenen Aktionen durchführen könnte.
Hovering, Klick-Aktionen und Skripte, Triggern anderer Events etc...

Schön wäre es ja wenn ich einfach n OnClick-Event einbauen könnte... Aber ich schätze mal ein Button-Skript kann ich nicht drauf legen oder? XD

Mir ging es halt größtenteils darum das alles aus der Hauptklasse rauszukriegen, denn wenn ich alles nur mehr oder weniger in eine Klasse schreibe dann ist das wohl irgendwie schlechter Stil und neher an imperativer Programmierung als an OOP, besonders wenn ich jetzt vorhabe zwei größere Klassen zusammenzufügen, weil ich gemerkt habe dass Klasse B zu 50% aus Verweisen an Klasse A besteht XD

Erst dachte ich daran ne Klasse für das ganze Input-Handling zu bauen aber auch das klingt nicht so prickelnd vor allem weil man halt wieder viele Verweise braucht.

aber wenn das scheiße ist dann überleg ich mir was besseres... mal gucken wie es wird.

Share this post


Link to post
Share on other sites
vor 13 Stunden schrieb Kokujou:

Schön wäre es ja wenn ich einfach n OnClick-Event einbauen könnte...

Klar kannst du das!

vor 13 Stunden schrieb Kokujou:

Aber ich schätze mal ein Button-Skript kann ich nicht drauf legen oder? XD

...aber nicht so! :)

Packste das hier auf die Kamera:

using UnityEngine;

[RequireComponent(typeof(Camera))]
public class CardRaycaster : MonoBehaviour
{
  new private Camera camera;
  
  private void Awake()
  {
    camera = GetComponent<Camera>();
  }
  
  private void Update()
  {
    if (Input.GetMouseButtonDown(0))
    {
      var ray = camera.ScreenPointToRay(Input.mousePosition);
      RaycastHit hit;
      if (Physics.Raycst(ray, out hit))
      {
        var hitCard = hit.collider.GetComponent<InteractiveCard>();
        if (hitCard)
        {
          hitCard.Interact();
        }
      }
    }
  }
}

und das auf deine Karte, wo auch der Collider sitzt:

using UnityEngine;
using UnityEngine.Events;

[RequireComponent(typeof(Collider))]
public class InteractiveCard : MonoBehaviour
{
  [SerializeField]
  private UnityEvent onInteract;
  
  public void Interact()
  {
    onInteract.Invoke();
  }
}

Die Vorkommen von Collider und Physics kann man noch auf 2D umstellen, und statt des Mauszeugs kann man auch gut Touchzeugs machen.

Share this post


Link to post
Share on other sites

hey so ähnlich hab ichs tatsächlich gemacht :)
 

Ich musste etwas Fummeln, weil so viel Hintergrundwissen aus anderen Klassen benötigt wird... Aber am Ende liefs auf Kommandos hinaus.

In der Player-Klasse wird jetzt der Input gehandhabt. Da switche ich dann zwischen zwei Funktionen für die Update-Routine die ich durch Kommando einstellen kann.

In der Player-Klasse die direkten Zugriff auf die Hände hat wird das Hovern der Karte geregelt und dann in der Funktion der Spielfeld-Klasse mitgeteilt, welche Karte gehovert wurde damit sie die passenden Feldkarten highlighted. Und wenn man dann auf dem Feld auch noch aufrufen muss ruft die Spielfeld-Klasse RequestInput() auf und die Player-Klasse schaltet quasi auf die zweite Update-Routine.

Zu finden in meinem neusten GitHub Skript^^

Das alleinige Hovern liegt jetzt tatsächlich auf der Karten-Komponente die vorher völlig leer war aber die Koordinierung des Hovers (es muss ja auch das vorherige "geunhovert" werden XD) übernimmt wieder das Spielfeld etc... kannst ja mal bei allem drübergucken was ich heute committet habe... hab nen neuen Branch eingerichtet weil die Änderungen von den Grundfunktionen das ganze Spiel zurückwerfen XD

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×