Athamas Athamas - 3 months ago 20
C# Question

Repeating graphics withing view

In Unity2D, I have made a script to repeat the background sprite just before the camera can see the end.

Here's my code:

using UnityEngine;
using System.Collections;

[RequireComponent (typeof(SpriteRenderer))]

public class Tiling : MonoBehaviour {

public int offsetX = 2; // the offset so that we don't get any weird errors

// these are used for checking if we need to instantiate stuff
public bool hasARightBuddy = false;
public bool hasALeftBuddy = false;

public bool reverseScale = false; // used if the object is not tilable

private float spriteWidth = 0f; // the width of our element
private Camera cam;
private Transform myTransform;
private float localSc;

void Awake () {
cam = Camera.main;
myTransform = transform;
localSc = transform.localScale.x;

// Use this for initialization
void Start () {
SpriteRenderer sRenderer = GetComponent<SpriteRenderer>();
spriteWidth = sRenderer.sprite.bounds.size.x * transform.localScale.x;

// Update is called once per frame
void Update () {
// does it still need buddies? If not do nothing
if (hasALeftBuddy == false || hasARightBuddy == false) {
// calculate the cameras extend (half the width) of what the camera can see in world coordinates
float camHorizontalExtend = cam.orthographicSize * Screen.width/Screen.height;

// calculate the x position where the camera can see the edge of the sprite (element)
float edgeVisiblePositionRight = (myTransform.position.x + spriteWidth/2) - camHorizontalExtend;
float edgeVisiblePositionLeft = (myTransform.position.x - spriteWidth/2) + camHorizontalExtend;

// checking if we can see the edge of the element and then calling MakeNewBuddy if we can
if (cam.transform.position.x >= edgeVisiblePositionRight - offsetX && hasARightBuddy == false)
MakeNewBuddy (1);
hasARightBuddy = true;
else if (cam.transform.position.x <= edgeVisiblePositionLeft + offsetX && hasALeftBuddy == false)
MakeNewBuddy (-1);
hasALeftBuddy = true;

// a function that creates a buddy on the side required
void MakeNewBuddy (int rightOrLeft) {
// calculating the new position for our new buddy
Vector3 newPosition = new Vector3 (myTransform.position.x + spriteWidth * rightOrLeft, myTransform.position.y, myTransform.position.z);
// instantating our new body and storing him in a variable
Transform newBuddy = Instantiate (myTransform, newPosition, myTransform.rotation) as Transform;

newBuddy.parent = myTransform.parent;

// if not tilable let's reverse the x size on our object to get rid of missmatches
if (reverseScale == true) {
newBuddy.localScale = new Vector3 (localSc*-1 , 1, 1);

if (rightOrLeft == 1) { //if this function was called to make a right buddy (1)
newBuddy.GetComponent<Tiling>().hasALeftBuddy = true;
else { //else we just made a left buddy, so it has a right copy
newBuddy.GetComponent<Tiling>().hasARightBuddy = true;

Now, the script is attached to the background sprite and it works fine.
You'll see that there's a
reverseScale to reverse the image.
This is because if the image is not repeatable, (the end and the start to not match on a pixel level) we can mirror it by reverting (* -1) the

The strange thing is, if I launch this with reverseScale disabled, eveything works as I said. If I enable reverseScale, it becomes a mess. Infinite loop of overlapping, badly scaled sprites, crashing the game.

What am I missing? Worst case (but still shouldn't happen), that code snippet should make an image that doesn't match, why is it breaking the program?


I found a solution thanks to Enfyve answer. I was flipping the scale of the whole graphic component instead oa single one for come reason. the flipX field should be used instead. Also, only one every two tiles has to be flipped, to avoid missmatches.


SpriteRenderer already contains a property to draw a sprite flipped, use flipX instead.