If you try creating test scene, with a simple script to change sprite every a period of time.
The sprite doesn't change, but if you try to log the changed sprite name, you'll see it has changed successfully. Which means only the visual is not changing.
Testing on Unity 6000.0.3f1, and on android S24 Ultra
My TestSpriteRendererChange.cs
script
using System.Collections;
using UnityEngine;
public class TestSpriteRendererChange : MonoBehaviour
{
[SerializeField] private SpriteRenderer spriteRenderer;
[SerializeField] private Sprite[] sprites;
private void Start()
{
StartCoroutine(ChangeSprites());
}
private IEnumerator ChangeSprites()
{
var index = 0;
foreach (var sprite in sprites)
{
Debug.Log($"before sprite: {spriteRenderer.sprite.name}");
spriteRenderer.sprite = sprite;
Debug.Log($"after sprite: {spriteRenderer.sprite.name}");
yield return new WaitForSeconds(0.1f);
index++;
}
if (index == sprites.Length)
{
index = 0;
StopCoroutine(nameof(ChangeSprites));
StartCoroutine(nameof(ChangeSprites));
}
}
}
Behaviour in unity editor
Behaviour in android device
This issue is related to URP 2D only, it works just fine in built-in-RP 2D projects.
This was an actual bug in unity 6000.0.3f1, so I did the following
As a workaround for this issue, I've modified my script as follow :-
I changed my TestSpriteRendererChange.cs
to the following :-
using System.Collections;
using UnityEngine;
public class TestSpriteRendererChange : MonoBehaviour
{
[SerializeField] private GameObject spriteGO;
[SerializeField] private Sprite[] sprites;
private void Start()
{
StartCoroutine(ChangeSprites());
}
private IEnumerator ChangeSprites()
{
var index = 0;
foreach (var sprite in sprites)
{
// check if SpriteRenderer exists
var hasComponent = spriteGO.TryGetComponent(out SpriteRenderer sr);
// we could cash reference to sortingLayer and sortingOrder to avoid reset
if (hasComponent)
{
// we remove the component if exists
Destroy(sr);
}
// wait for end of frame to avoid null reference error
yield return new WaitForEndOfFrame();
// we add the SpriteRenderer component again
var spriteRenderer = spriteGO.AddComponent<SpriteRenderer>();
spriteRenderer.sprite = sprite;
Debug.Log($"after sprite: {spriteRenderer.sprite.name}");
yield return new WaitForSeconds(1f);
index++;
}
if (index == sprites.Length)
{
index = 0;
StopCoroutine(nameof(ChangeSprites));
StartCoroutine(nameof(ChangeSprites));
}
}
}
By removing the SpriteRenderer component and adding it again, resolves the issue.
Let me know if there is a better solution.