【问题标题】:Can't create collision mesh for a child gameobject无法为子游戏对象创建碰撞网格
【发布时间】:2019-01-08 02:35:16
【问题描述】:

我正在创建 fbx 处理脚本来更改某些网格参数,创建预制件并自动添加碰撞网格。现在我被困在尝试将碰撞网格组件添加到我的游戏对象的某些子对象中。 但到目前为止还没有运气。我有一条错误消息 “无法将组件 'MeshCollider' 添加到 UCX_SM_bench_1_LOD0,因为游戏对象是生成的预制件,只能通过 AssetPostprocessor 进行修改。” 我正在使用 Unity 2017.1。

我是一名 3D 艺术家,这是我第一次尝试编写脚本。

using System;
using System.IO;
using UnityEngine;
using UnityEditor;

public class ModelAssetPostprocessor : AssetPostprocessor
{
public void OnPreprocessModel()
{
    ModelImporter modelImporter = assetImporter as ModelImporter;
    modelImporter.importAnimation = false;
    modelImporter.importBlendShapes = false;
    modelImporter.importCameras = false;
    modelImporter.importVisibility = false;
    modelImporter.importLights = false;
    modelImporter.importTangents = ModelImporterTangents.Import;
}
private const string PREFAB_DESTINATION_DIRECTORY = "Assets/Prefabs/";//setting up constant for prefabs destination directory

private static void OnPostprocessAllAssets(
    string[] importedAssets,
    string[] deletedAssets,
    string[] movedAssets,
    string[] movedFromAssetPaths)           
{
    foreach (string path in importedAssets) 
    {
        if (!path.EndsWith(".fbx", StringComparison.OrdinalIgnoreCase)) //skipping all the files, which are not .fbx
            continue;

        GameObject modelAsset = AssetDatabase.LoadAssetAtPath<GameObject>(path);    //As far as I understand here we declare local variable "modelAsset"
                                                                                    //It will become GameObject, which took from AssetDatabase using path we saved before. So
                                                                                    //Now we have a GameObject. 
        CreatePrefabFromModel(path, modelAsset);
        //And now we declare a function to create prefab from our game object
    }
}

private static void CreatePrefabFromModel(string path, GameObject modelAsset)
{
    EnsureDirectoryExists(PREFAB_DESTINATION_DIRECTORY);

    string modelFileName = Path.GetFileNameWithoutExtension(path);
    string destinationPath = PREFAB_DESTINATION_DIRECTORY + modelFileName + ".prefab";

    if (!File.Exists(destinationPath))
    {
        GameObjectUtility.SetStaticEditorFlags(modelAsset, StaticEditorFlags.LightmapStatic | StaticEditorFlags.NavigationStatic | StaticEditorFlags.BatchingStatic | StaticEditorFlags.OccludeeStatic | StaticEditorFlags.OccluderStatic | StaticEditorFlags.OffMeshLinkGeneration | StaticEditorFlags.ReflectionProbeStatic);

        foreach (Transform child in modelAsset.transform)
        {
            if (child.transform.name.Contains("UCX_"))
            {
                Renderer rend;
                rend = child.GetComponent<Renderer>();
                rend.enabled = !rend.enabled;

                string childname = child.transform.name;

                      GameObject childobject = modelAsset.transform.Find(childname).gameObject;
                      childobject.AddComponent<MeshCollider>();
            }
        }
        PrefabUtility.CreatePrefab(
            destinationPath,
            modelAsset);
    }
    else
    {
        PrefabUtility.ReplacePrefab(
            modelAsset,
            AssetDatabase.LoadAssetAtPath<GameObject>(destinationPath),
            ReplacePrefabOptions.ReplaceNameBased);
    }
}
private static void EnsureDirectoryExists(string directory)
{
    if (!Directory.Exists(directory))
        Directory.CreateDirectory(directory);
}
}   

【问题讨论】:

  • 您是否尝试过修改您的预制件实例,然后用它替换您的预制件?

标签: c# unity3d


【解决方案1】:

我不知道你想达到什么目的,但首先,尝试检查模型导入中的Generate Colliders 复选框(https://docs.unity3d.com/Manual/FBXImporter-Model.html)也许它会解决你所有的问题。

Image

第二个建议 - 更新统一(不,您的脚本将无法工作,但拥有新版本总是更好的方法)

根据您最初的要求。我只能建议(统一代码 2018.3):

var go = GameObject.Instantiate(modelAsset);

GameObjectUtility.SetStaticEditorFlags(modelAsset, (StaticEditorFlags)(-1));

foreach (Transform child in go.transform)
{
    if (child.name.Contains("UCX_"))
    {
        Renderer rend;
        rend = child.GetComponent<Renderer>();
        rend.enabled = !rend.enabled;

        child.gameObject.AddComponent<MeshCollider>();
    }
}

PrefabUtility.SaveAsPrefabAsset(go, destinationPath);
GameObject.DestroyImmediate(go);

我稍微修改了你的脚本。现在网格将首先被实例化,并且预制件将从实例化的对象中创建,而不是从资产中创建。

出现错误的原因是:您正在尝试修改fbx 文件,就像它是一个场景对象一样。你应该先实例化它,然后做任何你想做的改变,然后将它保存为预制件。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 2016-09-11
  • 1970-01-01
相关资源
最近更新 更多