使用FastObjImporter在场景上加载和显示obj模型

问题描述 投票:0回答:1

在我的Unity项目中,我想使用互联网上的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;
        }
}

问候

c# object unity3d import
1个回答
2
投票

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

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

我注意到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的功能,加载模型并将所有必要的组件附加到它上面以显示它:

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”文件夹中。

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

在上面的createMaterial函数中,

更改

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

Material mat = Resources.Load("StandardMat") as Material;
© www.soinside.com 2019 - 2024. All rights reserved.