Change Material in MeshRenderer - unity3d

I have a number of materials in my project and there paths are listed as followed:
Assets/3DModels/Materials/01 - white.mat
Assets/3DModels/Materials/02 - black.mat
Assets/3DModels/Materials/03 - red.mat
Assets/3DModels/Materials/04 - green.mat
Assets/3DModels/Materials/05 - blue.mat
Assets/3DModels/Materials/06 - purple.mat
I also have some 3D models created using 3ds max and imported into Unity. The models have the component Mesh Renderer, which contains an array called Materials. As set in 3ds max, all the models use 01 - white.mat as Element0 in array Materials.
During runtime, I want to change the Element0 of the array Materials to 04 - green.mat using C# script. Thus, I have the following code:
public void changeMaterial(){
MeshRenderer mr = this.Transform.GetComponent<MeshRenderer>();
mr.material = Resources.Load("3DModels/Materials/04 - green.mat", typeof(Material)) as Material;
}
When I run it, the Element0 of the object becomes None(Material). I think the there are some mistakes in my code. Please help, many thanks!

First of all, many thanks to Bart.
As Bart mentioned, I put the folder 3DModel under Resources folder. In my program, I changed a little bit, so I have
Resources.Load("3DModels/Materials/04 - green", typeof(Material)) as Material;
There's no need to put Assets/Resources/ at the front as Resources.Load always search assets in this folder. There's also no need to put .mat And now I can change the materials.
Again, many thanks to Bart

If you want assets to be available at run-time and load them via a Resources.Load() call, you'll have to put them in a Resources folder. So put them in something like Assets/Resources/3DModels/Materials
In addition your code has one other little snag. Some of the properties in Unity behave in an unexpected manner. In this case, setting a material won't work. You'll have to create an array of materials (even if it has just one element) and assign it to mr.materials.
I believe that with those corrections it should work.

Related

Unity3D 2018 OnInspectorGUI getAssetPath not working

I've recently upgraded my Unity from 5.6 to Unity2018.4.6f1, In my project I have a script which is called "ConstantCollection", the script has an editor script (ConstantCollectionEditor) which has an OnInspectorGui override of Editor.
The method contains only these 3 lines:
ConstantCollection col = (ConstantCollection)target;
string assetPath = AssetDatabase.GetAssetPath(col).ToLower();
Debug.LogError(assetPath);
Upon creating a prefab, and attaching the ConstantCollection component to it, the code runs and prints out an empty string.
According to documentation, an empty string or null is only returned in case the asset does not exist, but obviously the asset exists.
Furthermore, this code piece was working flawlessly previous to the version update.
Can anyone shed some light on the matter?
I will add that instead of trying to get the asset path this way, I also tried extracting the guid of the object and using the utility to get path from guid, but for some reason the guid returned from the asset is "000000000000000".
After a day of fiddling around with various things I've found the reason of the issue and the solution.
First the reason -
Since I upgraded to Unity2018.4.6f1, the "prefab view" feature is added, it seems (I did not know that) that when opening a prefab with "prefab view" Unity actually creates an Instance of the prefab for the view and does not use the actual prefab, therefor when using the target in OnInspectorGUI method, it actually references an instance of the prefab and not the prefab itself.
Regarding the solution -
After roaming the unity documentation a lot and realizing that Unity refers to the prefab view as its own stage I've managed to solve the issue using the following substitution of an experimental library unity has:
This is the original implementation:
ConstantCollection col = (ConstantCollection)target;
string assetPath = AssetDatabase.GetAssetPath(col).ToLower();
Debug.LogError(assetPath);
This is the new implementation:
ConstantCollection col = (ConstantCollection)target;
string assetPath = (UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(col.gameObject)).prefabAssetPath.ToLower();
Debug.LogError(assetPath);
This change locates the actual prefab from the prefab stage's instance and gets a reference to it and then you can simply fetch the asset path for it.
Hope this saves some time to people in the future.

Selecting object in WorldScaleARexample

