本文介绍了如何销毁属于预制件的游戏对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想使用 ModifyPrefab 方法,但不确定如何使用.问题是当我销毁 oldGameObject 时:
I want to use the ModifyPrefab method but not sure how.The problem is when I'm destroying the oldGameObject :
DestroyImmediate(oldGameObject);
我在编辑器中遇到异常:
I'm getting exception in the editor :
InvalidOperationException:不允许销毁预制实例内的游戏对象.
InvalidOperationException: Destroying a GameObject inside a Prefab instance is not allowed.
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class PrefabSwitch : MonoBehaviour
{
/// <summary>The new object to instantiate in place of the old object.</summary>
public GameObject newPrefab;
/// <summary>The old objects, intended to be swapped out for iterations of
/// the new object.</summary>
public GameObject[] oldGameObjects;
/// <summary>The string tag to use when replacing objects by tag.</summary>
public string searchByTag;
/// <summary>Swaps all the game objects in oldGameObjects for
/// a new newPrefab.</summary>
public void SwapAllByArray(GameObject[] objectsToSwap)
{
// Store a boolean to detect if we intend to swap this game object.
bool swappingSelf = false;
// For each game object in the oldGameObjects array,
for (int i = 0; i < oldGameObjects.Length; i++)
{
// If the current game object is this game object,
if (oldGameObjects[i] == gameObject)
{
// Enable the flag to swap this game object at the end, so we
// do not destroy it before the script an complete its task.
swappingSelf = true;
}
else
{
// Else, we are not dealing with the game object local to this
// script, so we can swap the prefabs, immediately.
SwapPrefabs(oldGameObjects[i]);
}
}
// If we have flagged the local game object to be swapped,
if (swappingSelf)
{
// Swap the local game object.
SwapPrefabs(gameObject);
}
}
/// <summary>Swaps all the game objects that use the tag <code>searchByTag</code>.
/// If empty, we will use the tag of the local game object.</summary>
public void SwapAllByTag()
{
// If searchByTag is null,
if (searchByTag == "")
{
// Set searchByTag to the tag of the local game object.
searchByTag = gameObject.tag;
}
// Find all the game objects using the tag searchByTag,
// store them in our array, and proceed to swapping them.
oldGameObjects = GameObject.FindGameObjectsWithTag(searchByTag);
SwapAllByArray(oldGameObjects);
}
/// <summary>Swaps the desired oldGameObject for a newPrefab.</summary>
/// <param name="oldGameObject">The old game object.</param>
void SwapPrefabs(GameObject oldGameObject)
{
// Determine the rotation and position values of the old game object.
// Replace rotation with Quaternion.identity if you do not wish to keep rotation.
Quaternion rotation = oldGameObject.transform.rotation;
Vector3 position = oldGameObject.transform.position;
// Instantiate the new game object at the old game objects position and rotation.
GameObject newGameObject = Instantiate(newPrefab, position, rotation);
// If the old game object has a valid parent transform,
// (You can remove this entire if statement if you do not wish to ensure your
// new game object does not keep the parent of the old game object.
if (oldGameObject.transform.parent != null)
{
// Set the new game object parent as the old game objects parent.
newGameObject.transform.SetParent(oldGameObject.transform.parent);
}
// Destroy the old game object, immediately, so it takes effect in the editor.
DestroyImmediate(oldGameObject);
}
private void ModifyPrefab()
{
// Get the Prefab Asset root GameObject and its asset path.
GameObject assetRoot = Selection.activeObject as GameObject;
string assetPath = AssetDatabase.GetAssetPath(assetRoot);
// Load the contents of the Prefab Asset.
GameObject contentsRoot = PrefabUtility.LoadPrefabContents(assetPath);
// Modify Prefab contents.
contentsRoot.AddComponent<BoxCollider>();
// Save contents back to Prefab Asset and unload contents.
PrefabUtility.SaveAsPrefabAsset(contentsRoot, assetPath);
PrefabUtility.UnloadPrefabContents(contentsRoot);
}
}
推荐答案
这里有大量讨论:https://forum.unity.com/threads/destroying-a-gameobject-inside-a-prefab-instance-is-not-允许.555868/
这不完全是错误,而是实施 PreFab 系统的副作用.
It is not exactly a bug, but a side effect from the implementation of the PreFab system.
最佳解决方案是:
if (UnityEditor.PrefabUtility.IsPartOfPrefabInstance(transform))
UnityEditor.PrefabUtility.UnpackPrefabInstance(gameObject,
UnityEditor.PrefabUnpackMode.Completely,
UnityEditor.InteractionMode.AutomatedAction);
// Then I do DestroyImmediate();
还有这个:
var rootGO = PrefabUtility.LoadPrefabContents(pathToMyPrefab);
// Destroy child objects or components on rootGO
PrefabUtility.SaveAsPrefabAsset(rootGO, pathToMyPrefab);
prefabUtility.UnloadPrefabContents(rootGO);
这篇关于如何销毁属于预制件的游戏对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!