Unity 一键替换场景中的物体

实现场景中批量替换预制体的编辑器功能。

一、关键api

PrefabUtility.InstantiatePrefab 将预设实例化到场景中,与GameObject.Instantiate不同,它是以预设实例的。

二、工具截图

三、使用方法

在Project中拖拽预设到工具中

打开需要操作的场景,可以多选需要替换的物体,或者输入需要替换的名字

修改完成后保存场景

四、代码

using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;

public class ObjectReplaceEditorWindow : EditorWindow
{
    [MenuItem("Tools/替换场景中的物体")]
    public static void Open()
    {
        EditorWindow.GetWindow(typeof(ObjectReplaceEditorWindow));
    }
    public GameObject newPrefab;
    static GameObject tonewPrefab;
    private string replaceName = "";
    private bool isChangeName = false;
    public class ReplaceData
    {
        public GameObject old;
        public GameObject replace;
        public int index = 0;
    }
    void OnGUI()
    {
        EditorGUILayout.LabelField("选择一个新的物体");
        newPrefab = (GameObject) EditorGUILayout.ObjectField(newPrefab, typeof(GameObject),true, GUILayout.MinWidth(100f));
        tonewPrefab = newPrefab;
        //isChangeName = EditorGUILayout.ToggleLeft("不改变场景中物体的名字", isChangeName);
        if (GUILayout.Button("替换选中的物体"))
        {
            ReplaceObjects();
        }
        EditorGUILayout.LabelField("----------------------");
        replaceName = EditorGUILayout.TextField("需要替换的物体名字", replaceName);
        if (GUILayout.Button("替换相同名字的"))
        {
            ReplaceObjectsByName(replaceName, false);
        }
        if (GUILayout.Button("替换包含名字的 慎用"))
        {
            ReplaceObjectsByName(replaceName, true);
        }
        EditorGUILayout.LabelField("----------------------");
        if (GUILayout.Button("保存修改"))
        {
            EditorSceneManager.SaveScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
        }
    }
    void ReplaceObjects()
    {
        if (tonewPrefab == null) return;
        Object[] objects = Selection.objects;
        List<ReplaceData> replaceDatas = new List<ReplaceData>();
        foreach (Object item in objects)
        {
            GameObject temp = (GameObject)item;
            ReplaceData replaceData = new ReplaceData();
            replaceData.old = temp;
            ReplaceOne(replaceData);
            replaceDatas.Add(replaceData);
        }
        HandleReplaceData(replaceDatas);
    }
    void HandleReplaceData(List<ReplaceData> replaceDatas)
    {
        foreach (var replaceData in replaceDatas)
        {
            replaceData.replace.transform.SetSiblingIndex(replaceData.index);
            if(null != replaceData.old && null != replaceData.old.gameObject)
                DestroyImmediate(replaceData.old.gameObject);
        }
    }
    void ReplaceObjectsByName(string name, bool isContain)
    {
        if (string.IsNullOrEmpty(name)) return;
        List<ReplaceData> replaceDatas = new List<ReplaceData>();
        Transform[] all = Object.FindObjectsOfType<Transform>();
        foreach (var item in all)
        {
            //Debug.LogError(item.name);
            ReplaceData replaceData = new ReplaceData();
            replaceData.old = item.gameObject;
            if (!isContain && item.gameObject.name == name)
            {
                ReplaceOne(replaceData);
                replaceDatas.Add(replaceData);
            }
            else if (isContain && item.gameObject.name.Contains(name))
            {
                ReplaceOne(replaceData);
                replaceDatas.Add(replaceData);
            }
        }
        HandleReplaceData(replaceDatas);
    }
 
    public void ReplaceOne(ReplaceData replaceData)
    {
        GameObject replace = (GameObject)PrefabUtility.InstantiatePrefab(tonewPrefab);
        replace.transform.SetParent(replaceData.old.transform.parent);
        replace.transform.localPosition = replaceData.old.transform.localPosition;
        replace.transform.localRotation = replaceData.old.transform.localRotation;
        replace.transform.localScale = replaceData.old.transform.localScale;
        replaceData.replace = replace;
        replaceData.index = replaceData.old.transform.GetSiblingIndex();
    }
}

 

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Unity是一个流行的游戏引擎,它通常用于创建大型游戏。在Unity,获取场景物体是一个重要任务,因为它涉及到游戏许多对象的处理和控制。通过优化这个过程,您可以获得更流畅的游戏性能。 下面我将讲解一些商业实践使用的一些方法: 第一,使用对象池:在游戏经常会创建和销毁大量的物体,在每次创建新的物体时,Unity都会申请内存和销毁旧的物体,这样会导致游戏的性能下降。通过使用对象池,我们可以重复使用旧的物体,而不是每次都创建新的物体。这样可以减少内存的分配和销毁,提高性能和稳定性。 第二,使用缓存:在Unity,每次使用Find获取GameObject引用都会访问场景树结构,这会导致性能下降。通过使用缓存,我们可以通过在场景加载时获取对物体的引用,并将它们存储在全局或静态变量,以便在游戏运行时直接使用,这可以显著提高游戏性能。 第三,使用八叉树:如果您的场景有很多物体,那么查找和获取这些物体的引用会变得很麻烦。一种解决方案是使用八叉树。八叉树是一种用于快速定位物体的数据结构,可以将场景划分为多个较小的区域。这个技术使得查找特定的物体更加高效,并且可以减少游戏的卡顿现象。 第四,使用裁剪技术:在游戏,有些物体可能不需要显示出来。通过使用裁剪技术,我们可以检查每个物体是否在摄像机的视野内。这可以减少需要处理的物体数量,并提高性能。 总之,从各种角度来看,Unity优化场景物体获取是一个非常重要的任务。通过使用适当的技术,我们可以减少CPU时间,提高游戏性能并创造更好的游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漫步云巅Kim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值