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. Dismiss Notice

Question Change Sprites on prefab objects

Discussion in 'Scripting' started by dreamos1982, Jul 30, 2023.

  1. dreamos1982

    dreamos1982

    Joined:
    Jan 27, 2020
    Posts:
    8
    Hello all,

    so i have my player object that is the composition of several body parts, each with it's own game object.

    Now i want to implement a transformation that will be triggered only on certain occasions. All the body parts have a SpriteRender component attached.

    The hierarchy for the player is:


    The parts i want to change are Basically the Body itself, the head and the arms.

    Now i think that an idea is that i can get reference to those components and change them when i need something like:


    Code (CSharp):
    1. public Sprite arm; //The reference to the sprite (probably passed via inspector)
    2. public Sprites armSprites[2] ;  // Populated with the arms (again via inspector)
    3. //....
    4. arm.sprite = armSprites[selected];
    5. // The same for other body parts
    6.  
    7.  
    8.  
    9.  
    Is there a better way or simpler way?

    Eventually how can i get the references to the body part sprites directly via code (The array) instead of having to pass them via the inspector?

    I was thinking also to create an animation, but it seems to much for this purpose. And in this case i was thinking of adding a sort of slowmotion to the entire scene, while the trasformation is occurring, but in this case how can i stop/slowdown the whole scene?

    Thanks
     
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,593
    Two different ways you can do this is by adding tags and searching by tag, or searching by name.

    If your entire scene is based on time, you can change the timeScale of your game. This would be really easy if your code is physics based, but difficult if you manually move stuff in Update.
     
  3. dreamos1982

    dreamos1982

    Joined:
    Jan 27, 2020
    Posts:
    8

    Aaand of course i'm moving stuffs in Update! :)
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,019
    Find by name (in children) is brittle and inefficient, don‘t do that.
    Find by tag (in children) is okay.
    Find by type (in children) would also work if you have a specific component on body parts like ArmMover.

    Lastly, assigning references in the Inspector makes sense if you want flexibility, for example in case you want to reuse the code on enemies.

    From a workflow perspective this is generally also the simpler „better“ solution over tags because you can drag the children into the inspector field vs having to select each child and assign a corresponding tag and if something fails, you need to check each child again to see if they have the correct tag or not which can be super annoying and hides potential issues. If the objects were assigned in the inspector instead you would instantly see a „None“ for any missing assignment.
     
  5. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I have a similar project, and found it was way easier to find children by code, for complex setups. One older way is:

    Code (CSharp):
    1. trans = transform;
    2. shin = trans.GetChild(0).transform;
    3. foot = shin.GetChild(0).transform;
    4. toe = foot.GetChild(0).transform;
    Getting the children by Index, but I strongly don't recommend this, as the order can change every time you make changes. And it becomes a real pain later in development. A better way I found was:

    Code (CSharp):
    1. body_obj = transform.Find("body").gameObject;
    2.     rig = body_obj.transform.Find("metarig").gameObject;
    3.     root_bone = rig.transform.Find("spine").gameObject;
    4.     spine1 = root_bone.transform.Find("spine.001").gameObject;
    5.     spine2 = spine1.transform.Find("spine.002").gameObject;
    6.     spine3 = spine2.transform.Find("spine.003").gameObject;
    Using the gameObjects transform to find the children by their name. You could also use hierarchy with that:

    Code (CSharp):
    1. spine3 = transform.Find("body/metarig/spine/spine.001/spine.002/spine.003").gameObject;
    But I found that is an awful lot of typing, but would be easier to see where bugs may have came from, later on.

    I would also recommend caching all your components, so you don't need to go out of the way when trying to change variables in something. But if you don't want to cache tons of components within the parent script, then each child would need it's own script, then cache it's components like Renderer, Rigidbody, etc... And then you can cache each script of the children within the parent, so easily call:

    Code (CSharp):
    1. spine1script.DoFunction1();
    2. spine2script.transform.Rotate();
    3. spine3script.cachedRenderer.material = redMaterial01;
    This is what I found works best for me, but I'm sure it can be improved on.
     
  6. dreamos1982

    dreamos1982

    Joined:
    Jan 27, 2020
    Posts:
    8
    Thanks everyone for the replies!
     
  7. dreamos1982

    dreamos1982

    Joined:
    Jan 27, 2020
    Posts:
    8
    Btw how do i base a scene on time? All the tutorials/guide i have found always pointed me to the classic "Update()" way.
     
  8. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    He's referring to if everything moves(physics based, or not) with multiplied by Time.deltaTime, there are Unity functions that can change that time frame, and make things slow-motion. For the life of me, I can't remember what the function, or call, is called, as I have never used it.

    But the reply was in reference to your wanting things to move in slow-motion with animation of said feature.
     
  9. dreamos1982

    dreamos1982

    Joined:
    Jan 27, 2020
    Posts:
    8
    Ah perfect thanks, so yeah i'm using Time,deltaTime.
     
  10. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Found it, was https://docs.unity3d.com/ScriptReference/Time-timeScale.html

    But if you have a set animation from animator, you can just set it's speed, which wouldn't change the time scale globally for all other objects(if that's what you need).
     
    dreamos1982 likes this.