Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Zendee

unregistriert

1

09.02.2012, 11:10

Unity3D: Ein in Blender erstelltes Modell in Unity als Terrain importieren

Ich möchte in Unity ein Modell importieren, das mit Blender erstellt wurde, und als Terrain dient. Ich habe zwar ein Script gefunden, nur dies Funktioniert nicht wirklich. Es geschieht zwar was, aber das Terrain nimmt nicht die Form des Modelles an. Ich will nämlich eine Art "UFO" als Terrain. Oder versteh ich das Script falsch? Gibt es eine andere Lösung?

Hier das Script:

Quellcode

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
@MenuItem ("Terrain/Object to Terrain")
static function Object2Terrain () {
    // See if a valid object is selected
    var obj = Selection.activeObject as GameObject;
    if (obj == null) { 
        EditorUtility.DisplayDialog("No object selected", "Please select an object.", "Cancel");
        return;
    }
    if (obj.GetComponent(MeshFilter) == null) {
        EditorUtility.DisplayDialog("No mesh selected", "Please select an object with a mesh.", "Cancel");
        return;
    }
    else if ((obj.GetComponent(MeshFilter) as MeshFilter).sharedMesh == null) {
        EditorUtility.DisplayDialog("No mesh selected", "Please select an object with a valid mesh.", "Cancel");
        return;     
    }
    if (Terrain.activeTerrain == null) {
        EditorUtility.DisplayDialog("No terrain found", "Please make sure a terrain exists.", "Cancel");
        return;
    }   
    var terrain = Terrain.activeTerrain.terrainData;
    
    // If there's no mesh collider, add one (and then remove it later when done)
    var addedCollider = false;
    var addedMesh = false;
    var objCollider = obj.collider as MeshCollider;
    if (objCollider == null) {
        objCollider = obj.AddComponent(MeshCollider);
        addedCollider = true;
    }
    else if (objCollider.sharedMesh == null) {
        objCollider.sharedMesh = (obj.GetComponent(MeshFilter) as MeshFilter).sharedMesh;
        addedMesh = true;
    }
    
    Undo.RegisterUndo (terrain, "Object to Terrain");

    var resolutionX = terrain.heightmapWidth;
    var resolutionZ = terrain.heightmapHeight;
    var heights = terrain.GetHeights(0, 0, resolutionX, resolutionZ);
    
    // Use bounds a bit smaller than the actual object; otherwise raycasting tends to miss at the edges
    var objectBounds = objCollider.bounds;
    var leftEdge = objectBounds.center.x - objectBounds.extents.x + .01;
    var bottomEdge = objectBounds.center.z - objectBounds.extents.z + .01;
    var stepX = (objectBounds.size.x - .019) / resolutionX;
    var stepZ = (objectBounds.size.z - .019) / resolutionZ;
    
    // Set up raycast vars
    var y = objectBounds.center.y + objectBounds.extents.y + .01;
    var hit : RaycastHit;
    var ray = new Ray(Vector3.zero, -Vector3.up);
    var rayDistance = objectBounds.size.y + .02;
    var heightFactor = 1.0 / rayDistance;
        
    // Do raycasting samples over the object to see what terrain heights should be
    var z = bottomEdge;
    for (zCount = 0; zCount < resolutionZ; zCount++) {
        var x = leftEdge;
        for (xCount = 0; xCount < resolutionX; xCount++) {
            ray.origin = Vector3(x, y, z);
            if (objCollider.Raycast(ray, hit, rayDistance)) {
                heights[zCount, xCount] = 1.0 - (y - hit.point.y)*heightFactor;
            }
            else {
                heights[zCount, xCount] = 0.0;
            }
            x += stepX;
        }
        z += stepZ;
    }
    
    terrain.SetHeights(0, 0, heights);
    
    if (addedMesh) {
        objCollider.sharedMesh = null;
    }
    if (addedCollider) {
        DestroyImmediate(objCollider);
    }
}


Danke!

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

2

09.02.2012, 11:25

Das normale Terrain in Unity besteht NUR aus Höhendaten, du kannst also nicht davon ausgehen dass dein Terrain die Form eines Ufos annimmt.

