Search code examples
unity-game-enginemeshgameobject

Display 10 separate Meshes one by one with looping behavior to create "Animation" for empty GameObject?


I have 10 meshes that are each basically freeze-"frames" of an animation of a whale swimming.

If I were to loop through displaying these meshes then it would create a pseudo-animation, which is what I want.

How can this be achieved? Currently I have GameObject AnimTest, and I've placed the 10 mesh .obj files as children to it. I've started with this code on a script changeMeshes for the GameObject:

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

public class changeMeshes : MonoBehaviour
{
     //Create array of the meshes
    public float[] currentMesh; 

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < 10; i++)
        {
            currentMesh[i].gameObject.GetComponent<MeshRenderer>().enabled = true;
        }
    }
}

This is obviously very wrong since I'm new and confused, so I'm getting errors with script like float does not contain a definition for gameObject. Can anyone help lead me down the correct path?

Edit: Here's my better try at it.

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

public class changeMeshes : MonoBehaviour

{
    //Create array of the meshes
    public GameObject[] whaleMeshes;

    void FindWhales()
    {    
        whaleMeshes = GameObject.FindGameObjectsWithTag("WhaleMesh");    
        print(whaleMeshes.Length);
    }

    void CycleWhales()
    {
        for (int i = 0; i < whaleMeshes.Length; i++)
        {
            if (i > 0)
            {
                whaleMeshes[i - 1].gameObject.GetComponentInChildren<MeshRenderer>().enabled = false;
            }

            whaleMeshes[i].gameObject.GetComponentInChildren<MeshRenderer>().enabled = true;
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        FindWhales();
    }

    // Update is called once per frame
    void Update()
    {
        CycleWhales();
        
    }
}

The result now is that only the last Mesh is permanently rendered, rather than the script cycling through the meshes on a loop. How do I get the meshes to loop?


Solution

  • Well .. a float has no property .gameObject .. not even Mesh would

    Since you say the objects are children of this component you can simply iterate through them.

    And then I would simply activate and deactivate the entire GameObject.

    Sounds like what you would want to do is something like

    public class changeMeshes : MonoBehaviour
    {
        // How long should one mesh be visible before switching to the next one
        [SerializeField] private float timePerMesh = 0.2f;
    
        public UnityEvent whenDone;
    
        private IEnumerator Start()
        {
            // Get amount of direct children of this object
            var childCount = transform.childCount;
    
            // Get the first child 
            var currentChild = transform.GetChild(0);
    
            // Iterate through all direct children
            foreach(Transform child in transform)
            {
                // Set all objects except the first child to inactive
                child.gameObject.SetActive(child == currentChild);
            }
    
            // Iterate though the rest of direct children
            for(var i = 1; i < childCount; i++)
            {
                // Wait for timePerMesh seconds
                yield return new WaitForSeconds(timePerMesh);
    
                // Set the current child to inactive
                currentChild.gameObject.SetActive(false);
                // Get the next child
                currentChild = transform.GetChild(i);
    
                // Set this one to active  
                currentChild.gameObject.SetActive(true);
            }
    
            // Optionally do something when done like e.g. destroy this GameObject etc
            yield return new WaitForSeconds(timePerMesh);
    
            whenDone.Invoke();
        }
    }