Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Simple problem, complex description

Discussion in 'Scripting' started by MindGem, Jan 21, 2018.

  1. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    Hi.

    Trying to do something in 2D and I'm stuck.

    I have made letters A and B in Photoshop. It has a fill image and a Outline image.
    I have a button on scene. When I click the button I want to color all letters Fill image with a color.

    So my question is how I can color all letters fill color at once?

    What I don't understand is how I can reference several instantiated prefabs image childs called "Fill"?

    -----------------------
    What I mean, since both letters have the same children. Images called Fill and Outline.
    Can I somehow do
    variable="fill"
    variable.color = code.
    to fill all selected letters fill?

    Because Im stuck at fill.color = code but fill is explicitly assigned in the inspector
    and I need it to be in script instead and I cant figure it out.
     
    Last edited: Jan 21, 2018
  2. morris-

    morris-

    Joined:
    Jan 21, 2018
    Posts:
    12
    Maybe you can find them by tag or type and add them to an array:
    GameObject[] list1 = GameObject.FindGameObjectsWithTag("Fill");
    GameObject[] list2 = GameObject.FindObjectsOfType<String>();

    Then do: foreach(GameObject go in list1) { go.color =...
     
  3. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    When they're instantiated, keep track of them in a list. You can either use the GameObjects or the transforms of these, or if that's a more generalized setup, you could turn it into a prefab and have a component that knows about the prefab's structure and resolves the references. You could then just keep track (or search for) the component types (which abstract everything) and call a function on it. The component would then take care of whatever it was designed to do - it's the implementation detail and the caller (the method that is linked to the onClick of the button) would no longer need to know any details directly.

    Sorry for that very abstract description, but perhaps that's already enough for you to get on the right track.
     
  4. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    Tried something like that but GameObject don't have .color attached. I don't know how to color a GameObject.


    Suddoha.
    Here is what I'm trying to re-create. http://www.graffiticreator.net/htm/creator_kodiak.htm
    So back in 2000 or so I coded that thing in ActionScript. I don't even remember what base language that way, haven't coded since then so now when I pick it up again I'm starting from scratch.

    Anyways, so if I wanted to put colors on all letters elements named "fill"
    Then I could type

    variableName = "fill";
    letter[0][variableName].color = soAndSo...

    As I understand it you can't replace part of a path in the same way in c#.
    So really, I am completely lost on how people usually do this. How would you go about targeting several letters specific image? Or maybe that is the wrong way to start..maybe I shoulnd't put images inside a GameObject, what else?
     
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Oh that example is alot more advanced than I imagined.

    Anyway, it's basically still the same as if you only had 2 parts to fill.

    So, since you're dealing with 2D, you'll have all these SpriteRenderer components attached to your objects. That's the access point you need to get to, as they're responsible for manipulating the appearance of the sprite.

    You can get the renderer component by using GetComponent<Renderer> or more specifically, GetComponent<SpriteRenderer>().
    If you've setup everything to be in a hierarchy, you could just use GetComponentsInChildren<...> (note the 's' for plural). You may then want to sort them depending on their tag, name, any appendix or however you like to ensure you build lists of certain parts (top, bottom...)

    It's worth reading the documentation. Often, you can also guess which properties are available by looking at the inspector of a component. For instance, in order to set the SpriteRenderers color, you can get the component like mentioned above and access the color property (.color).

    The remaining logic is pretty straight forward using solid colors: Get the array or list of renderers you want to apply the color to and use a for (or foreach) loop to iterate that array/list and set the color.

    For some more advanced effects like the gradient and such, it might be better to look into shaders (unless you're satisfied with the not-as-flexible variants using textures).


    Another (perhaps a better?) approach is the one I described above.
    Write a component that resolves all the parts of a letter (i.e. it's renderers) and expose some more decriptive methods.
    The access of the renderers remains the same, it's just structured a little differently.
     
  6. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    Ok thank you very much Suddoha,

    I'll read up on it. thx.
     
  7. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    Quick question.

    I currently have my different elements i.e Fill, Outline, Bubbles and so on each on Images.
    When I have them on Images then Sprite renderer doesn't apply any color because it seems that the component Image/Color will override it.

    Is there a workaround for this or should I instead put my images on Sprites or something else?
     
  8. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    853
    If they are sprites, use GetComponent<SpriteRenderer>().color
    If they are UI images use GetComponent<Image>().color
    You can easily keep the gameobjects in a list when you instantiate them and then set colors
     
    Suddoha likes this.
  9. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    This should actually work. The color adds an overall tint to the sprite. If you use white sprites, they should be colored correctly. You can test this by creating a new sprite and assign one of the default sprites to it, then just change the color in the inspector. It should change the color accordingly.

    *Edit Reading @mahdiii's post, I just realized you might have used UI images. I'd just switch to sprites instead.
     
  10. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    Yea I tested that before, all my elements are solid whites.
    However it doesnt work because in run mode I see that I Do color the Sprite renderer but nothing happens because the other component in Image / color, that one overrides it it seems. I can always remove that component I guess.

    In any event. I wont get nowhere before I figure out how to Reference a specific image inside my GameObejct when I instantiate it :)

    How do I reference my "fill" image located in a GameObject that is my Prefab, which I instantiate?
    I get the reference error, I don't want to explicitly link them in the inspector because I don't know which letters comes out..
    If you understand what I mean.
     
  11. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    I did this guy,

    letter.newLetters[0].GetComponent<Image>().color = new Color32 ((byte)sliderRed.value, (byte)sliderGreen.value, (byte)sliderBlue.value, (byte)sliderAlpha.value);

    letter is the Class where I Instantiate my prefab letters.
    newLetters is the empty list I push in the created letters.

    And this give me a reference error. So I don't know how to get around that.
     
  12. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    We've already told you to use GetComponent call. You need to speak to the renderer, so to say. It's the component responsible to change the sprites appearance.

    *Edit Posted at the same time :p

    First of all, as I mentioned earlier, use sprites instead of images.
    Next, as stated above, you have to tell the renderes to change the color.
     
  13. MindGem

    MindGem

    Joined:
    May 11, 2017
    Posts:
    84
    I know you said it but I've tried using sprites instead of images and for a reason I don't know, they turn invisible.

    I instantiate like this:
    GameObject letterA = Instantiate (letter [0], new Vector2 (0, 0), Quaternion.identity);
    newLetters.Add (letterA);
    newLetters [0].transform.SetParent (GameObject.FindGameObjectWithTag ("canvas").transform, false);

    And I see it pop up inside my canvas but invisible. position is 0,0,0.
    Know why that is?

    And..if I get it visible again the reference is still broken.
    I hit my color button.

    letter.newLetters[0].GetComponent<SpriteRenderer>().color = new Color32 ((byte)sliderRed.value, (byte)sliderGreen.value, (byte)sliderBlue.value, (byte)sliderAlpha.value);

    the error: NullReferenceException: Object reference not set to an instance of an object

    Do I have to explicitly link it in the inspector?
     
  14. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I read most of this thread. I have a question. Say you just put 1 sprite (or image) in the game, and try to change it's color value (even just in Start(), for testing), can you get that done?
    1 problem at a time :)
     
  15. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    1) Sprites don't need to be a child of a canvas. A canvas is the root object for a hierarchy of UI elements. That'd be only necessary if you used UI Images.

    2) It does work without explicit linking.

    3) Post the complete error message and if possible, the complete script as well.