How to get all the materials assigned to a GameObject in Unity - c#

In Unity, we can get the material that the GameObject has with the following code.
Material myMaterial = GetComponent<Renderer>().material;
But with the above code, we can only get one material per GameObject.
However, in actually, Unity GameObjects can have more than one material.
As shown in the image below
There can be more than one material per GameObject if it is assigned on a face-by-face basis.
I tried to get multiple materials with the code below but it didn't work.
List<Material> myMaterials = GetComponent<Renderer>().material;
Is there a way to get multiple materials assigned to a GameObject?

You can use the Renderer.Materials: https://docs.unity3d.com/ScriptReference/Renderer-materials.html
List<Material> myMaterials = GetComponent<Renderer>().materials.ToList();

Related

Unity C# Adding Material Component to new GameObject

i have a problem about adding Material component to my new GameObject.
Situation: I have a big cube and a bullet. After bullet touches to the big cube. Big cube will be pieced 5x5x5. This is ok. I created small cubes for that. I wanna add to these cubes colors. I know that blabla.AddComponent();
blabla.GetComponent().xxx;
I used this method so as to add Rigidbody, but i couldn't add a Material.
My code:
piece.AddComponent();
piece.GetComponent().color = Color.red;
Can you say how can i add material ?
You can't, because Material is not a Component.
Rather, do the following:
var mr = GetComponent<MeshRenderer>();
mr.material = your material

How to create scriptable object from scene in unity editor

I am currently creating a 2D-game in Unity and facing troubles in level design. I would like to create about 100 levels, each with different prefabs at different positions.
In order to load up the proper levels I have built an architecture with scriptable objects. Tilemaps are being used to represent obstacles. So it is possible to have about 30 different tile-positions for each level. It seems wrong to me to fill in those informations on every scriptable object seperatly.
What I am now looking for is a way to create a level in the editor and save the data directly in a scriptable object. To have a button in editor which says: "Save current scene-layout in e.g. scriptable object level 3". And also being able to load every level to the scene in editor mode.
You create your level in a prefab and reference this prefab into your ScriptableObject.
So your level prefab contains your tilemap and other prefabs.
I would suggest Raphael solutions, but in some cases this can be hard if you are deal with prefabs issues.
Other way to achive this would be create your custom editor to iterate your scene and create this ScriptableObject.
I use this code for something similar
GameObject __PARENT = GameObject.Find("__PARENT");
Vector3 centroid = Vector3.zero;
Transform[] childs = __PARENT.transform.GetComponentsInChildren<Transform>();
foreach (Transform go in childs)
{
Debug.Log(go.name);
centroid += go.position;
}
centroid /= (__PARENT.transform.childCount);
GameObject centerPivotObject = new GameObject();
centerPivotObject.name = "CenterPivotObject";
centerPivotObject.transform.position = centroid;
foreach (Transform go in childs)
{
go.parent = centerPivotObject.transform;
}
In my case I was trying to center pivot in parent object, but you can combine this iterate over your parent game using this and create using this your ScriptableObject
https://wiki.unity3d.com/index.php/CreateScriptableObjectAsset

How to distinguish between different BoxCollider in the inspector Unity

Let's say I have a gameobject "player" with 4 different BoxColliders2D
I have a wall script that's a component of the "wall" gameobject.
The wall script has 4 different public boxcolliders2D variables, but I can't seem to find a way to set each of them to their respective boxcollider2D in the player gameobject, in the inspector.
The wall script has 4 different public boxcolliders2D variables, but I
can't seem to find a way to set each of them to their respective
boxcollider2D in the player gameobject, in the inspector.
You can't do that from the Editor but you should be able to do this via code.
Initialize your 4 variables from code by using the GetComponents function which returns array of components attached to the GameObject. Notice the 's' at the end. That's different from the GetComponent function which returns just one GameObject.
public BoxCollider2D col1;
public BoxCollider2D col2;
public BoxCollider2D col3;
public BoxCollider2D col4;
void Awake()
{
BoxCollider2D[] colliders = GetComponents<BoxCollider2D>();
col1 = colliders[0];
col2 = colliders[1];
col3 = colliders[2];
col4 = colliders[3];
}
While the code version should work, do not attach multiple BoxCollider2D to one GameObject. What to do is create child GameObject for each extra collider you want then attach the BoxCollider2D component to it. This is the recommended way of using multiple colliders on one GameObject and that should solve your problem.
Below is a screenshot of what that should look like:
Now, you can drag each child Collider (BoxCollider2D 1, BoxCollider2D 2, BoxCollider2D 3) to the proper public variable name.

Detecting a single instance of a prefab

I am developing a unity project.In that I have a prefab where there will be multiple instances of that prefab will be generated in the scene.I want to select one instance of that prefab and change the color of that of that prefab.
void Update(){
if (Input.GetMouseButtonDown(1))
{
wallPrehab.renderer.material.color = Color.red;
}
}
but this changes all the instances of the prefab.How can I change it to a single object.
Change the color of the object by locating the instance of the prefab, not the prefab itself. Use a Raycast to locate the gameobject. (Since you are responding to mouse click event i assume that you are selecting the object which you want to change the color)
private RaycastHit hit;
void Update(){
Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hit);
if (Input.GetMouseButtonDown(1) && hit.collider){
hit.collider.gameObject.renderer.material.color = Color.red;
}
}
Dont forgrt to add a Collider to the prefab.
Because all your objects use the same material it won't be possible to change ones color without affecting others , one way is to create a copy of that material and change that ones color , this way they aren't using the same material the only thing that you need to do differrent in your code is to get the reference to the instance not the prefab this way if you change the material at runtime a new material will be created
Gameobject go = Instantiate(myPrefab);
go.renderer.material.color = Color.blue;

Adding a MeshFilter mesh via script?

How do you add a MeshFilter component with a specific mesh, let's say a Capsule mesh (from Unity default library resources), via C#? I'm this far ...
GameObject obj = new GameObject("Player");
MeshFilter meshFilter = obj.AddComponent<MeshFilter>();
meshFilter.mesh =
Capsule and other primitive meshes are in the Unity default resources and I know how to assign it in the editor but how do I obtain one in C#? Obviously instantiaion isn't available since it's a library asset.
UPDATE:
I would have thought that this would work:
meshFilter.mesh = Resources.Load<Mesh>("Capsule");
But the mesh is still null afterwards in the editor component inspector.
I am not aware about a direct way how to would not know a direct way how to do it, but there is the "hacky" way:
MeshFilter meshfilter = gameObject.AddComponent<MeshFilter>();
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Capsule);
meshfilter.mesh = go.GetComponent<MeshFilter>().mesh;
meshfilter.gameObject.AddComponent<MeshRenderer>();
Destroy(go);
Does that help?
GameObject obj=GameObject.CreatePrimitive(PrimitiveType.Capsule);
obj.name="Player";

Categories

Resources