Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by jbabineau · Jan 13, 2020 at 04:07 PM · nullreferenceexceptionstartchild objectderived-class

How do I get a function of a derived class of a child game object to activate AFTER the Start method from during the instantiation of its parent gameobject?

I wanted to make a base class component for animating sprites by a selected sequence, followed by a derived class that initializes the sequence data for each game object containing a sprite. I have succeeded in doing so and I wanted to apply this to some animated arrows that are children of a root menu screen. Upon instantiating the root menu screen, however, I have come across a problem with triggering a function that selects a sequence while compiling all the necessary data in the Start method of the root menu script. For some reason, the base component of the sprite animator is activating the assigned outside function BEFORE it runs its Start method. This causes the sequence to read as null and create null reference errors. Is there a specific reason the Start methods of both the base and derived animator classes are not being triggered in time before other functions? Does it have something to do with the derived component being attached to a child object while the root or parent is running first? Here is some example code to clarify what I'm going through:

 //Base class of the sprite animator
 public abstract class AnimateSprite : MonoBehaviour {
 
     [SerializeField] protected bool animateOn = true;
     [SerializeField] public int animState;
     public Dictionary<int, AnimData> animSeq;
     public Dictionary<int, AnimNext> animSkip;
     SpriteRenderer sprend;
     Sprite[] spr;
 
     protected bool loopOn = false;
     protected int loopCount = 0;
 
     int frame = 0;
     int renderFrame = 0;
 
     public class AnimData
     {
         public int[] phase;
         public int[] speed;
         public string spriteName;
     }
     public class AnimNext
     {
         public int nextPhase;
         public bool loopPhase;
         public int loopAmount;
     }
 
     // Use this for initialization
     protected virtual void Start () {
         StartCall();
         sprend = gameObject.GetComponent<SpriteRenderer>();
         spr = Resources.LoadAll<Sprite>(sprend.sprite.name.Substring(0, sprend.sprite.name.Length-2));
         frame = 0;
         renderFrame = 0;
         if (animSeq != null)
         {
             sprend.sprite = spr[animSeq[animState].phase[renderFrame]];
         } else
         {
             sprend.sprite = spr[0];
         }
     }
 
     protected abstract void StartCall();
 
     void FixedUpdate()
     {
         //Animation in progress
     }
 
     public void setAnimation(int nAnimState)
     {
         animState = nAnimState;
         //ERROR STARTS BELOW
         string nSprite = animSeq[nAnimState].spriteName;
         sprend = gameObject.GetComponent<SpriteRenderer>();
         spr = Resources.LoadAll<Sprite>(nSprite);
         sprend.sprite = spr[animSeq[animState].phase[0]];
         loopOn = animSkip[animState].loopPhase;
         loopCount = animSkip[animState].loopAmount;
         frame = 0;
         renderFrame = 0;
     }
 }

 //Derived class of sprite animator
 public class AnimateGlowArrows : AnimateSprite {
 
     // Use this for initialization
     protected override void Start () {
         base.Start();
     }
 
     protected override void StartCall()
     {
         initializeAnimation();
     }
 
     public void initializeAnimation()
     {
         animSeq = new Dictionary<int, AnimData>
         {
             { 0, new AnimData{ phase = new int[1]{ 0 }, speed = new int[1]{ 1 }, spriteName = "MenuScreenArrow1" } },
             { 1, new AnimData{ phase = new int[6]{ 1, 2, 3, 4, 3, 2 }, speed = new int[6]{ 2, 2, 3, 3, 3, 2 }, spriteName = "MenuScreenArrow1" } },
             { 2, new AnimData{ phase = new int[1]{ 5 }, speed = new int[1]{ 1 }, spriteName = "MenuScreenArrow1" } }
         };
         animSkip = new Dictionary<int, AnimNext>
         {
             { 0, new AnimNext{ nextPhase = 0, loopPhase = false, loopAmount = 1 } },
             { 1, new AnimNext{ nextPhase = 1, loopPhase = false, loopAmount = 1 } },
             { 2, new AnimNext{ nextPhase = 2, loopPhase = false, loopAmount = 1 } }
         };
         loopOn = animSkip[animState].loopPhase;
         loopCount = animSkip[animState].loopAmount;
     }
 }

 //Component of root menu screen where animator is being called within
 public class MenuScreenRoot : MonoBehaviour {
 
     //Initializing fields here
 
 
     void Start()
     {
         //After certain code, assign animator HERE
 gameObject.transform.Find("MenuScreenArrows").gameObject.transform.Find("MenuScreenArrowLeft").GetComponent<AnimateGlowArrows>().setAnimation(0);
     StartCoroutine("summonMenu", endMoveY);
     }
 }

For the record, I can bypass this issue if I use a coroutine that waits for the sequence to no longer be null before activating, but I don't want to rely on that as a default, as I believe this would eventually slow down processing time. Could I get a solution regarding the order around functions and Start methods sometime soon?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Kishotta · Jan 13, 2020 at 05:20 PM

A couple of things:

It's generally a bad idea to implement the MonoBehaviour event methods ( Awake, Start, Update, etc) as abstract/virtual or to override them. Unity calls these methods via reflection, so you can just add the vanilla event methods to your AnimateGlowArrows class directly.

As for guaranteeing that the subclass fires it's Start event first, you could do a couple things:

  • Edit the script execution order for your base class and all its inheritors

  • Remove the Start event from the base entirely and move that logic to a protected void Initialize () method to do your initialization, then have the derived classes call that from their Start events.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jbabineau · Jan 13, 2020 at 06:00 PM 0
Share

It would seem the only way to resolve my issue was to edit the script execution order, which I have never been introduced to until now. Thanks to a solution for my question in the forums section in addition to this answer, I have the process running orderly. I do hope this execution order change does not bring any future issues upon new script developments.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

121 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Get gameObjects from a protected GameObject array of base class in derived class 1 Answer

Huge fps drop 1 Answer

Why are my bullets spawning only from the original muzzle transform? 1 Answer

On Trigger Enter with Child colliders (2D) 1 Answer

unity does not start 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges