1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen
  2. Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
    Information ausblenden
  3. Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
    Information ausblenden

Pfadfinderbiene, Tutorial

Dieses Thema im Forum "Entwickler-Forum" wurde erstellt von Jenna Felton, 30. Juli 2012.

  1. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Das klang etwas hochnasig, war nicht so gemeint. Naja, ich glaube ich habe einen Weg gefunden, diese Fehlläufe (des Characters) zu vermeiden und umzugehen. Mit dem Ansatz habe ich in den letzten Tutorialpost erweitert.
     
    Zuletzt bearbeitet: 17. August 2012
  2. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Teil 3: Einrichtung der Umgebung (Fortsetzung)

    So, ich habe wieder Zeit gefunden, mit der Konstruktion und den Pendlern zu spielen, es gibt eine kleine Fortsetzung.

    9. Walkability = Begehbarkeit (Koeffizienten)


    a) Koeffizienten

    Im Linksetfloater haben vier Zahlen die ganze Zeit die Augen gekitzelt, jetzt sind sie an der Reihe - die Zahlen hinter den Buchstaben A, B, C, D neben der Überschrift "Walkability". Wozu sind sie? Sie werden meines Wissens nur für Linksets mit dem Parameter "Walkable" und "Material Volume" verwendet, un bestimmen wie teuer die Bewegung über diese Orte für Characters sind. Der Floater gibt eigentlich gleich eine Empfehlung ab:

    • A für humanoide (menschenännliche) Characters,
    • B für biologische Creaturen, wie Tiere etwa,
    • C für mechanische Creaturen, z.B. Roboters
    • D für andere Chars, die hier nicht passen

    Auf diese Weise kann man die Umgebung mehr oder minder für Characters vorbereiten, die man selbst nicht besitzt, und die mit Besuchern kommen oder auch so reinlauen. Die Characters sollten sich nur auch an diese Empfehlung halten: Sie können sich nämmlich einem dieser Typen zuweisen, und die Einstellung benutzen.

    Das wollen wir uns genauer anschauen und machen einen einfachen Versuch. Dazu benutzen wir die im vorigen Abschnitt korrigierte Rampenkonstruktion (mit der eingeengten Brücke). Die Konstruktion wird im Floater ausgewählt, sich vergewissert, dass sie "Walkable" ist, und für die Typen A bis D die Koeffizienten 75%, 50%, 25% und 5% zugewiesen:

    [​IMG]

    Nach Abspeichern, springt erneut der Button zum Rebacken der Region auf (bitte drücken) -- die Navmesh muss der Veränderung angepasst werden.

    b) Characteranpassung

    Würden wir nun den Pendler über die Konstruktion laufen lassen, würde er die Änderung gar nicht mitbekommen: Er benutzt die Defaulteinstellung "kein Typ" und diese beachtet die Koeffizienten nicht. Wir müssen die Characters so einstellen, dass sie sich einem der Typen zuordnen. Das geht nur im LSL Script des Characters, es reicht nur eine Zeile:

    Entweder setzen wir direckt nach dem Aufruf von llCreateCharacter diese Zeile ein:

    Code:
    llUpdateCharacter([CHARACTER_TYPE, CHARACTER_TYPE_A]);
    Oder wir erstellen den Character direkt mit dem erforderlichen Typ:

    Code:
    		llCreateCharacter([
    			CHARACTER_TYPE,          CHARACTER_TYPE_A,
    			CHARACTER_MAX_SPEED,       3.0,
    			CHARACTER_DESIRED_SPEED,   2.0,
    			CHARACTER_RADIUS,          0.125,
    			CHARACTER_LENGTH,          10.0,
    			CHARACTER_AVOIDANCE_MODE, AVOID_CHARACTERS,
    			CHARACTER_DESIRED_TURN_SPEED, 3.0,
    			CHARACTER_MAX_TURN_RADIUS, 0.5
    				]);
    Um vergleichen zu können, rezzen wir fünf Pendlerchars. Jeder wird bearbeitet und im Code die obige Veränderung eingebaut. Allerdings bekommen nicht alle den Typ A zugewiesen, jeder bekommt den anderen Typ: Die Typkonstanten heißen CHARACTER_TYPE_A, CHARACTER_TYPE_B, CHARACTER_TYPE_C, CHARACTER_TYPE_D und CHARACTER_TYPE_NONE.

    Den Typ NONE kann man auch weglassen, es ist default. vollständigkeitshalber weisen wir den trotzdem zu. Die Pendler bekomen zum Unterscheiden eine andere Farbe, ich habe folgende Zuordnung gewählt:

    • CHARACTER_TYPE_A - gelb
    • CHARACTER_TYPE_B - blau
    • CHARACTER_TYPE_C - grün
    • CHARACTER_TYPE_D - rot
    • CHARACTER_TYPE_NONE - weiß

    c) Rampenaufstieg (Pendlerlauf)

    Nachdem die Chars sich initialisiert haben und die Koordinatenliste eingelesen haben, kann man sie per Klick starten. Allerdings -- sollte man sie gleichzeitig starten, holen die chars sich ein und schubsen doch noch von der Rampe, weil der Pfad dem Rand gefährlich nahe kommt. Dagegen werden wir später was unternehmen, in diesem Test lassen wir sie nacheinander laufen und stellen die Stoppuhr. Das Bild fasst alle fünf Pendlerläufe zusammen:

    [​IMG]

    Auf dem Boden sind alle Pendler gleich schnell, der Unterschied fängt auf der Rampe an:

    • Der weiße Pendler, steigt die Rampe ungebremst in nur 7 Sekunden auf.
    • Der gelbe vom Typ A ist nur um 25% verzögert und braucht nur 9 Sekunden.
    • Der blaue (Typ B) hat die halbe Geschwindigkeit und braucht doppelte Zeit.
    • Der grüne (Typ C) hat den Viertel an Geschwindigkeit und braucht umso länger.
    • Der rote ist vom Typ D und ist auf 5% abgebremst, er kriecht förmlich die ganzen zwei Minuten. Bis er oben ist, könnte der Weiße vier Runden absolvieren. Dass die rote Kugel nicht durchgehend über die Rampe schwebt, liegt daran, dass ich nur den Aufstieganfang, die Mitte und das Ende abgebildet habe, der Char hatte keine Sprünge gemacht :)

    Die Geschwindigkeiten sind nicht genau festlegbar, weil da bestimmt noch Vorgänge auf der Sim was verzögern, aber den Trend kann man so setzen.

    Ok, das wars dann mit dem Abschnitt 9, danach folgen die Volumenbereiche und ich werde mit der Originalrampe (ohne eingeengten Brücke arbeiten, weil das der Ausgang war)
     
    Zuletzt bearbeitet: 4. August 2013
  3. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Teil 3: Einrichtung der Umgebung (Fortsetzung)

    Guten Morgen :)

    Es kommt wahrscheinlich der vorletzte Abschnitt des Teil 3. Es bleiben uns noch die Volumenbereiche zu untersuchen. Sie sind für die Finetuning der Pfade da, indem sie das Begehbarkeits-Parameter verändern. Es gibt zwei dieser Bereiche: Exclusion Volume und Material Volume.


    10. Exclusion Volume


    Der Ausschlussbereich definiert einen Bereich, den die Characters nicht betreten dürfen, Avatare oder physikalische Objekte aber schon. Das funktioniert so, dass ein so markierter Linkset einen Loch im Navmesch schneidet, genau wie Static Obstacle, allerdings ist Exclusion Volume phantom und somit durchquerbar, für Characters ist das Bereich aber Tabu (betreten können sie es aber trotzdem, wegen Lag oder Navigationsfehlern.) Mit solch einem Bereich können wir die Rampe jetzt reparieren: Sie hatte ja das Problem dass die Chars sich am Abstiegspunkt permanent verliefen.

    Ansatz 1.

    Im ersten Versuch schützen wir nur diesen kritischen Punkt, dazu nehmen wir die Originalkonstruktion und setzen in die entsprechende Ecken einen Würfel, den wir dann via Linksetfloater auf Exclusion Volume setzen. Wichtig: Die Würfel dürfen nicht mit der Konstruktion verlinkt werden, sonst kann man ihnen keine eigenen Parameter zuweisen.

    Die Würfel müssen auch etwas abgesenkt werden und nicht einfach auf der Rampe stehen, sie müssen sich mit der Navmesh schneiden, und diese verläuft etwa 12 cm unter der Oberfläche. Nach Abspeichern und Rebacken der Navmesh, sieht sie jetzt so aus:

    [​IMG]

    Das Problemdreieck habe ich hervorgehoben. Man sieht deutlich den Ausschnitt, den die Würfel ausgefräst hat. Lassen wir jetzt den Pendler probelaufen, läuft er ohne Problemme um die Würfel herum. sogar mit 15µs auf der Abstiegstelle:

    [​IMG]

    Allerdings, weil die untere Coni untrhalb der Brücke sind, verläuft der Pfad am unteren Rampenende sehr nah zum Rand. Treffen sich hier mehrere Chars auf einem Pfad, können sie sich von der Rampe schubsen, dann sitzen sie verwirrt in der Ecke.

    Ansatz 2.

    Um das zu vermeiden, verlängen wir die Würfel und machen eine Wand daraus, die die ganze Seite der Rampe mit einem Tabubereich schützt:

    [​IMG]

    Der Schutzbereich verdrängt den Pfad vom Rand zur Mitte, die Gefahr für die Chars, sich zu schubsen, ist kleiner geworden. Aber nicht völlig gebannt: Da der Schutzbereich duch einen Phantomprim realisiert ist, kann er die Chars nicht auf der Rampe halten, falls es auf einmal zuviel davon wird. Eine andere Möglichkeit bietet da die Einstellung "Static Obstacle" für die Schutzwände, sie schneidet dann ebenfalls einen Loch im Navmesh, ist zudem auch solid und kann zur Not die Chars leiten. Allerdings steigt die Prozessorzeit der Chars von 15µs auf 19µs, sobaid der Schutzbereich auf Static Obstacle umgestellt wird. Ich führe die Beobachtung darauf zurück, dass jetzt mehr Kollisionen berechnet werden müssen.

    Egal, wir lassen die Schutzwände auf Exclusion Volume und machen sie unsichtbar. Dadurch können sie nur die Chars sehen und spüren. In der Regel wird man bei solchen Gängen diese beidenseitig schützen: Wären die untere Coni draußen, müsste man die Außenseite schützen und man weiß nicht immer wie konkrete Pfade verlaufen werden. Bei nachfolgenden Abbbildungen sind die Schutwände jedenfalls unsichtbar verbaut.

    Verkehrsinsel.

    Wir setzen hier noch eins drauf, und rollen einen Teppich aus, den die Biene, also der Pendler, gefällichst nicht überfliegen sollte. Wie erreicht man das? Genauso, man setzt den Teppich auf Excluxive Volume. Ist der Teppichprim soweit abgesenkt dass er sich mit der Navmesch schneidet, entsteht in dieser ein Fenster:

    [​IMG]

    Der Pendler nimt jetzt brav einen Umweg um den Teppich herum (gelber Pfad), obwohl dieser Umweg über einen 1m breiten Streifen verläuft. Der Teppichbereich wird nicht beteten, obwohl phantom:

    [​IMG]


    11. Material Volume

    Der Materialbereich ist auch phantom und ist auch für Characters betretbar. Dabei ist es möglich, die Begehbarkeit des Linksetbereichs zu ändern, und somit die Geschwindigkeit der Pfade zu beeinflussen, und damit den Pfadverlauf selbst.

    Es ist nämlich so, dass die Charactrs aus allen möglichen Pfaden den günstigsten nehmen. Und wie teuer ein Pfadabschnitt ist, entscheiden die Begehbarkeitsparameter. Anders ausgedruckt: Sie sagen aus, wie stark der Char bestimmten Typs auf dem Pfadabschnitt abgebremst werden soll. Die Characters suchen den Weg aus, auf dem sie am wenigsten abgebremst werden.

    Genau dazu machen wir jetzt einen Versuch. Wir rollen den Teppich zur seite und machen daraus einen langen Wegabschnitt. Auf diesem Abschnitt soll der Char vom Typ B es viermal teuer/schwieriger/langsamer haben, während der Char vom Typ C ungebremst bewegen kann. Auf der Rampe selbst soll das genau umgekehrt sein. Dazu muss die Versuchsanordung so eingestelt werden:

    [​IMG]

    • Der umfunktionierte Teppich ist jetzt Material Volume, Chartyp B und C erhalten die Walkability von 25% und 100%.
    • Die Rampenkonstruktion bleibt Walkable, Charactertyp B und C erhalten die Walkability von 100% und 25%.

    Ein Blick in die Navmesh: Der Wegabschnitt ist da ganz deutlichzu sehen.

    [​IMG]

    Die Pendler mit der Einstellung des Charactertyps haben wir noch vom letten Tag (wenn nicht, bitte zum Abschnit 9 zurückscrollen.) Der Probelauf bestätigt die Behauptung:

    [​IMG]

    • Der blaue Char vom Typ B meidet den Wegabschnitt, da er dort höhere Bewegungskosten hat.
    • Der grüne Char vom Typ C ist vom Wegabschnitt regelrecht angezogen, er kann sich dort wesentlich schneller bewegen.

    Materialbereiche sind übrigens der einzige Weg, auf dem Simboden die Begehbarkeit festzulegen, dort hat man ja keine Rampe, die man im Linksetfloater auswählen kann um die Werte zu setzen.

    Somit sind wir fast am Ende des 3ten Teil. Es gilt noch kurz die Skyboxen zu untersuchen, vor allem wie hoch kann eine Skybox hängen damit die Chars immer noch laufen können, dann kann es weiter mit der Biene gehen.

    LG
    Jenna
     
    Zuletzt bearbeitet: 4. August 2013
  4. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Teil 3: Einrichtung der Umgebung (Abschluss)

    So, da wäre der letzte Abschnitt des Teil 3, der momentan recht kurz ausfällt.


    12. Skyboxen


    Also Ziel dieses Abschnitts ist zu untersuchen, ob und wie die Skyboxen konfiguriert werden können, damit die Chars dort auch laufen können. Die Antwort ist eigentlich ja, Pathfinding geht auch auf Skyboxen, man braucht die Prims einfach auf "Walcable" einzustelen, schon können die Chars darauf laufen. Nur leider wird dieses Abschnitt nur kurz, es gibt einen Bug, der im aktuelen Servercode noch vorhanden ist und es gerade der Art wie unser Char initialiwiert wird, es nicht möglich macht: Solange die Chars keine Änderung der Länge durchführen, können sie sich auf der Skybox prima initialisieren und laufen. Aber sobald die Höhenupdates im Spiel sind (was zum Landen auf den Blumen ja erforderlich ist). spielt die Kollisionskapsule des Chars verrückt.

    Mal hängt der char irgendwo in der Luft, mal fällt durch die Plattform hindurch, mal liegt am Boden der Skybox obwohl es 5m darüber sein soll. Der Bug ist hier vorgestellt:

    https://jira.secondlife.com/browse/PATHBUG-187?

    Bis der Bug beseitigt ist, bleibt der Abschnitt kurz, oder falls der Vorhaben mit der Höhenkorrektur gar nicht geht, dann editiere ich diesen Post und schreibe das auch rein. Aber ich gehe davon aus, dass der Char sich auf jeder Navmesh identisch verhalten soll, ob sie auf dem Simboden ist oder 4000m Höhe.


    Ich mache dann aber mit dem vierten Teil des Tutorials weiter.
     
    Zuletzt bearbeitet: 1. September 2012
  5. JointVenture Resident

    JointVenture Resident Aktiver Nutzer

    Beiträge:
    101
    Zustimmungen:
    0
    Punkte für Erfolge:
    0
    Hallo Jenna, Thema Skybox/bauplatte genau das hindert mich grade daran das alles auszuprobieren. Könntest du bitte auch ein kleines Beispiel ohne das Höhenupdate posten? LG

    Falls du in SL online bist, würde ich dir gerne ein kleines Geschenk überreichen.
    Ich hoffe das macht auch das Höhenupdate für dich unnötig! :)
    Snapshot_001.jpg
    Die Biene ist ca. 1.4lm hoch und würde theoretisch ohne irgendein Update auskommen
    Ps: Flügel sind animiert, sound müsste noch
     
    Zuletzt bearbeitet: 17. Oktober 2012
  6. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Hallo JointVenture

    Achso, so sieht sie aus, sieht ganz gut aus, muss ich aber noch annehmen wenn ich on komme, danke dir :)

    So in etwa wollte ich die auch machen, genauer habe ich bereits ein Sculpty (5 Prims) in Hexagon gemacht, wollte als ein Mesh in Blender machen, dafür hatte ich auch geübt. Meine Fragen in dem Mesh-Unterforum hatten die Biene im Hinterkopf.

    Das Problem mit dem Höhenupdate besteht leider immer noch, der Jira Beitrag war auch gestern noch unbeantwortet und der Test hat es bestätigt. Daher hatte ich mir eine andere Lösung überlegt wie man auf die Blume landet, ohne die Charhöhe anpassen zu müssen, es müsste gehen wenn die Biene nur 1 Prim ist, diese als Child zu machen und gegenber Root verschieben, welches den Char bildet. Muss ich noch testen ob das funktioniert, um da Gewissheit zu bekommen.

    Allerdings hatte ich gestern beim Test (in Beta) eine Art Work-around entdeckt. Also ich beschreibe kurz das Problem.

    Ich mache eine schwebende Platform ohne Verbindung zu Boden, ein Prim der Größe (40, 40, 0.5), und deklariere es als Walkable (via Linksetfloaters.) Nachdem ich die Navmesh upgedatet habe (Rebake Region) kann ich die Platform sehen, als Walkable. Soweit in Ordnung.

    Jetzt rezze ich einen Würfel darauf und lege da ein einfaches Skript:

    Code:
    default {
        state_entry() {
            llCreateCharacter([
                CHARACTER_LENGTH, 10.0
            ]);
        }
    }
    Wenn ich das Char dann betrachte, sehe ich wie es über der Platform schwebt, weil es auf der Pillle (die Capsule) steht:

    char10mOk.jpg

    Das war aber ohne Höhenupdate. Das Zirkus beginnt erst beim Höhenupdate. Also lösche ich den Würfel und erstelle einen neuen, mit diesem Skript drin:

    Code:
    default {
        state_entry() {
            llCreateCharacter([
                CHARACTER_LENGTH, 1.0
            ]);
            
            llUpdateCharacter([CHARACTER_LENGTH, 10.0]);
        }
    }
    Hier wurde das Char mit 1m Höhe erstellt und auf 10m upgedated. Das scheint die Sim aber nicht zu kümmern, die Capsule läuft durch die Platform, also die walkable Oberfläche, durch wie Butter:

    char1to10m.png

    Umgekehrt kann man die Höhe erst mit 10m initialisieren und dann auf 1m setzen, was eigentlich die Art wie die unsere Biene iitialisert wurde. Wieder ein neuer Würfel mit diesen Skript:

    Code:
    default {
        state_entry() {
            llCreateCharacter([
                CHARACTER_LENGTH, 10.0
            ]);
            
            llUpdateCharacter([CHARACTER_LENGTH, 1.0]);
        }
    }
    Das Char fällt dabei durch die Platform durch:

    char10to1m.png

    Das geht natürlich nicht. Also die eine Lösung wäre, auf die Höhenupdate ganz zu verzichten.

    Das Workaround das ich entdeckt habe, ist, mit dem Höhenupdate kurz zu warten, bis das Character auf die Endhöhe gehievt wurde und die Sim das irgendwo bei sich merkt, oder die PF Engine. Dieser Script scheint den Bug abzwenden:

    Code:
    default {
        state_entry() {
            llCreateCharacter([
                CHARACTER_LENGTH, 10.0
            ]);
            
            llSleep(5.0);
            llUpdateCharacter([CHARACTER_LENGTH, 1.0]);
        }
    }
    Neu ist nur eine Zwangspause von 5s, dann scheint die Sim den Char bzw. seine Capsule irgendwie mitzubekommen. 2s reichen da nicht, obwohl der Würfel optisch innerhalb einer Sekunde auf die Position schwebt, 3s haben aber funktioniert, ich habe daher etwas mehr gegeben. Aber schön ist dieser Workaround nicht.

    Eigentlich war das Höhenupdate (von 10m nach Zielhöhe) gleich nach dem Erstellen bereits ein Workaround, sonst wollte das Char manchmal nicht navigieren, wenn man die Höhe zu hoch ändert. Das neue Workaround ist also Workaround des Workarounds :grin:

    Daher versuche ich das mit dem Primverschieben. Aber erst schaue ich Deine Biene an :)
     
    Zuletzt bearbeitet: 23. Oktober 2012
  7. Jenna Felton

    Jenna Felton Superstar

    Beiträge:
    1.995
    Zustimmungen:
    57
    Punkte für Erfolge:
    64
    Teil 4: Neue Hovermethode

    Hallo, jetzt folgt eine kleine Fortsetzung. Zwar nicht so forgeschritten wie geplannt, aber etwas weiter. Der oben angesprochene Bug wird anscheinend bearbeitet. Ich kann jedenfalls keine Kommentare mehr hinzufügen, also ist er in Berbeitung bei LL. Kann deshalb sein, dass die Höhenanpassung auch in einer Skybox oder auf Platformen funktionieren wird.

    Aber JointVenture hat vorgeschlagen, das Landen der Biene per Animation durchzuführen, das heißt indem die Prims des Bienenkörpers gegenüber dem Rootprim, welches den Char bildet, verschoben wird. Das macht zwar etwas mehr Arbeit, besonders wenn der Körper aus mehreren Prims besteht, aber ist derzeit die einzige überall funktionierende Lösung. Außerdem ermöglicht sie, dass die Blume bzw. der Bienenstock 10m über dem Boden hängen kann, alte Methode könnte nur 5m erreichen, weil der Char maximal 10m lang sein kann.

    In diesem Teil wird diese Lösung implemntiert und das Char so wie der Pendelskript angepasst.


    1. Markierungsskript


    Der Markierungsskript bleibt wie in #6, Abschnitt. 2, das heißt man kann problemlos die Koni vom letzten Teil übernehmen. Zur Erinerung, ihre Spitzen representieren die Blumen, also Punkte zum Landen. Der Markierungsskript meldet an den Charskript die Koordinate auf dem Navmesh und die Höhe des Landepunktes darüber, indem das Char diese Höhe einnimmt, landet er visuel.


    2. Charskript


    Dieser ist neu. Im Grunde ist der Skript dem letzten Pendler ännlich. Die wichtigste Änderung ist, die neue Funktion hoverHeight(float height), welche die Höhe anpasst und rausgeschmissene llUpdateCharacter() - Aufrufe (eines ist durch hoverHeight() ersetzt.) Außerdem wird die Charhöhe gleich relativ klein festgelegt und bleibt auch so.

    Ferner wird die vom Markerungsskript gemeldete Höhenangabe etwas anders gespeichert, und die Konstante VERBOSE schaltet das Labbern ein oder aus.

    Code:
    integer PFWPC    = 1606231603;
    
    float   HALFLEN  = 0.2;
    integer VERBOSE  = TRUE;
    
    list    lTargets = []; // [(key object)*]
    list    lCoords  = []; // [(vector pos)*]
    list    lHeights = []; // [(float height)*]
    
    integer gTargNum = -1;
    key     kTarget  = NULL_KEY;
    vector  vTarget;
    float   fHeight;
    
    // --- ----------------------------------------------------
    
    goToTarget(integer targNum) {
        gTargNum = targNum;
        if (gTargNum >= llGetListLength(lTargets)) gTargNum = 0;
    
        kTarget = llList2Key(lTargets, gTargNum);
        vTarget = llList2Vector(lCoords, gTargNum);
        fHeight = llList2Float(lHeights, gTargNum);
    
        if (VERBOSE) {
            llOwnerSay("Visit "+llKey2Name(kTarget)
                +" at "+(string)vTarget);
        }
    
        llNavigateTo(vTarget, []);
    }
    
    hoverHeight(float height) {
        height = height - HALFLEN;
        llSetLinkPrimitiveParams(2,
            [PRIM_POS_LOCAL, <0.0, 0.0, height>]);
    }
    
    // --- ----------------------------------------------------
    
    default {
        state_entry() {
            llSay(0, "Hello World");
            
            llDeleteCharacter();
            llCreateCharacter([
                CHARACTER_MAX_SPEED,          3.0,
                CHARACTER_DESIRED_SPEED,      2.0,
                CHARACTER_RADIUS,             0.125,
                CHARACTER_LENGTH,             HALFLEN*2.0,
                CHARACTER_AVOIDANCE_MODE,     AVOID_CHARACTERS,
                CHARACTER_DESIRED_TURN_SPEED, 3.0,
                CHARACTER_MAX_TURN_RADIUS,    0.5
                ]);
    
            llListen(PFWPC, "", NULL_KEY, "");
            llShout(PFWPC, "pf.waypoints?");
        }
        on_rez(integer start_param) {
            llResetScript();
        }
    
        // message = "pf.waypoint:<x, y, z>|h"
        listen(integer channel, string name, key id, string message) {
            if (llGetSubString(message, 0, 11) == "pf.waypoint:") {
                message = llGetSubString(message, 12, -1);
    
                list tmp = llParseString2List(message, ["|"], []);
    
                vector target = (vector)llList2String(tmp, 0) - llGetRegionCorner();
                float  height = (float)llList2String(tmp, 1);
                if      (height < 0.0)  height = 0.0;
                else if (height > 10.0) height = 10.0;
    
                // Korrigiere die Zielkoordinate auf die exakte
                // Position des char-Prims (0.5m über dem Boden)
                target.z = target.z + HALFLEN;
    
                channel = llListFindList(lTargets, [id]);
                if (channel < 0) {
                    lTargets += [id];
                    lCoords  += [target];
                    lHeights += [height];
                }
                else {
                    lCoords  = llListReplaceList(lCoords,  [target], channel, channel);
                    lHeights = llListReplaceList(lHeights, [height], channel, channel);
                }
    
                if (id == kTarget) {
                    vTarget = target;
                    fHeight = height;
                    llNavigateTo(vTarget, []);
                }
                
                channel = (integer)llGetListLength(lTargets);
                llSetText((string)channel+" points", <1.0, 1.0, 1.0>, 1.0);
            }
        }
    
        touch_start(integer total_number) {
            if (llDetectedKey(0) == llGetOwner() && lTargets != []) {
                llSetTimerEvent(0.0);
                if (gTargNum < 0) goToTarget(0);
                else {
                    llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
                    gTargNum = -1;
                    kTarget  = NULL_KEY;
                }
            }
        }
    
        path_update(integer update, list reserved) {
            // We are near target.
            if (update == PU_SLOWDOWN_DISTANCE_REACHED) {
                if (gTargNum > -1) llSetTimerEvent(10.0);
            }
            
            // We are at target.
            if (update == PU_GOAL_REACHED) {
                llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
    
                if (gTargNum > -1) {
                    llSetRegionPos(vTarget);
                    hoverHeight(fHeight);
    
                    llSetTimerEvent(10.0);
                }
            }
    
            // Navigation failed. Try direct
            else if (update == PU_FAILURE_INVALID_START) {
                llNavigateTo(vTarget, [FORCE_DIRECT_PATH, TRUE]);
            }
    
            // Otherwise, the bee is lost
            else {
                llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
            }
        }
    
        timer() {
            llSetTimerEvent(0.0);
            goToTarget(gTargNum+1);
        }
    }

    3. Versuchsanordnung


    Ich habe desen Charskript mit der Rampe getestet, der funktioniert, da sind die Koni aber gleich hoch, die Höhe wird also nicht angepasst. Das werde ich hier deshalb nicht mehr wiederholen. Stattessen wird eine etwas andere Anordng aufgebaut. Der Sinn ist dabei, die neue Höhenanpasung zu prüfen, deshalb werden vier Koni gerezzt und unterschiedlich hoch skalliert. Den Alpha habe ich auf 10m Höhe gestellt, also die zunächst maximale angestrebte Höhe. Dazu noch ein kleines Hindernis, damit die Route nicht so langweilig wird:

    [​IMG]

    Die Koni haben verschiedene Farben bekommen, das weiße Alpha ist 10m hoch. Den Rahmen sollte man per Floater auf Static Obstacle setzen, oder Exclusion Volume (sollte das eine begehbare Hecke sein, die von der Biene herumzufliegen ist), tut man das nicht, ist der Rahmen dem Navmesh nicht bekannt und das Char bleibt in der Ecke hängen.


    4. Charobjekt


    So, neben der inneren Koni wird das Char aufgebaut. Er besteht aus einem (später unsichtbaren) Rootprim, das eigentlich der Char ist, und dem Childprim, das den sichbaren Bienenkörper repreäsentiert. Der Skript geht zunächst davon aus, dass es nur diese zwei Prims sind. Der Rootprim wird später unsichtbar, aber jetzt habe ich ihn wie Schatten da gelasen. Nachdem beide verlinkt wurden, geht da der Skript rein:

    [​IMG]

    Der sollte sich gleich initialisieren, alle Markierungspositionen empfangen haben und etwa auf die Höhe von 20cm über dem Boden schweben (die Konstante HALFLEN gibt die konstante Schwebehöhe des eigentlichen Chars an.)


    5. Bienenflug


    So, jetzt das Baumenu schließen und den Char anklcken. Er fliegt zunächst zu Alpha (diesem 10m hohen Konus, die Route habe ich ausgelassen) und dann um dien Zaun herum zu Beta (roter Konus.) Die hohe Flughöhe behällt sie bei. Erst wenn angekommn, stürzt die Kugel auf den Konus:

    [​IMG]

    Fragt mich nicht, warum da so weiter Umweg genomen wurde, anscheinend hatte die Navmesh der Sim was an der Stelle, ich blieb aber an der Position mit der Anordung.

    Beim roten Konus angekommen, spring die Kugel zunächst auf den blauen, dann gelben, und dann setzt sich in den Flug richtung Alpha. Wieder über die komische weite Route:

    [​IMG]

    Danach schließt sich der Kreislauf.

    Wie man sieht, fliegt die Biene den Zaun um, obwohl sie optisch daüber fliegen könnte. Man könnte das vielleicht dadurch erreichen, dass man den Zaun als Material Volume setzt. Je nach der Umgebung, das könnte auch eine Hecke sein. Dann kann man selbst zwar dadurch laufen, die Biene könnte man aber sogar abbrremsen, wenn man die Hecke richtig parametrisiert.


    LG und danke für die Geduld mit dem Tutorial lesen :)
     
    Zuletzt bearbeitet: 4. August 2013