Das Script misst einfach nur die Entferung deines Models zum "Meeresspiegel" in einem Raster, diese Entfernung wird dann als Höheninformation für die Heightmap des Terrains verwendet.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

09.02.2012, 11:26

Kenne mich mit Unity nicht aus, aber das sieht auf den ersten Blick für mich so aus, als wenn eine Heightmap erstellt wird. Von daher wäre dein Modell nicht komplett erhalten, sondern nur die Oberfläche. Ansonsten zeig mal vielleicht Screenshots.

edit: Zu spät:D
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

4

09.02.2012, 11:33

Was er vorhat ist auch überhaupt nicht möglich mit dem Standard Unity Terrain, es kann nur Höhendaten. Es gibt allerdings entsprechende Assets die das wiederum können.
Die Voxeltools zB (kA wie die grade wirklich heißen). Damit wäre sowas möglich.

Wieso genau planst du überhaupt ein Ufo als Terrain zu verwenden? Du willst darauf herumlaufen können?

mio991

Frischling

Beiträge: 6

Beruf: FIAE Ausbildung

  • Private Nachricht senden

5

09.02.2012, 11:42

Ich kenne mich mit Unity zwar auch nur begrenzt aus aber mein Tip währe das Ufo als Model einzubinden und dann einfach in die göße zu zihen die man brauch.

Zendee

unregistriert

6

09.02.2012, 11:50

Es sollte wie die fliegende Stadt aus Star Wars aussehen ;-). Also eher indirekt ein UFO.
Kann ich ein Modell einfach als Terrain "missbrauchen"?

mio991

Frischling

Beiträge: 6

Beruf: FIAE Ausbildung

  • Private Nachricht senden

7

09.02.2012, 11:57

Ich denke schon. :D

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

8

09.02.2012, 12:16

Ich gehe mal davon aus dass die Unterseite deines Ufos eher keine Rolle spielt beim laufen auf dem Ufo (du planst ja vermutlich keine Gravitationsspielereien), daher gäbe es da verschiedene Möglichkeiten:

A) Du nutzt MeshCollider, hat den Nachteil dass diese recht langsam sind und auch vielen Begrenzungen unterliegen. Willst du dass andere MeshCollider mit diesem MeshCollider kollidieren kann so musst du <=255 Triangles im Collidermesh haben und den Collider auf Convex stellen.

B) Du benutzt einen Verbund aus diversen simplen Collidern, dazu hast du dein normales Objekt und erstellst für jeden Collider ein leeres GameObject welches du als Child an dein größeres Objekt anhängst (das anhängen als Child kannst du dir vermutlich auch ersparen da sich deine Stadt sicher nicht beweglich sein soll wenn man gegen stößt). Hier kann Unity und die unterliegende Physikengine sehr gut optimieren, erfordert aber einiges an Setup arbeit.

C) Du spaltest dein Ufo in viele Unterobjekte auf und importierst diese separat um deine Stadt aufzubauen, jedes unterobjekt sollte dann relativ einfach mit Collidern versehen werden können zur Not wie in Fall B. Hier hast du nur mehr arbeit beim Exportieren der Modelle, die Einstellungsarbeit der Collider sollte dir dabei weitesgehenst erspart bleiben. Ein weiterer Vorteil hierbei ist, da die einzelnen Teile wirklich separat sind kannst du sie auch separat behandeln, erkennne welches Gebäude was macht, etc. Noch dazu dürfte es recht entspannt sein im umgang mit der GPU, da hier evtl mehr optimiert werden kann.

Oh und noch D) Die Objekte wie in C einzeln haben, aber alle als fbx exportieren und in Unity importieren. Unity dürfte die einzelnen Unterobjekte auch einzeln behandeln, aber schön für dich so aufbereitet dass du nur noch dein Stadtmodell in die Szene einfügen brauchst als komplette GameObject Hierarchie.

Zendee

unregistriert

9

09.02.2012, 12:32

Eine andere Möglichkeit wäre ein rundes Terrain. Nur weiß ich nicht wie ich das Terrain rund bekommen könnte.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

10

09.02.2012, 12:39

Du kannst ja einfach dein Skript mit einer Halbkugel ausführen. Dann hast du deine Rundung. Alternativ kannst du sicherlich auch selbst Heightmaps einbinden.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Werbeanzeige