You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity:如何在Editor脚本中调用StartCoroutine执行协程?

解决方案

要实现编辑模式和运行时都能通过按钮启动预制体生成,需要修改两处脚本,解决协程在编辑模式下的执行问题,同时确保地形数据初始化正确。

修改后的Mono脚本

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

public class InstantiateOnTerrain : MonoBehaviour
{
    private float terrainWidth;
    private float terrainLength;

    private float xTerrainPos;
    private float zTerrainPos;

    public Terrain terrain;
    public GameObject prefab;
    public int numberOfObjects;
    public float instantiateTime;
    public float yOffset;


    void Start()
    {
        InitializeTerrainData();
        StartCoroutine(GenerateObjectsOnTerrain());
    }

    /// <summary>
    /// 初始化地形尺寸和位置数据
    /// </summary>
    public void InitializeTerrainData()
    {
        if (terrain == null)
        {
            terrain = Terrain.activeTerrain;
        }
        if (terrain == null) return;

        terrainWidth = terrain.terrainData.size.x;
        terrainLength = terrain.terrainData.size.z;

        xTerrainPos = terrain.transform.position.x;
        zTerrainPos = terrain.transform.position.z;
    }

    /// <summary>
    /// 生成物体的协程方法(改为公开以便编辑器调用)
    /// </summary>
    public IEnumerator GenerateObjectsOnTerrain()
    {
        InitializeTerrainData();

        if (terrain == null || prefab == null)
        {
            Debug.LogError("请指定地形或预制体!");
            yield break;
        }

        for (int i = 0; i < numberOfObjects; i++)
        {
            float objOffsetX = prefab.transform.localScale.x / 2;
            float objOffsetZ = prefab.transform.localScale.z / 2;

            float randX = UnityEngine.Random.Range(xTerrainPos + objOffsetX, xTerrainPos + terrainWidth - objOffsetX);
            float randZ = UnityEngine.Random.Range(zTerrainPos + objOffsetZ, zTerrainPos + terrainLength - objOffsetZ);
            float yVal = terrain.SampleHeight(new Vector3(randX, 0, randZ)) + yOffset;

            GameObject objInstance;
            if (Application.isPlaying)
            {
                objInstance = Instantiate(prefab, new Vector3(randX, yVal, randZ), Quaternion.identity);
            }
            else
            {
                objInstance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                if (objInstance != null)
                {
                    objInstance.transform.SetPositionAndRotation(new Vector3(randX, yVal, randZ), Quaternion.identity);
                    EditorUtility.SetDirty(objInstance);
                }
            }

            if (instantiateTime > 0)
            {
                yield return new WaitForSeconds(instantiateTime);
            }
        }

        if (!Application.isPlaying)
        {
            EditorUtility.SetDirty(terrain.gameObject);
            SceneView.RepaintAll();
        }
    }
}

修改后的Editor脚本

using System.Collections;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(InstantiateOnTerrain))]
public class InstantiateOnTerrainEditor : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        InstantiateOnTerrain onTerrain = (InstantiateOnTerrain)target;

        if (GUILayout.Button("生成物体"))
        {
            if (Application.isPlaying)
            {
                onTerrain.StartCoroutine(onTerrain.GenerateObjectsOnTerrain());
            }
            else
            {
                EditorCoroutine.StartCoroutine(onTerrain.GenerateObjectsOnTerrain(), onTerrain);
            }
        }
    }
}

核心修改点

  1. 地形数据独立初始化:

    • 把原Start方法里的地形数据提取成单独的InitializeTerrainData方法,确保编辑模式下点击按钮时也能正确获取地形参数,不会因为Start没执行导致数据为空。
    • 协程开头也调用这个方法,保证每次生成都用最新的地形状态。
  2. 跨模式协程执行:

    • 把协程改成公开方法,让编辑器脚本能直接调用。
    • 编辑器脚本里判断当前是运行时还是编辑模式:运行时用Mono自带的StartCoroutine,编辑模式用Unity提供的EditorCoroutine来跑协程。
  3. 编辑模式实例化优化:

    • 用PrefabUtility.InstantiatePrefab替代普通Instantiate,这样生成的物体还能和原预制体保持关联。
    • 调用EditorUtility.SetDirty标记修改,确保编辑模式下生成的物体能被保存到场景里。
    • 生成完刷新场景视图,让效果立刻显示出来。
  4. 细节修复:

    • 加了空值检查,避免没指定地形或预制体时崩溃。
    • 修正了原按钮文字的拼写错误。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:25:22