Search Unity

Question How can i generate prefabs in the world passing the MeshRenderer and MeshFilter to a base prefab?

Discussion in 'Prefabs' started by Daeshimaru, Jun 8, 2021.

  1. Daeshimaru

    Daeshimaru

    Joined:
    May 11, 2021
    Posts:
    2
    Hello, I have a question about a problem that has taken me a disproportionate amount of hours searching for tutorials online, looking in forums and going to the Unity documentation, but I have not been able to solve the question with any of this, so I come to you.

    In the 3D project I have a prefab in the Assets folder called PrefabItemWorld, more specifically the prefab of a sword with the Transform, MeshRenderer, MeshFilter, BoxCollider components and a script called ItemWorld. I also have this prefab as a scene object.

    Here the problem begins. I want this prefab to be able, through the script code, to create objects in the game being able to take the Material (MeshRenderer) and the MeshFilter from other prefabs that I have stored in the SAResources / Meshes folder. That is, it can instantiate the objects that I order from the code on a point on the terrain preprogrammed by me, taking for this the two components that I mentioned above from each prefab that I order.

    So far my code is divided into several scripts. This one that I attach below is called ItemWorld, and it is the script that is linked to the PrefabItemWorld, which is the one that I want to generate the objects that I want:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ItemWorld : MonoBehaviour
    6. {
    7.     public static ItemWorld SpawnItemWorld(Vector3 position, Item item)
    8.     {
    9.         Transform transform = Instantiate(ItemAssets.Instance.PrefabItemWorld, position, ItemAssets.Instance.PrefabItemWorld.transform.rotation );
    10.  
    11.         ItemWorld itemWorld = transform.GetComponent<ItemWorld>();
    12.         itemWorld.SetItem(item);
    13.  
    14.         return itemWorld;
    15.     }
    16.  
    17.     private Item item;
    18.  
    19.     public void SetItem(Item item)
    20.     {
    21.         this.item = item;
    22.     }
    23. }
    In another script called ItemAssets I create a reference for my prefab:

    Code (CSharp):
    1. public Transform PrefabItemWorld;
    And finally I did a test in the Start () function of the main script, ThirdPersonMovement, trying to spawn two different objects (one the same as the one in the prefab and the other not) to check that it worked correctly:

    Code (CSharp):
    1. ItemWorld.SpawnItemWorld(new Vector3(230, 2, 115), new Item { itemType = Item.ItemType.Sword, amount = 1 });
    2.         ItemWorld.SpawnItemWorld(new Vector3(230, 2, 120), new Item { itemType = Item.ItemType.Iron, amount = 1 });
    The result of all this? Since I'm only referencing the PrefabItemWorld in the code, three objects appeared on the Game screen. The PrefabItemWorld, which was already there as a GameObject, and the two clones that I invoked. The first clone is also a sword prefab, so it's obvious that it spawns that; the second clone would have to generate a prefab of an iron ingot, but since the references to the components of each prefab are not programmed to alternate the Material (MeshRenderer) and the MeshFilter, it appears with the wrong texture.

    In short, if someone can provide me a stable code to do this that I have just explained and end my agony, I will make an altar and pray to him every day.

    Greetings and thanks in advance.



    ******************** EDIT [8-6-21 || 16:45] ********************



    Hello again, i've been trying new methods to implement what i want but with no outputs.

    First, and maybe like a noob in programation in Unity and in programation in general, i have added MeshFilter and MeshRenderer types to my ItemAssets script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ItemAssets : MonoBehaviour
    6. {
    7.     public static ItemAssets Instance { get; private set; }
    8.  
    9.     private void Awake()
    10.     {
    11.         Instance = this;
    12.     }
    13.  
    14.     public Transform PrefabItemWorld; //call to the PrefabItemWorld
    15.  
    16.     public Sprite swordSprite; //variables for each prefab sprite
    17.     public Sprite woodSprite;
    18.     public Sprite ironSprite;
    19.  
    20.     public MeshFilter swordMesFilt; //variables for each prefab MeshFilter component
    21.     public MeshFilter woodMesFilt;
    22.     public MeshFilter ironMesFilt;
    23.  
    24.     public MeshRenderer swordMesRend; //variables for each prefab MeshRenderer component
    25.     public MeshRenderer woodMesRend;
    26.     public MeshRenderer ironMesRend;
    27. }
    Then I added in my Item script more switch cases to introduce the correct MeshFilter and MeshRenderer components to each object from the enum itemType:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Item
    6. {
    7.     public enum ItemType //enum with all my prefabs
    8.     {
    9.         Wood,
    10.         Sword,
    11.         Iron,
    12.     }
    13.  
    14.     public ItemType itemType; //variable to store my items, set in the enum ItemType
    15.     public int amount; //variable to set the amount of items i want to instatiate at the same time
    16.  
    17.     public Sprite GetSprite() //function with [I]switch [/I]to add the correct Sprite to each object (I use this one to see the correct objects sprites in my UI inventory)
    18.     {
    19.         switch (itemType)
    20.         {
    21.             default:
    22.             case ItemType.Sword: return ItemAssets.Instance.swordSprite;
    23.             case ItemType.Wood: return ItemAssets.Instance.woodSprite;
    24.             case ItemType.Iron: return ItemAssets.Instance.ironSprite;
    25.         }
    26.     }
    27.  
    28.     public MeshFilter GetMeshFilter() //function with [I]switch [/I]to add the correct MeshFilter to each object
    29.     {
    30.         switch (itemType)
    31.         {
    32.             default:
    33.             case ItemType.Sword: return ItemAssets.Instance.swordMesFilt;
    34.             case ItemType.Wood: return ItemAssets.Instance.woodMesFilt;
    35.             case ItemType.Iron: return ItemAssets.Instance.ironMesFilt;
    36.         }
    37.     }
    38.  
    39.     public MeshRenderer GetMeshRenderer() //function with [I]switch [/I]to add the correct MeshRenderer to each object
    40.     {
    41.         switch (itemType)
    42.         {
    43.             default:
    44.             case ItemType.Sword: return ItemAssets.Instance.swordMesRend;
    45.             case ItemType.Wood: return ItemAssets.Instance.woodMesRend;
    46.             case ItemType.Iron: return ItemAssets.Instance.ironMesRend;
    47.         }
    48.     }
    49. }
    Finally, in the ItemWorld script I try to call (in the wrong way I see) the correct MeshFilter and the correct MeshRenderer for each existent object:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ItemWorld : MonoBehaviour
    6. {
    7.     public static ItemWorld SpawnItemWorld(Vector3 position, Item item) //function to instantiate the PrefabItemWorld data and call the SetItem() function to set the correct objects
    8.     {
    9.         Transform transform = Instantiate(ItemAssets.Instance.PrefabItemWorld, position, ItemAssets.Instance.PrefabItemWorld.transform.rotation );
    10.  
    11.         ItemWorld itemWorld = transform.GetComponent<ItemWorld>();
    12.         itemWorld.SetItem(item);
    13.  
    14.         return itemWorld;
    15.     }
    16.  
    17.     private Item item; //variable called item from the class Item
    18.     private MeshRenderer meshRenderer; //variable called meshRenderer from the type MeshRenderer
    19.     private MeshFilter meshFilter; //variable called meshFilter from the type MeshFilter
    20.  
    21.     private void Awake() //In the Awake() function I call MeshFilter and MeshRenderer components of the object
    22.     {
    23.         meshFilter = GetComponent<MeshFilter>();
    24.         meshRenderer = GetComponent<MeshRenderer>();
    25.     }
    26.  
    27.     public void SetItem(Item item) //here I create a function to get the correct item that I want to spawn in the world
    28.     {
    29.         this.item = item;
    30.         meshFilter.mesh = item.GetMeshFilter(); //Here is the problem. I misunderstood how the call to MeshFilter and MeshRenderer works and I get an error instead: "The type 'UnityEngine.MeshFilter' can't be converted implicity in 'UnityEngine.Mesh'"
    31.     }
    32. }
     
    Last edited: Jun 8, 2021