1
\$\begingroup\$

I am a total newby to unity and cannot figure out how to achieve the following:

I want to show a picture composed of different sprites. E.g., a pen with four binary features: the pencolor (black or silver), the penshape (ballpen or normalpen), an ornament (blue or orange), and the tintcolor (blue or black).

My goal:

A function taking a numerical vector as input to specify which of the features/attributes of the pen to show.

  • 0,0,0,0 = a black ballpen with blue ornaments and blue tint.
  • 1,1,1,1 = a a silver normal pen with orange ornaments and black tint.
  • ... and all combinations in between.

One constraint: I need to be able to change how many features there are, and how many values they take.

The sprites are stored in a sprite with mode "multiple" and I use unity to create the layers.

What I did so far:

1) Define an object holding the feature sprites

To enable changing how many features and feature values there are I created a structure. It has flexible length specifying the number of features. Each feature is sprite array specifying the number and source of the featuer values.

// New object class holding all visual feature sprites in hierarchical vectors
[Serializable]
public struct Feature
{
    public string Name;
    public Sprite[] FeatureValues;
}

public Feature[] Features; 

This allows me to specify how many features, how many different sprites per feature, and to drag and drop the respective sprites onto the associated elements of the Features structure.

unity screenshot

2) Defined a Prefab for the Pen

With the help of this post on displaying multiple sprites I created a prefab with as many layers as there are features of the pen

enter image description here

3. And now ... ?

Based on the first comment I created Sprite Renderers for all sub-elements of the Pen object.

The Pen object is a prefab.

Can anyone help me how to change the values of the sprite?

I am trying this: Based on the link mentioned above I create a new class for Pen objects with some sprite renderers

public class Pen : MonoBehaviour {

public SpriteRenderer Tintcolor;
public SpriteRenderer Casecolor;
public SpriteRenderer Ringcolor;
public SpriteRenderer Shape;

public void setTintcolor (Sprite featureImage)
{
    Tintcolor.sprite = featureImage;
}
public void setCasecolor (Sprite featureImage)
{
    Casecolor.sprite = featureImage;
}
public void setRingcolor (Sprite featureImage)
{
    Ringcolor.sprite = featureImage;
}
public void setShape (Sprite featureImage)
{
    Shape.sprite = featureImage;
}

}

Then I write a function to change the value of the sprite renderer.

// featureCombination is the vector holding the feature values to be displayed   
public void ShowFeatureCombination(int[] featureCombination)
{
    Pen newPen = Instantiate(penPrefab) as Pen; // new Pen object

    newPen.setTintcolor(Features[0].FeatureValues[featureCombination[0]]);  
    newPen.setCasecolor(Features[1].FeatureValues[featureCombination[1]]);
    newPen.setRingcolor(Features[2].FeatureValues[featureCombination[2]]);
    newPen.setShape    (Features[3].FeatureValues[featureCombination[3]]);
}

This does not work so far.

And it requires to manually specify the spriteRenderers, which i need to have automatically done based on the number of different features that I enter in the Feature structure.

\$\endgroup\$
  • \$\begingroup\$ each part of the pen which is visible must have a sprite renderer. Just attach it in the editor. What you will need to do is having a script with references of the 4 children and change sprites acording to parameters \$\endgroup\$ – Leggy7 Jul 19 '16 at 11:15
  • \$\begingroup\$ Thank you. I created a sprite renderer, but need help with how to script this (I updated the question). \$\endgroup\$ – JBJ Jul 19 '16 at 13:21
1
\$\begingroup\$

You should have a script attached to your Pen object.

Inside this script you have references (wether public or just visible in editor) where you drag the children via editor.

class YourPenScript {
    public GameObject Tint;
    public GameObject Case;
    public GameObject Ring;
    public GameObject Shape;

    private SpriteRenderer sr_tint;
    private SpriteRenderer sr_case;
    private SpriteRenderer sr_ring;
    private SpriteRenderer sr_shape;

    void Awake(){
        sr_tint = Tint.GetComponent<SpriteRenderer>();
        sr_case = Case.GetComponent<SpriteRenderer>();
        sr_ring = Ring.GetComponent<SpriteRenderer>();
        sr_shape = Shape.GetComponent<SpriteRenderer>();
    }

    public void ShowFeatureCombination(int[] featureCombination){
        /* here you should apply your logic to pick features and apply sprites*/
    }
}

In this way you have a class with references to desired components. Now you can apply your logic to pick sprites from the features.

EDIT:

To fit your needs of dynamic feature number you have to create at runtime al the gameobjects needed by your pen.

consider having an initialization function like

public void Initialize(int[] featureCombination){
    foreach(Transform t in newPen.transform){
        if(t!=newPen.transform) Destroy(t.gameObject);
    }
    ShowFeatureCombination(featureCombination);
}

with consequent change to your function

public void ShowFeatureCombination(int[] featureCombination)
{
    Pen newPen = Instantiate(penPrefab) as Pen; // Move this to awake and make newPen a class variable

    for(var i = 0; i < featureCombination.Length; i++){
        GameObject f = new GameObject();
        f.AddComponent<SpriteRenderer>();
        //insert your logic to apply sprite
        /*maybe f.GetComponent<SpriteRenderer>().sprite = _spriteRenderers[i]; ?*/
        f.transform.parent = newPen.transform;
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks that makes sense!! To make the number of sprite renderers flexible, I ended up getting the sprite renderer component from all children of the pen object by using private SpriteRenderer[] _spriteRenderers; and _spriteRenderers = GetComponentsInChildren<SpriteRenderer>(); \$\endgroup\$ – JBJ Jul 20 '16 at 8:38
  • \$\begingroup\$ doesn't your pen have 4 children? each one can have only 1 spriteRenderer. Tint, Case, Ring, Shape in your case. For what I understood you should have all the sprite renderers and in your logic function apply sprites only where there is a feature. The remaining will have a null sprite. Be sure to set the alpha to 0 where the sprite is null. \$\endgroup\$ – Leggy7 Jul 20 '16 at 8:43
  • \$\begingroup\$ Yes, this pen has 4 children. Remember that in my original question I said I need the number of features (pen children) to be flexible. The object in my next scene may have 3 or 5 children (features); and I want to avoid having to recode that part by hand. \$\endgroup\$ – JBJ Jul 20 '16 at 13:01
  • \$\begingroup\$ So in this way you shouldn't be able to change your feature elements. I edited my answer with the gameobject creation part. Consider that this code is not tested. may contain errors \$\endgroup\$ – Leggy7 Jul 20 '16 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.