【问题标题】:Load and display obj model on the scene with FastObjImporter使用 FastObjImporter 在场景中加载和显示 obj 模型
【发布时间】:2017-12-18 19:56:26
【问题描述】:

在我的 Unity 项目中,我想使用在 Internet 上找到的 FastObjImporter 类将 obj 放在场景中。我是否必须创建一个空的 GameObject 并将已处理的 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;

谁能解释我做错了什么?

代码:

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;
        }
}

问候

【问题讨论】:

  • 我在start中初始化了objPath
  • objPath = Application.persistentDataPath + "/testObj.obj";
  • 这是安卓手机应用
  • 好的,抱歉。在我的应用程序中,我从谷歌驱动器下载 obj 文件并将其保存在此位置。所有作品,当我下载 jpg 并在立方体中用作 maintexture 时,但我不知道如何将 obj 放在场景中。
  • 是的,我想在屏幕上显示加载的模型。

标签: c# object unity3d import


【解决方案1】:

无需实例化网格。它是一个组件,我不确定您是否可以实例化它。只需将其分配给材质即可。

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

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

创建MeshFilder、Material 和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));
}

编辑:

在极少数情况下,当使用Shader.Find("Standard") 时,Unity 无法在 Android 上找到着色器。发生这种情况时,您会收到错误消息。

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

1。创建一个材质,名称为“StandardMat”。

2。将该材料放入名为“Resources”的文件夹中。如果它不存在,请创建它。您必须正确拼写。同样,该文件夹必须命名为“Resources”并放置在“Asset”文件夹中。

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

在上面的createMaterial函数中,

改变

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

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

【讨论】:

  • 我必须添加 MeshFilter 和 MeshRenderer 来清空场景中的 GameObject "Loaded Mesh"?
  • 我按照说明做了一切,但它不起作用。调试器中没有错误。最初,错误是由于我的错,因为我没有向游戏对象添加材质。
  • 发现问题。原来导入器没有创建前墙(我导入了立方体),剩下的墙很薄,在场景中看不到。
  • @RobertPiotrowski 你是怎么解决的?我使用的是固定代码,但 Unity 根本不显示对象,无论我使用什么着色器(我在 PC 上测试,而不是 Android)。
猜你喜欢
  • 2020-08-02
  • 2018-08-06
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 2013-04-26
相关资源
最近更新 更多