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
相关产品推荐
相关产品推荐

