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

Unity如何通过协程实现墙体平滑升起并自动闭合

Unity 墙体平滑升起闭合实现方案

前置准备

  • 墙体预制体wallPrefab设置要求:
    • 初始缩放为(1, 1, 1),pivot(轴心点)设置为底部靠左位置(可直接使用你第二版代码里的UPLEFT轴心生成工具处理)
    • 预制体默认朝向为X轴正方向
  • 确保PlaneSpawnObjects脚本挂载到你的平面对象上,原有平面顶点获取逻辑保留即可

完整实现代码

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class PlaneSpawnObjects : MonoBehaviour
{
    [Header("墙体参数")]
    public GameObject wallPrefab;
    [Tooltip("动画速度,值越大动画完成越快")]
    public float raiseSpeed = 1f;
    [Tooltip("墙体最终升起高度")]
    public float targetWallHeight = 3f;
    public int sphereSize = 1;

    private List<Vector3> cornerPosList = new List<Vector3>();
    private List<Color> CornerColors = new List<Color>() { Color.red, Color.blue, Color.yellow, Color.green };
    // 四个角墙体对应旋转角度,保证沿平面边缘延伸不穿模
    private readonly List<Quaternion> wallRotations = new List<Quaternion>()
    {
        Quaternion.Euler(0, 0, 0), // 第一个角:沿X正方向延伸
        Quaternion.Euler(0, 90, 0), // 第二个角:沿Z正方向延伸
        Quaternion.Euler(0, 180, 0), // 第三个角:沿X负方向延伸
        Quaternion.Euler(0, 270, 0) // 第四个角:沿Z负方向延伸
    };

    void Start()
    {
        GetPlaneCornersPositions();
        StartCoroutine(RaiseWalls());
    }

    public IEnumerator RaiseWalls()
    {
        // 第一步:一次性实例化所有墙体,避免逐个生成导致的动画不同步
        List<Transform> wallList = new List<Transform>();
        for (int i = 0; i < cornerPosList.Count; i++)
        {
            GameObject wall = Instantiate(wallPrefab, cornerPosList[i], wallRotations[i], transform);
            // 初始状态缩放为0,完全隐藏
            wall.transform.localScale = Vector3.zero;
            wallList.Add(wall.transform);
        }

        // 自动计算墙体需要延伸的总长度(平面实际边长)
        float wallTargetLength = Vector3.Distance(cornerPosList[0], cornerPosList[1]);
        float progress = 0f;

        // 第二步:同步控制所有墙体的升起和延伸
        while (progress < 1f)
        {
            progress += Time.deltaTime * raiseSpeed;
            progress = Mathf.Clamp01(progress);

            foreach (var wall in wallList)
            {
                // X轴为延伸方向,Y轴为高度方向,Z轴为墙体厚度可自行调整
                wall.localScale = new Vector3(wallTargetLength * progress, targetWallHeight * progress, 1f);
            }

            // 每帧更新一次,实现平滑动画
            yield return null;
        }
    }

    private void GetPlaneCornersPositions()
    {
        List<Vector3> verticeList = gameObject.GetComponent<MeshFilter>().sharedMesh.vertices.ToList();
        // 保留原有获取四个角的逻辑,若拼接顺序不对可自行调整顶点索引
        cornerPosList.Add(transform.TransformPoint(verticeList[0]));
        cornerPosList.Add(transform.TransformPoint(verticeList[10]));
        cornerPosList.Add(transform.TransformPoint(verticeList[110]));
        cornerPosList.Add(transform.TransformPoint(verticeList[120]));
    }

    private void OnDrawGizmos()
    {
        int b = 0;
        if (cornerPosList != null && cornerPosList.Count > 0)
        {
            for (int a = 0; a < cornerPosList.Count; a++)
            {
                Gizmos.color = CornerColors[b++];
                Gizmos.DrawSphere(cornerPosList[a], sphereSize);
            }
        }
    }
}

核心逻辑说明

  • 提前一次性生成四个墙体,初始缩放为0,保证后续动画完全同步
  • 协程内通过Time.deltaTime控制进度,不受帧率影响,动画速度均匀稳定
  • 墙体延伸长度基于平面实际边长自动计算,四面墙刚好在顶点处拼接,不会出现穿模或者缝隙
  • 完全使用协程实现动画控制,不需要在Update里写逻辑,符合需求要求

常见问题调整

  • 如果墙体拼接方向不对,调整wallRotations列表里的四个旋转值即可
  • 如果墙体厚度不符合预期,修改缩放里的Z轴数值即可
  • 如果需要调整动画时长,修改raiseSpeed参数:值越大动画越快,值越小动画越慢

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 21:45:00