I am working on an AR app in Unity and want to display information of an object. To display said information, the user has to be able to click/select that object.
I cannot find the line of code that creates the objects.
I have tried to use a snippet of the ARTabletopKit that handles the user's input to select an object.
If I am correct, the problem is that I cannot use the DebugCanvas-GameObject of the WorldScaleAR example as it does not contain any of the actual game objects.
As far as I can see the objects are created and placed here:
unityTile.Initialize(_map, tileId, _map.WorldRelativeScale, _map.AbsoluteZoom, _map.LoadingTexture);
PlaceTile(tileId, unityTile, _map);
At last I expect the method EventSystem.current.IsPointerOverGameObject() to return true.
Cheers!
You'll need to add a [GameObjectModifier][1] to handle the onClick. You can configure the modifiers to be added at runtime on the game objects in the Map Features area of the AbstractMap.cs script.
I would take a look at how it's implemented on the Data Explorer example.

How do I find more comprehensive Google Documentation for using its APIs

A lot of the times the Google documentation is incomplete and is missing things like libraries required to import. How do I view a more comprehensive example?
Example: https://cloud.google.com/vision/docs/detecting-faces#vision-face-detection-python
def highlight_faces(image, faces, output_filename):
"""Draws a polygon around the faces, then saves to output_filename.
Args:
image: a file containing the image with the faces.
faces: a list of faces found in the file. This should be in the format
returned by the Vision API.
output_filename: the name of the image file to be created, where the
faces have polygons drawn around them.
"""
im = Image.open(image)
draw = ImageDraw.Draw(im)
for face in faces:
box = [(vertex.x, vertex.y)
for vertex in face.bounding_poly.vertices]
draw.line(box + [box[0]], width=5, fill='#00ff00')
im.save(output_filename)
Missing the PIL import
On many of Google's code examples, there will be a VIEW ON GITHUB button that will take you to a complete working example rather than a snippet. Very useful for finding necessary library imports or just going straight to more code.
When that is missing, sometimes there is a link to the file like this firebase example linking to index.js:

Generating MDLMesh with crease support?

I’ve been able to create a MDLMesh and convert to SCNGeometry to render in SceneKit. But I haven’t been able to get crease support in my meshes or geometry.
I just wanted to verify that I’m taking the correct steps to add crease support for my mesh.
Create MDLSubmeshTopology
For the new topology object assign MDLMeshBuffers to edgeCreaseIndices, edgeCreases and Int to edgeCreaseCount properties.
Create MDLSubmesh with topology object.
I’m not looking for specific solutions, just a general idea of how one would go about adding crease support to a mesh. Anyone with experience on this would be great.
SceneKit has edgeCreasesElement and edgeCreasesSource as well as the vertexCrease semantic.
You can take a look at the documentation for SCNGeometry.subdivisionLevel for more information.
The following should work, assuming you've prepared the data as edge pairs of four byte integers, and the crease values as floats.
geometry.edgeCreasesSource = [SCNGeometrySource geometrySourceWithData:ecsData
semantic:SCNGeometrySourceSemanticEdgeCrease
vectorCount:creaseCount
floatComponents:YES
componentsPerVector:1
bytesPerComponent:4
dataOffset:0
dataStride:sizeof(float)];
geometry.edgeCreasesElement = [SCNGeometryElement geometryElementWithData:eceData
primitiveType:SCNGeometryPrimitiveTypeLine
primitiveCount:creaseCount
bytesPerIndex:4];

How to create new demon.model in openGLES?

I want to create a rotating object with 3d effect , I am using the sample project iPhoneGLEssentials provided by developer.apple.com. In the sample project demon.model file is used , I need to create my own .model file. Can any one help me how to create the required .model file?
You can see from the source for that demo that's not a common format. It just has the arrays for positions, normals, texcoords and element indices. You can see how it is read from the .model file in the moduleUtil.h. You can search online for libraries that can load specific formats for models. Engines like irrlicht has support for many formats such as .3ds, and .x. You can start from checking there.