0
\$\begingroup\$

I am creating a 2D sprite-based game and the tile map contains many animated background tiles (such as water). The map contains many areas that can be transitioned between in a Zelda style (camera scrolls to new area). After scrolling, I set the previous area to inactive. Setting the area to inactive pauses the animations (which is what I want), but when I reenter a previous area the animations start from where they left off. Therefore, any animated tiles adjacent to each other between screens are out of sync and cause an obvious seam. I would like for all the background tile animations to run on the same time value even after they've been paused. The animations use an Animator Controller attached to each animated tile GameObject with an Animation that changes the sprite from an atlas.

Another idea I had would be to have a separate class modify my texture atlas (maybe using setpixel) to update the tiles to their next frame of animation (since I want all tile animations to be in sync and run at the same speed), but I'm not sure how updating the texture will affect performance.

I would like to hear people's ideas for any solutions to this problem.

\$\endgroup\$
1
\$\begingroup\$

I've implemented a solution using my idea of actually modifying the texture that is being used by the tiles. It works perfectly for what I am trying to do, and doesn't affect performance in a meaningful way that I could see with the Profiler/stats.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TextureAnimator : MonoBehaviour {
    // The texture that will be modified.
    // Must have read/write enabled in the texture import settings.
    public Texture2D tilemap;

    // The texture containing each frame of the animated tiles.
    // For my example, each unique tile is laid out vertically,
    // and each frame of the tile is laid out horizontally.
    // Must have read/write enabled in the texture import settings.
    public Texture2D animations;

    // frames per second of the animation
    int samples = 5;
    int lastFrame = -1;
    float time = 0;

    void Update () {
        // the current frame of animation
        int frame = Mathf.FloorToInt (time * samples);

        // make sure we are on a different frame of animation before
        // updating the texture
        if (frame != lastFrame) {
            // first 4 params of SetPixels are the x,y,width,height of the region in the tilemap to change
            // first 4 params of GetPixels are the x,y,width,height of the region in the animations texture to read from
            // this animation has 4 frames, so we do frame%4
            tilemap.SetPixels (1, 1, 16, 16, animations.GetPixels (1+((frame%4)*17), 1, 16, 16));
            // actually applies the SetPixels calls to the texture
            tilemap.Apply ();
            lastFrame = frame;
        }

        time += Time.deltaTime;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.