2017-12-18 404 views
0

在我的Unity项目中,我想使用互联网上的FastObjImporter类将obj放到场景中。我是否必须创建一个空的GameObject并将处理的obj分配给它?使用FastObjImporter在场景中加载和显示obj模型

尝试用一个空的游戏对象:

GameObject go = new GameObject("obj"); 
myMesh = FastObjImporter.Instance.ImportFile(objPath); 
Instantiate(myMesh, Vector3.zero, Quaternion.identity); 
go.AddComponent<MeshRenderer>(); 
go.GetComponent<MeshFilter>().mesh = myMesh; 

早些时候,我想这种方式,但它也没有工作:

GameObject go; 
myMesh = FastObjImporter.Instance.ImportFile(objPath); 
Instantiate(myMesh, Vector3.zero, Quaternion.identity); 
go.GetComponent<MeshFilter>().mesh = myMesh; 

有人能解释我做错了吗?

CODE:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using UnityEngine; 
using System.IO; 

/// <summary> 
/// Sample 
/// </summary> 
public class DriveTest : MonoBehaviour 
{ 
    //public static readonly string REQUIRED_MIME = "image/jpeg"; 
    //public string filePath; 
    public string objPath; 
    bool initInProgress = false; 
    GoogleDrive drive; 
    public string url; 
    List<GoogleDrive.File> remoteObjFiles; 

    public Mesh myMesh; 
    public GameObject go; 

    /* ---------------------------------------------------------------------------------------------------------------------------------- */ 
    void Start() 
    { 
     objPath = Application.persistentDataPath + "/testObj.obj"; 
     StartCoroutine(ImportObj()); 
     go = new GameObject("obj"); 
    } 

    /* ---------------------------------------------------------------------------------------------------------------------------------- */ 

    void Update() 
    { 

     if (Input.GetKey(KeyCode.Escape)) 
      Application.Quit(); 
    } 

    /* ---------------------------------------------------------------------------------------------------------------------------------- */ 

    IEnumerator ImportObj() 
    { 
     initInProgress = true; 

     drive = new GoogleDrive(); 
     var driveInit = drive.Initialize(); 
     while (driveInit.MoveNext()) 
      yield return null; 

     initInProgress = false; 

     for (;;) 
     { 
      (SEARCHING AND SETTING DOWNLOAD FOLDER IN GDRIVE) 

      var download = drive.DownloadFile(remoteObjFiles[0]); 
      yield return StartCoroutine(download); 
      var data = GoogleDrive.GetResult<byte[]>(download); 

      if (File.Exists(objPath)) 
      { 
       File.Delete(objPath); 
       File.WriteAllBytes(objPath, data); 
      } 
      else 
       File.WriteAllBytes(objPath, data); 

      Debug.Log("Obj: " + remoteObjFiles[0].ToString()); 

      if (File.Exists(objPath)) 
      { 
       Debug.Log("Loading OBJ from the device"); 
       myMesh = FastObjImporter.Instance.ImportFile(objPath); 
       Debug.Log("Obj imported..."); 
       Instantiate(myMesh, Vector3.zero, Quaternion.identity); 
       go.AddComponent<MeshRenderer>(); 
       go.GetComponent<MeshFilter>().mesh = myMesh; 
      } 
      break; 
     } 
} 

问候

+0

我在开始 –

+0

objPath = Application.persistentDataPath + “/testObj.obj” 初始化objPath; –

+0

这是Android手机应用程序 –

回答

1

没有必要实例化网格。它是一个组件,我不确定你是否可以实例化它。只需将其分配给材料。

你的代码中的主要问题是你没有创建材质和着色器。您需要创建一个材质,然后创建一个“标准”着色器并将该着色器分配给该材质。

我注意到FastObjImporter脚本是旧的,并决定尝试它来确保它正常运行。我遇到了一个索引异常错误,然后修复它。您可以获取固定版本here的副本。请参阅行#57为我所做的实际修复。

函数来创建MeshFilder,材质和MeshRenderer

void attachMeshFilter(GameObject target, Mesh mesh) 
{ 
    MeshFilter mF = target.AddComponent<MeshFilter>(); 
    mF.mesh = mesh; 
} 

Material createMaterial() 
{ 
    Material mat = new Material(Shader.Find("Standard")); 
    return mat; 
} 

void attachMeshRenderer(GameObject target, Material mat) 
{ 
    MeshRenderer mR = target.AddComponent<MeshRenderer>(); 
    mR.material = mat; 
} 

函数来创建新的游戏对象,加载模型和一切必要的组件连接到它,以显示它:

GameObject loadAndDisplayMesh(string path) 
{ 
    //Create new GameObject to hold it 
    GameObject meshHolder = new GameObject("Loaded Mesh"); 

    //Load Mesh 
    Mesh mesh = FastObjImporter.Instance.ImportFile(path); 

    //return null; 

    //Attach Mesh Filter 
    attachMeshFilter(meshHolder, mesh); 

    //Create Material 
    Material mat = createMaterial(); 

    //Attach Mesh Renderer 
    attachMeshRenderer(meshHolder, mat); 

    return meshHolder; 
} 

用法:

void Start() 
{ 
    string objPath = Application.persistentDataPath + "/testObj.obj"; 

    GameObject obj = loadAndDisplayMesh(objPath); 

    //Position it in front od=f the camera. Your ZOffset may be different 
    Camera cam = Camera.main; 
    float zOffset = 40f; 
    obj.transform.position = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.nearClipPlane + zOffset)); 
} 

编辑:

在某些罕见的情况下,团结找不到Android上的着色器在使用Shader.Find("Standard")。发生这种情况时会出现错误。

解决此问题的方法是在编辑器中创建一个材质并为其分配“标准”着色器。它应该默认使用“标准”着色器。

。创建一个材料和名称是“StandardMat”。

。将该材质放在名为“Resources”的文件夹中。如果它不存在,就创建它。你必须正确拼写。同样,该文件夹必须命名为“资源”并放置在“资产”文件夹内。

。您可以使用Resources.Load("StandardMat") as Material加载材料。

在上述createMaterial功能,

变化

Material mat = new Material(Shader.Find("Standard")); 

Material mat = Resources.Load("StandardMat") as Material; 
+0

我必须添加MeshFilter和MeshRenderer以在场景上清空GameObject“Loaded Mesh”? –

+0

我根据说明做了所有事情,但不起作用。调试器中没有错误。最初,这个错误是由于我的错,因为我没有添加材料到游戏对象。 –

+0

发现问题。原来,进口商并没有制造前墙(我输入了立方体),其余的墙壁都很薄,以至于在现场看不到。 –