Sorry, I cannot think of a succinct title to this post. I have no idea if this is related to 2D Animation or Prefabs or neither. Maybe I’m doing something wrong.
Here’s what I’m trying to do: I’ve got a 2D animation character with multiple faces. The player takes actions and then I enable/disable certain faces to make the character’s expression change. In my hierarchy you can see the faces here:
I have a scriptable object which has a reference to a prefab of my animation. This prefab has a script with references to the face GameObjects like so:
Notice how the icon of Idle Face is different from the other two? That’s because, after the prefab was instantiated, I manually dragged the face3 from the hierarchy (pictured above) to the script while in play mode. When I did that to with all the faces, it started working as expected, but before I did that, the actions had no effect on the screen.
Here’s how I’m instantiating the prefab:
if (characterData.humanAnimation != null)
{
spriteRenderer.sprite = null;
var animation = Instantiate(characterData.humanAnimation, sprite.transform);
animation.name = "Animation";
var faceReferences = animation.GetComponent<FaceReferences>();
faceReferences.BeIdle();
}
characterData is the scriptable object. humanAnimation is the 2D Animation Package prefab.
Here’s the really weird thing (at least to me): After I stopped the game and started it again, the instantiated Face References script STILL had the right face3 and the wrong face1 and 2, even though I didn’t do anything to save this prefab after I dragged the things over manually. Weirder still, after dragging face 1 and 2 over manually, after I restarted, it looked just like the image above: The instantiated Face References script STILL had the right face3 and the wrong face1 and 2.
Anyway, the workaround I came up with is this, and it seems to fix the issue:
if (characterData.humanAnimation != null)
{
spriteRenderer.sprite = null;
var animation = Instantiate(characterData.humanAnimation, sprite.transform);
animation.name = "Animation";
var faceReferences = animation.GetComponent<FaceReferences>();
faceReferences.idleFace = animation.transform.Find(faceReferences.idleFace.name).gameObject;
faceReferences.happyFace = animation.transform.Find(faceReferences.happyFace.name).gameObject;
faceReferences.upsetFace = animation.transform.Find(faceReferences.upsetFace.name).gameObject;
faceReferences.BeIdle();
}
But, it feels like a bug that I have to do this at all. I would expect this to work with no manual intervention: Shouldn’t the script get references to the instantiated prefab instead of what it’s getting?
Here’s my FaceReferences script if that helps:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FaceReferences : MonoBehaviour
{
public GameObject idleFace;
public GameObject happyFace;
public GameObject upsetFace;
public void BeHappy()
{
idleFace.SetActive(false);
happyFace.SetActive(true);
upsetFace.SetActive(false);
}
public void BeIdle()
{
idleFace.SetActive(true);
happyFace.SetActive(false);
upsetFace.SetActive(false);
}
public void BeUpset()
{
idleFace.SetActive(false);
happyFace.SetActive(false);
upsetFace.SetActive(true);
}
}