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

AR Core+Unity中Runtime地形与Water缩放异常问题求助

Hey there, let's dig into why your Terrain and Unity Water Asset are misbehaving when using Lean Touch scaling in your AR Core project, and walk through practical fixes to get them working right.

Why Terrain & Water Asset Break on Scaling

The core issue is that these aren't standard GameObjects—they have specialized internal logic that clashes with Lean Touch's default scaling behavior:

  • Terrain's unique structure: Unity's Terrain relies on fixed heightmaps, LOD systems, and world-space coordinate calculations. Directly modifying its Transform.scale breaks these internal references, causing the terrain mesh to fail rendering (hence it disappearing). AR Core's spatial anchoring also doesn't play nice with Terrain's non-standard transform setup.
  • Water Asset's rendering dependencies: Official Unity Water (like URP/HDRP Water 2) ties its wave patterns, reflections, and tiling to world-space coordinates and specific component parameters. Scaling the Transform throws these parameters out of sync with the mesh, leading to visual glitches like stretched waves or broken reflections.
  • Lean Touch's default logic: By default, Lean Touch modifies the target's localScale directly—this works for basic meshes, but not for assets with custom rendering or data pipelines like Terrain and Water.
Fixes for Each Asset Type

Fixing Terrain Scaling

Forget scaling the Transform entirely—adjust the Terrain's native size parameters instead:

  • Editor-time adjustment: Select your Terrain, head to the Terrain Settings panel, and tweak Terrain Width, Terrain Length, and Terrain Height to set your desired size.
  • Runtime dynamic scaling: Use code to modify the Terrain's TerrainData.size property, and hook this into Lean Touch's scaling events. Example code:
    using UnityEngine;
    using Lean.Touch;
    
    public class TerrainARScaler : MonoBehaviour
    {
        public Terrain targetTerrain;
        private Vector3 initialTerrainSize;
    
        void Start()
        {
            if (targetTerrain != null)
            {
                initialTerrainSize = targetTerrain.terrainData.size;
            }
            LeanTouch.OnScale += OnTerrainScale;
        }
    
        void OnDisable()
        {
            LeanTouch.OnScale -= OnTerrainScale;
        }
    
        void OnTerrainScale(LeanFinger finger1, LeanFinger finger2)
        {
            if (targetTerrain == null) return;
            
            float scaleDelta = LeanGesture.GetScale(finger1, finger2);
            Vector3 newSize = initialTerrainSize * scaleDelta;
            // Clamp values to prevent extreme sizes that break rendering
            newSize = Vector3.Max(newSize, new Vector3(10, 1, 10));
            
            targetTerrain.terrainData.size = newSize;
            targetTerrain.Flush(); // Force terrain to update visuals
        }
    }
    
  • Anchor setup: Attach your Terrain as a child to an empty GameObject with your AR Core anchor component. This keeps the Terrain anchored to AR space without scaling the anchor itself.

Fixing Water Asset Scaling

Sync scaling with the Water component's specific parameters instead of just the Transform:

  • For URP/HDRP Water 2:
    1. Avoid scaling the Water GameObject directly. Instead, adjust the Wave Scale and Tiling properties in the Water component to match your desired size.
    2. Use code to link Lean Touch's scaling gesture to both the water plane's size and the Water component's parameters:
      using UnityEngine;
      using Lean.Touch;
      using UnityEngine.Rendering.Universal; // For URP Water 2
      
      public class WaterARScaler : MonoBehaviour
      {
          public Water waterComponent;
          private Vector3 initialPlaneScale;
          private float initialWaveScale;
      
          void Start()
          {
              if (waterComponent != null)
              {
                  initialPlaneScale = transform.localScale;
                  initialWaveScale = waterComponent.WaveScale;
              }
              LeanTouch.OnScale += OnWaterScale;
          }
      
          void OnDisable()
          {
              LeanTouch.OnScale -= OnWaterScale;
          }
      
          void OnWaterScale(LeanFinger finger1, LeanFinger finger2)
          {
              if (waterComponent == null) return;
              
              float scaleDelta = LeanGesture.GetScale(finger1, finger2);
              transform.localScale = initialPlaneScale * scaleDelta;
              waterComponent.WaveScale = initialWaveScale * scaleDelta;
              
              // Optional: Update reflection probe position if used
              if (waterComponent.ReflectionProbe != null)
              {
                  waterComponent.ReflectionProbe.transform.position = transform.position;
              }
          }
      }
      
  • Simpler alternative: If the official Water Asset is too finicky, create a basic Plane with a transparent, vertex-animated wave shader. This acts like a standard mesh, so Lean Touch's default scaling will work without glitches.

Universal Lean Touch Setup

Replace Lean Touch's default LeanScale component with a custom script that handles different asset types:

using UnityEngine;
using Lean.Touch;

public class ARMultiScaler : MonoBehaviour
{
    public GameObject targetObject;
    private Terrain targetTerrain;
    private Water targetWater;
    private Vector3 initialObjectScale;
    private Vector3 initialTerrainSize;
    private float initialWaveScale;

    void Start()
    {
        targetTerrain = targetObject.GetComponent<Terrain>();
        targetWater = targetObject.GetComponent<Water>();
        
        if (targetTerrain != null)
        {
            initialTerrainSize = targetTerrain.terrainData.size;
        }
        else if (targetWater != null)
        {
            initialObjectScale = targetObject.transform.localScale;
            initialWaveScale = targetWater.WaveScale;
        }
        else
        {
            initialObjectScale = targetObject.transform.localScale;
        }
        
        LeanTouch.OnScale += OnScale;
    }

    void OnDisable()
    {
        LeanTouch.OnScale -= OnScale;
    }

    void OnScale(LeanFinger finger1, LeanFinger finger2)
    {
        float scaleDelta = LeanGesture.GetScale(finger1, finger2);
        
        if (targetTerrain != null)
        {
            Vector3 newSize = initialTerrainSize * scaleDelta;
            newSize = Vector3.Max(newSize, new Vector3(5, 0.5f, 5));
            targetTerrain.terrainData.size = newSize;
            targetTerrain.Flush();
        }
        else if (targetWater != null)
        {
            targetObject.transform.localScale = initialObjectScale * scaleDelta;
            targetWater.WaveScale = initialWaveScale * scaleDelta;
        }
        else
        {
            targetObject.transform.localScale = initialObjectScale * scaleDelta;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:24:21