Search Unity

I Need Help In FindObjectOfType

Discussion in 'Scripting' started by RyanGamingKob, Nov 11, 2019.

  1. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    So I Made A Script
    Code (CSharp):
    1.  public void LoadNextLevelFunction()
    2.     {
    3.         FindObjectOfType<LevelFaderScript>().FadeToLevel(SceneManager.GetActiveScene().buildIndex + 1);
    4.     }
    But InPlayMode, When The LevelFaderScript Get's Created, A Animator Should Be Linked Up
    But It Doesn't And I Cant Manually Link It Up Since The Script Get's Created
    How Can Link up the animator when the script gets added
     
  2. cmyd

    cmyd

    Joined:
    Oct 29, 2017
    Posts:
    92
    What do you mean the animator should be linked up, I don't understand the question.
     
    Dextozz likes this.
  3. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    When

    When The Player Wins The Game, A LevelWon Panel Get Activated And In An Anination Of this panel, An Event Triggers This LoadNextLevelFunction , And Then A LevelFaderScript Component Gets Added To That Panel, But In The Script, There Is A public variable For The "LevelFade" animator. But the LevelWon Panel Already Has An Animator So When The Script Get's Added To The Panel, I Cant Use GetComponent<Animator> since there's already an existing Animator To The LevelWon Panel, And In PlayMode, when the script gets added to the LevelWon Panel At a later point, the variable For the animator has no animator in it( it should have The "LevelFade" Animator in it
    So How Can I Get This "LevelFade" Animator In the LevelWon Panel When The Script Get's Added?
     
  4. cmyd

    cmyd

    Joined:
    Oct 29, 2017
    Posts:
    92
    I still don't understand much but you do know GetComponent<Animator> is used for getting Animator not for adding.
    If there's an animator on the object GetComponent<Animator> will return the animator and if there is not Animator on the object the GetComponent<Animator> will return null
     
  5. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    This What Is Happening with me
    https://drive.google.com/file/d/1UwMPUqDI4Xpsqv_eQFAE5dfPIggf_tgo/view?usp=sharing
    GetComponent<Animator> dont add a component as you said. But as you saw in the pic, the Panel Already Has
    An Animator. I Mean How Can I Add The "LevelFader" Animator Inside the LevelFaderScript Using Scripts.
    Also, Can I Make Transitions Between 2 animators, so when the "LevelCompleted" Animator finishes, the "LevelFader" Will Play? And If I Can, How?
     
  6. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    827
    Please don't capitalize every word of every sentence, it makes it hard to read.

    If you need to load an asset dynamically at runtime, the easiest way is to make use of the Resources API.

    Alternatively, you can pass the reference to the LevelFaderScript from the object that adds the component.
     
  7. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    Sorry fo capitalizing every word, if I don't, it triggers my OCD.
    but I didn't quite understand your point here
     
  8. cmyd

    cmyd

    Joined:
    Oct 29, 2017
    Posts:
    92
    Show me the code LevelFaderScript , I want to see where you're using GetCompnonet<Animator>()
     
  9. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3. public class LevelFaderScript : MonoBehaviour
    4. {
    5.  
    6.     private int levelToLoad;
    7.     public Animator animator;
    8.     public ScenesClass[] scenes;
    9.  
    10.  
    11.     public void FadeToLevel(int levelIndex)
    12.     {
    13.         levelToLoad = levelIndex;
    14.         animator.SetTrigger("FadeOut");
    15.     }
    16.  
    17.     public void LevelFadeOut()
    18.     {
    19.  
    20.         SceneManager.LoadScene(levelToLoad);
    21.         Time.timeScale = 1f;
    22.     }
    23.  
    24.     public void FadeToMainMenu()
    25.     {
    26.         animator.SetTrigger("FadeOutMainMenu");
    27.     }
    28.  
    29.     public void LevelFadeOutToMainMenu()
    30.     {
    31.         SceneManager.LoadScene(0);
    32.     }
    33.  
    34.     public void LevelToAppyFadeIn()
    35.     {
    36.         animator.SetTrigger("FadeIn");
    37.     }
    38.  
    39.     public void LevelToAppyFadeInMainMenu()
    40.     {
    41.         animator.SetTrigger("FadeInMenu");
    42.     }
    43. }
    44.  
     
  10. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    355
    I think I might understand what the problem is.

    You can in fact just use GetComponent<Animator>() to get the Animator component on the GameObject. A GameObject can in fact only contain one Animator component at a time, so there should never be a situation where you need to differentiate between multiple Animator components on the same GameObject.

    However I think that the issue here is that you would like the change the current Animator Controller on the Animator component to a different asset, as visualized in the picture you linked.


    You can change the current Animator Controller using the Animator.runtimeAnimatorController property.

    You also need to get a reference to the "LevelFader" Animator Controller asset somehow, so that you can assign it to the property. You say that LevelFaderScript component is only added to the GameObject at runtime, so you can't add the reference to it using the inspector. Perhaps what you could do is have the GameObject contain another component, which exists on the GameObject the whole time and holds a reference to the asset.

    So you could have a component like this added to the GameObject to hold the reference:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class AnimatorControllerReferences : MonoBehaviour
    4. {
    5.     public RuntimeAnimatorController levelFaderController; // assign using the inspector
    6. }
    Then you could modify the LevelFaderScript to fetch the reference from there and assign it to the Animator.

    Code (CSharp):
    1. using UnityEngine;
    2. public class LevelFaderScript : MonoBehaviour
    3. {
    4.     public Animator animator;
    5.     ...
    6.  
    7.     private void Start()
    8.     {
    9.         animator = GetComponent<Animator>();
    10.         var animatorController = GetComponent<AnimatorControllerReferences>().levelFaderController;
    11.         animator.runtimeAnimatorController = animatorController;
    12.     }
    13.  
    14.     ...
    15. }

    What you are trying to do does seem strange to me, though. Do you really need to reuse the same Animator for handling these different animations? Could you not have two different GameObjects with two different Animators, and have the LevelFaderScript exist in the scene from the start on one of them?
     
  11. cmyd

    cmyd

    Joined:
    Oct 29, 2017
    Posts:
    92
    Mate I don't see you using the GetComponent<Animator>(),
    Code (CSharp):
    1. void Start(){
    2.     animator = GetComponent<Animator>();
    3. }
    Add this to your code then report back.
     
  12. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    I'm still figuring this out but thanks for the help! I didn't know you can change the controller in the runtime.
    Actually there is a LevelFaderScript at the start of a mainMenu that is sitting On a Gameobject with the BlackImage that is animated, and I used Don'tDestroyOnLoad. But when the LevelCompleted Panel animates, an event triggers a LoadNextLevel function. One question bro, Can I reference the LevelFaderScript (that is on dDon'tDestroyOnload) inside the LoadNextLevel function (that is in the LevelCompleted panel in the canvas) instead of having 2 LevelFaderScript Scripts as you said?
     
  13. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    355
    Can't you just use FindObjectOfType<LevelFaderScript>(), like you did in your original post?
     
  14. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    so you mean in the LevelWon Animation, for the event to proceed to the next level, I Change The Animator Controller ( using what you told me) I use FindObjectOfType<LevelFaderScript>(), and in the LevelFaderScript, I Use In The Start Method animator = GetComponent<Animator>() ( after using public Animator animator; ) and I assign the animator variable in the first scene?
     
  15. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    355
    It is difficult for me to tell you the exact sequence of events you should use, because I don't know all the details, like when which components get added to the scene.

    In my code example LevelFaderScript swaps the animator controller the moment that is gets added to a GameObject, since it uses the Start function. You might want to move that to the beginning of the FadeToLevel method, if you only want it to happen when that method is called instead.

    And you can move the AnimatorControllerReferences component to anywhere that it makes the most sense too. Could be either in the same GameObject with LevelFaderScript or in the same GameObject with whatever component contains the LoadNextLevelFunction (of it's a component class). Wherever it is easy to find with something like GetComponent<AnimatorControllerReferences>().

    Maybe something like this would work for you:

    Code (CSharp):
    1. public void LoadNextLevelFunction()
    2. {
    3.     var levelFader = FindObjectOfType<LevelFaderScript>();
    4.     levelFader.FadeToLevel(SceneManager.GetActiveScene().buildIndex + 1);
    5. }
    6.  
    7. [RequireComponent(typeof(Animator)), RequireComponent(typeof(AnimatorControllerReferences))]
    8. public class LevelFaderScript : MonoBehaviour
    9. {
    10.     private int levelToLoad;
    11.     private Animator animator;
    12.     private RuntimeAnimatorController levelFaderController;
    13.    
    14.     private void Start()
    15.     {
    16.         animator = GetComponent<Animator>();  
    17.         levelFaderController = GetComponent<AnimatorControllerReferences>().levelFaderController;
    18.     }
    19.    
    20.     public void FadeToLevel(int levelIndex)
    21.     {
    22.         animator.runtimeAnimatorController = levelFaderController;
    23.         levelToLoad = levelIndex;
    24.         animator.SetTrigger("FadeOut");
    25.     }
    26.    
    27.     ...
    28. }
    Or you could acquire the levelFaderController in the LoadNextLevelFunction, then pass it to LevelFaderScript as a parameter when calling the FadeToLevel method.

    Code (CSharp):
    1.     public void FadeToLevel(int levelIndex, AnimatorControllerReferences levelFaderController)
    2.     {
    3.         animator.runtimeAnimatorController = levelFaderController;
    4.         levelToLoad = levelIndex;
    5.         animator.SetTrigger("FadeOut");
    6.     }
     
  16. RyanGamingKob

    RyanGamingKob

    Joined:
    Oct 27, 2019
    Posts:
    18
    sorry
    sorry for last reply, but i will message you when i fix it, thanks for the support a lot! :D
     
unityunity