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

Unity对象池复用对象时缩放值异常变更的原因是什么?

问题原因
  • 父对象缩放继承导致的累积变化:当披萨对象被设置为pizzasParent的子对象后,它的localScale会被父对象的缩放影响。你计算位置时用的lossyScale是世界空间下的缩放值,已经包含了父对象的缩放叠加。当对象停用后没有重置状态,下次启用时,之前被父对象修改过的缩放会被再次用于计算位置,导致缩放值不断累积偏差。
  • 对象池状态未重置:回收对象时没有将其从父对象下移除,也没重置自身缩放为初始值,导致每次复用对象时,都会带着上一次被父对象影响后的缩放状态,进而引发后续计算错误。
解决办法
  1. 提前存储初始缩放:在对象池初始化阶段,把每个披萨对象的初始localScale存起来,确保每次复用都能回到原始缩放状态。
  2. 用初始缩放计算位置:放弃使用受父对象影响的lossyScale,改用存储的初始缩放值计算位置,避免父级缩放干扰。
  3. 回收时重置对象状态:对象停用前,脱离父对象并重置缩放,保证下次启用时是干净的初始状态。

修改后的代码示例

首先添加初始化逻辑,存储初始缩放:

// 存储每个披萨的初始缩放值
private Dictionary<Transform, Vector3> _initialPizzaScales = new Dictionary<Transform, Vector3>();

// 在对象池初始化时调用这个方法
private void InitPizzaPool(List<Transform> pizzas)
{
    foreach (var pizza in pizzas)
    {
        _initialPizzaScales[pizza] = pizza.localScale;
        pizza.gameObject.SetActive(false);
        pizza.parent = null; // 初始时让对象脱离父级
    }
}

然后修改创建披萨的方法:

private IEnumerator Create_Green_Pizzas(List<Transform> pizzas)
{
    int pizzaCount = 0;

    while (pizzaCount < pizzas.Count)
    {
        currentColumn++;

        if (currentColumn >= columnCount)
        {
            currentRow++;
            currentColumn = 0;
        }

        if (currentRow >= rowCount)
        {
            pizzaLevel++;
            currentRow = 0;
            currentColumn = 0;
        }

        for (int i = 0; i < pizzas.Count; i++)
        {
            if (!pizzas[i].gameObject.activeInHierarchy)
            {
                // 先重置缩放为初始值
                Vector3 initialScale = _initialPizzaScales[pizzas[i]];
                pizzas[i].localScale = initialScale;
                
                pizzas[i].gameObject.SetActive(true);
                pizzas[i].parent = pizzasParent;
                pizzas[i].rotation = transform.rotation;
                
                // 用初始缩放计算位置,不再依赖受父级影响的lossyScale
                pizzas[i].position = initialSlotPosition + new Vector3(initialScale.x * currentColumn, 
                                                                       pizzaLevel * initialScale.y, 
                                                                      -initialScale.z * currentRow);
                
                pizzas[i].GetComponent<MeshRenderer>().material.color = Color.green;
                _player.collectableGreenPizzas.Add(pizzas[i]);

                pizzaCount++;

                yield return new WaitForSeconds(0.5f);
                break;
            }
        }
    }
}

对象回收时的处理逻辑

当披萨需要回收回对象池时,执行以下操作:

public void RecyclePizza(Transform pizza)
{
    pizza.gameObject.SetActive(false);
    pizza.parent = null; // 脱离父对象,避免父缩放持续影响
    pizza.localScale = _initialPizzaScales[pizza]; // 重置缩放为初始值
    // 可选:把对象移回对象池的固定初始位置
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:33:27