changing the material of children.

I’m still a total beginner at this so this might be obvious.
but I’m trying to “highlight” the object I’m looking at from an fps perspective by changing the material.
the object is multiple blocks in an L shape (like the tetris block) all objects are in an empty parent with the rigidbody attached.

so far I managed to change the material of the block that has the same position as the parent.But now I want to have all children to change material aswell. (I want all the blue ones to be yellow if highlighted)6757333--779899--Screenshot 2021-01-23 191845.png
How do I do this? and if possible I would like an explanation to how that solution works so I can understand it.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class Highlights : MonoBehaviour
{
    public LayerMask Mask;
    public Material highlightMaterial;
    Material originalMaterial;
    GameObject lastHighlightedObject;

    void HighlightObject(GameObject gameObject)
    {
        if (lastHighlightedObject != gameObject)
        {
            ClearHighlighted();
            originalMaterial = gameObject.GetComponentInChildren<MeshRenderer>().sharedMaterial;
            gameObject.GetComponentInChildren<MeshRenderer>().sharedMaterial = highlightMaterial;
            lastHighlightedObject = gameObject;
        }

    }

    void ClearHighlighted()
    {
        if (lastHighlightedObject != null)
        {
            lastHighlightedObject.GetComponentInChildren<MeshRenderer>().sharedMaterial = originalMaterial;
            lastHighlightedObject = null;
        }
    }

    void HighlightObjectInCenterOfCam()
    {
        float rayDistance = 1000.0f;
        // Ray from the center of the viewport.
        Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
        RaycastHit rayHit;
        if (Physics.Raycast(ray, out rayHit, rayDistance, Mask))
        {
            GameObject hitObject = rayHit.collider.transform.parent.gameObject;
            HighlightObject(hitObject);
        }
        else
        {
            ClearHighlighted();
        }
    }

    void Update()
    {
        HighlightObjectInCenterOfCam();
    }
}

If you have those four cubes as children of another GameObject, you can always go up one level from what you hit with the raycast (go up one level using transform.parent), then from that point do a GetComponentsInChildren<Renderer>(); and get all renderers below that parental point.

For your above cube object that would work assuming your hierarchy looks like:

TopOfBlockObjectEmptyGameObject
   Cube1
   Cube2
   Cube3
   Cube4

So lets say you hit Cube3, you go up one level with transform.parent and do the get all renderers call above, and then iterate them.

Transform parent = WhatIHitWithTheRaycast.transform.parent;

Renderer[] AllRenderers = parent.GetComponentsInChildren<Renderer>();

// iterate and change
foreach (Renderer r in AllRenderer)
{
  r.sharedMaterial = .... whatever you like
}

That’s a good cheap and cheerful hack.

Alternately you can put a script on the parent gameobject that explicitly lists the renderers in the children you want changed. That way you could only change specific ones, such as if you had some other renderers you did NOT want changed but that were also children.

1 Like

I was amazed I got most of that hahaha, I got it working that all child objects highlighted as desired, but if I move my cursor away the highlightmaterial stays, this was working before that if I didnt look at it, it would revert back to the original material.

Where did I go wrong?
Here is the part that I changed.

    void HighlightObjectInCenterOfCam()
    {
        float rayDistance = 1000.0f;
        // Ray from the center of the viewport.
        Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
        RaycastHit rayHit;
        if (Physics.Raycast(ray, out rayHit, rayDistance, Mask))
        {
            Transform parent = rayHit.collider.transform.parent;
            Renderer[] AllRenderers = parent.GetComponentsInChildren<Renderer>();

            foreach (Renderer r in AllRenderers)
            {
                r.sharedMaterial = highlightMaterial;
            }
        }
        else
        {
            ClearHighlighted();
        }
    }

You were calling ClearHighlighted() before. :slight_smile:

where was he calling clearhighlighted

Please don’t necro-post. If you have a new question, make a new post. It’s FREE!!

If you can’t find text, use the search feature of your browser.

Read lines 18 and 48 in the first code block. There could be more.