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

Flappy Bird式循环背景重置多次后出现间隙问题技术求助

Fixing Background Object Relocation Gaps in Unity

Hey there, let's break down why those gaps are popping up after a few cycles and how to fix them!

First, let's recap your setup: 6 background objects moving along the Z-axis at -0.1f per frame, and you want to reposition the first one to the end (right after the 6th) when it hits your BackgroundRespawner trigger. Your initial code works at first, but over time, tiny floating-point errors and rigid trigger timing start adding up, creating those annoying gaps.

Why the Gaps Happen

  • Floating-point precision drift: Moving by -0.1f every frame uses a non-incremental float value. Over hundreds of frames, tiny inaccuracies in the object's position start to accumulate. When you calculate the new position using fixed multipliers, these errors get carried over each cycle.
  • Fixed offset calculation: Your current code uses hardcoded multipliers (*5, -4.0f * col.bounds.size.z) instead of basing the new position on the current actual position of the last background object. If any object's position drifts even a little, the fixed offset won't line up perfectly.
  • Trigger timing inconsistencies: Depending on when the collision is detected, the background object might have already moved slightly past the ideal trigger point, making the repositioned offset off by a tiny bit each time.

Solution: Dynamic Positioning Based on the Last Background

Instead of using fixed math, always calculate the new position relative to the current farthest background object. This way, even if there's minor drift, each reposition will snap perfectly to the end of the line.

Here's a revised version of your code with this approach:

Step 1: Cache Background References (for performance)

First, cache all your background objects in a list at startup so you don't have to search for them every time a trigger fires:

using UnityEngine;
using System.Collections.Generic;

public class BackgroundRespawner : MonoBehaviour
{
    private List<Transform> _backgrounds;
    private float _backgroundLength;

    void Start()
    {
        // Get all background objects (assign them a "Background" tag first!)
        GameObject[] bgObjects = GameObject.FindGameObjectsWithTag("Background");
        _backgrounds = new List<Transform>();

        foreach (GameObject bg in bgObjects)
        {
            _backgrounds.Add(bg.transform);
        }

        // Sort backgrounds by their Z position (so we can easily grab the last one)
        _backgrounds.Sort((a, b) => a.position.z.CompareTo(b.position.z));

        // Cache the length of one background (assuming all are identical)
        _backgroundLength = _backgrounds[0].GetComponent<Renderer>().bounds.size.z;
    }

Step 2: Update the Trigger Logic

Now, when the trigger fires, find the current last background, and move the triggered one right after it:

void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.name == "StartCollider")
        {
            Transform bgToMove = col.transform.parent;

            // Get the current farthest background (last in our sorted list)
            Transform lastBg = _backgrounds[_backgrounds.Count - 1];

            // Calculate new position: same X/Y as the moving background, Z = lastBg's Z + background length
            Vector3 newPosition = new Vector3(
                bgToMove.position.x,
                bgToMove.position.y,
                lastBg.position.z + _backgroundLength
            );

            // Optional: Round to eliminate tiny floating-point errors
            newPosition.z = Mathf.Round(newPosition.z / _backgroundLength) * _backgroundLength;

            bgToMove.position = newPosition;

            // Update our sorted list to reflect the new position
            _backgrounds.Remove(bgToMove);
            _backgrounds.Add(bgToMove);
            _backgrounds.Sort((a, b) => a.position.z.CompareTo(b.position.z));
        }
    }
}

Key Improvements

  • Dynamic positioning: Every reposition is based on the actual current position of the last background, so gaps can't accumulate.
  • Cached references: No repeated Find calls, which is better for performance.
  • Error correction: The optional Mathf.Round line ensures the position is always a perfect multiple of the background length, wiping out any tiny floating-point drift.
  • Sorted list: Makes it trivial to grab the farthest background every time.

Quick Setup Tip

Don't forget to assign a Background tag to all your "Korito" objects in the Unity inspector—this is how the code finds them.

This should eliminate those gaps for good, even after dozens of cycles!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:05:02