Search Unity

Access a material on object with more than one material within scene view

Discussion in 'Scripting' started by redmotion_games, Sep 19, 2020.

  1. redmotion_games

    redmotion_games

    Joined:
    May 6, 2013
    Posts:
    84
    I'm trying to create a simple script for applying materials on models in the scene view. If I click on a prefab instance in the scene view I want to override the material with a new material.

    The script below works fine on objects with only one material applied but on objects and prefabs with more than one material it only assigns to the first one.

    How do you obtain the right material?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. public class PaintMaterial : EditorWindow
    7. {
    8.     [SerializeField] private Material material;
    9.     [SerializeField] public bool canPaint = false;
    10.  
    11.     [MenuItem("Tools/Paint Material")]
    12.     static void CreateReplaceWithPrefab()
    13.     {
    14.         EditorWindow.GetWindow<PaintMaterial>();
    15.     }
    16.  
    17.     private void OnEnable()
    18.     {
    19.         if (!Application.isEditor)
    20.         {
    21.             Destroy(this);
    22.         }
    23.         SceneView.onSceneGUIDelegate += OnScene;
    24.     }
    25.  
    26.     void OnScene(SceneView scene)
    27.     {
    28.         Event e = Event.current;
    29.  
    30.         if (e.type == EventType.MouseDown && canPaint )
    31.         {  
    32.             //Debug.Log("Left Mouse was pressed");
    33.             Vector3 mousePos = e.mousePosition;
    34.             float ppp = EditorGUIUtility.pixelsPerPoint;
    35.             mousePos.y = scene.camera.pixelHeight - mousePos.y * ppp;
    36.             mousePos.x *= ppp;
    37.  
    38.             Ray ray = scene.camera.ScreenPointToRay(mousePos);
    39.             RaycastHit hit;
    40.  
    41.             if (Physics.Raycast(ray, out hit))
    42.             {
    43.                 Debug.Log("Clicked point " + hit.point);
    44.                 //Debug.Log("Trianngle " + hit.triangleIndex.ToString());
    45.                 //Debug.Log("gameobject= " + hit.transform.gameObject.name.ToString());
    46.                 //Transform go = hit.collider.transform;
    47.                 //Debug.Log("gameobject="+go.name.ToString());
    48.  
    49.                 Renderer renderer = hit.collider.GetComponent<Renderer>();
    50.                 if ( renderer != null ) {
    51.                     Material mat = renderer.sharedMaterial;
    52.                     Debug.Log ("material = " + mat.name.ToString());
    53.                    
    54.                     //left
    55.                     if ( e.button == 0  ) {
    56.                         if ( material != null ) {
    57.                             renderer.sharedMaterial = material; //this needs to change to locate the right material
    58.                             Repaint(); //refresh UI
    59.                         }
    60.                     }
    61.                     //right
    62.                     if ( e.button == 1 ) {
    63.                         material = renderer.sharedMaterial;
    64.                         Repaint(); //refresh UI
    65.                     }
    66.                 }
    67.             }
    68.         }
    69.     }
    70.  
    71.     private void OnGUI()
    72.     {
    73.         material = (Material)EditorGUILayout.ObjectField("Material", material, typeof(Material), false);
    74.         canPaint = EditorGUILayout.Toggle("Can Paint ", canPaint);
    75.     }
    76. }
     
  2. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    To access multiple,
    Material[] mats = renderer.sharedMaterials;
    , to set the 2nd material of 2,
    renderer.sharedMaterials[1] = material;
     
  3. redmotion_games

    redmotion_games

    Joined:
    May 6, 2013
    Posts:
    84
    Thanks for this, although the main problem I think I'm having is that the hit.collider method isn't always identifying the right material under the mouse click. Sometimes it returns a material that is hidden from view.