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

Unity墙体放置脚本问题:如何循环列表对象计算柱体间距?

解决Unity墙体放置脚本的立柱循环距离计算问题

我来帮你搞定这个立柱之间生成墙体的逻辑问题~先梳理下你当前代码的核心问题:你的AdjustWalls方法里只固定取了列表里的第一个立柱作为previousPost,这显然没法实现和所有已有立柱(或者上一个立柱)的距离判断,下面给你两种符合需求的解决方案,按需选择:

方案1:新立柱与所有已有立柱判断距离(适合任意位置的立柱自动连墙)

这个方案会在每次新增立柱后,遍历所有已经放置的立柱,只要新立柱和某根已有立柱的距离足够近,就自动在两者之间生成墙体:

首先修改你的代码,替换掉原来的AdjustWalls和Distance方法,新增一个专门生成墙体的方法:

[SerializeField] private GameObject wall;
[SerializeField] private GameObject post;
[SerializeField] private float wallPlacementThreshold = 10f; // 可在Inspector调整的距离阈值
private List<GameObject> posts = new List<GameObject>();

private void Update()
{
    GetInput();
    Debug.Log(posts.Count);
}

private void AdjustWalls()
{
    // 取刚添加的新立柱
    GameObject newPost = posts[posts.Count - 1];
    // 遍历所有已有的旧立柱(排除刚添加的这个)
    foreach (GameObject existingPost in posts.Take(posts.Count - 1))
    {
        float distance = Vector3.Distance(newPost.transform.position, existingPost.transform.position);
        // 距离足够近时生成墙体(注意这里是<=阈值,你原来的>是逻辑反了)
        if (distance <= wallPlacementThreshold)
        {
            InstantiateWallBetween(newPost, existingPost);
            Debug.Log("Wall placed between posts");
        }
    }
}

// 专门处理墙体的实例化、位置、旋转和缩放
private void InstantiateWallBetween(GameObject postA, GameObject postB)
{
    // 墙体位置设为两个立柱的中点
    Vector3 wallPos = Vector3.Lerp(postA.transform.position, postB.transform.position, 0.5f);
    // 墙体朝向两个立柱的连线方向
    Vector3 direction = postB.transform.position - postA.transform.position;
    Quaternion wallRot = Quaternion.LookRotation(direction);
    // 如果你墙体模型是横向的,可能需要调整旋转让它竖直(根据你的模型调整)
    wallRot *= Quaternion.Euler(90, 0, 0);
    // 实例化墙体
    GameObject newWall = Instantiate(wall, wallPos, wallRot);
    // 调整墙体长度刚好适配两个立柱的距离
    float wallLength = direction.magnitude;
    newWall.transform.localScale = new Vector3(newWall.transform.localScale.x, newWall.transform.localScale.y, wallLength);
    // 给墙体设置父物体,方便管理
    newWall.transform.parent = transform;
}

private void AddPosts()
{
    GameObject newPost = Instantiate(post, gridSnap(getWorldPoint()), Quaternion.identity);
    posts.Add(newPost);
    newPost.transform.parent = transform;
    AdjustWalls();
}

private void GetInput()
{
    if (Input.GetKeyDown(KeyCode.Q)) // 建议用KeyCode枚举代替字符串,更可靠
    {
        AddPosts();
    }
}

// 你的gridSnap和getWorldPoint方法保持不变
private Vector3 gridSnap(Vector3 point)
{
    // 你的网格对齐逻辑
    return point;
}

private Vector3 getWorldPoint()
{
    // 你的获取世界点逻辑
    return Vector3.zero;
}

方案2:仅与上一个放置的立柱判断距离(适合连续放置的线性墙体)

如果你的需求是只有连续放置的立柱之间才生成墙体(比如画一条连续的墙),那逻辑更简单,只需要和列表里的倒数第二个立柱比较:

private void AdjustWalls()
{
    // 至少有2根立柱才需要判断
    if (posts.Count >= 2)
    {
        GameObject newPost = posts[posts.Count - 1];
        GameObject lastPost = posts[posts.Count - 2];
        float distance = Vector3.Distance(newPost.transform.position, lastPost.transform.position);
        
        if (distance <= wallPlacementThreshold)
        {
            InstantiateWallBetween(newPost, lastPost);
            Debug.Log("Wall placed between last two posts");
        }
    }
}

关键优化点说明

  • 把距离阈值做成了可序列化变量wallPlacementThreshold,不用改代码就能在Unity编辑器里调整;
  • 移除了冗余的currentPost和previousPost变量,直接从列表中取对应的立柱,避免变量混乱;
  • 修复了你原来逻辑中Distance() > 10的错误(需求是距离近才生成墙,应该是<=阈值);
  • 新增的InstantiateWallBetween方法专门处理墙体的位置、旋转和缩放,让墙体刚好贴合两个立柱,避免错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:29:38