-1

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?

Neo
  • 397
  • 1
  • 4
  • 15
  • It is because you are using a float array and call the .gameObject of it which does not exist – Leoverload Dec 17 '20 at 07:50
  • Hi, I went ahead and did a much better try at the code. I edited the post to show this new code. Basically I'm trying to display the meshes, one by one, on a loop. I created the function `CycleLoop` in the hopes that it would cause the meshes to enable the current [i] mesh (and turn off the previously enabled mesh), but the unwanted result is that for some reason when I hit `Play`, only the very last mesh in the array is enabled. There is no looping behavior at all. Any ideas on how to solve this, please? – Neo Dec 17 '20 at 08:21

1 Answers1

1

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();
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • Okay, now that is cool. It works great and a very understandable approach. Thank you for the nice solution on this!! Exciting to see it working. – Neo Dec 17 '20 at 08:27