Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
avatar image
0
Question by fre_ber · May 25, 2016 at 07:09 PM · starttiming

Is there a way to extend the two-step GameObject init process with Awake() and Start() to three steps?

Hi. I have a problem that, at the surface, seems to require a three-step init process. I know about the two-step process that Unity does provide with Awake() and Start(), but I have come to a point where I would like three steps. The following code is a simplification of the situation:

 public class Manager
 {
     protected Action action;
     public void RegisterAction (Action action)
     {
         this.action += action;
     }
     public void TriggerAction()
     {
         if (action != null)
         {
             action();
         }
     }
 }
 
 public class GameController : MonoBehaviour
 {
     public static GameController instance;
     public Manager manager;
     void Awake()
     {
         instance = this;
         manager = new Manager();
     }
     void Start()
     {
         manager.TriggerEvent();
     }
 }
 
 public class OtherController : MonoBehaviour
 {
     void OnEnable() // I want this to be called before any Start() is
                     // called and after ALL Awake() are called, but it
                     // is called immediately after the Awake() on the
                     // same object. (If the object is enabled, that is)
     {
         GameController.instance.manager.RegisterAction (OnAction);
     }
     protected void OnAction()
     {
         // Do stuff!
     }
 }

So, in words, I have a manager class in the model. This manager triggers actions that can be registered with it. The GameController class is a singleton-ish thing that creates the model in the Awake() method and kicks off the game in Start(), i.e. the triggers can be expected to fire in and after Start(). I have many controller objects in the scene that needs to perform actions on these triggers, they must register with the manager after it has been created but before any Start() method has been called.

Is this something that can be done? Sure, I can make every Start() in the game set a flag in the GameController and move the code in GameController.Start() to GameController.Update() surrounded by a test of that flag. However, this feels wrong.

Is there something wrong with my design pattern? Are there completely different ways of setting something like this up?

Best regards, Fredrik

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

2 Replies

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

Answer by JedBeryll · May 25, 2016 at 07:30 PM

Here's how i do this: my manager does the first things in it's Awake, at the end of that it starts a coroutine that waits for the end of frame. That starts a second method which iterates through some other controller objects and calls their Init method. (all the controllers derive from a BaseController class and the Init is a virtual method which the controllers override). I only need these 2 methods but you can continue this for as long as you like, after you iterate through the objects you can already reference them and do stuff in an order or wait another frame and then do stuff.

Comment
Add comment · 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
0

Answer by fre_ber · May 26, 2016 at 10:08 AM

[Edit: Hmm, did you remove your answer?]

Thanks. I think that your solution would work for me too and it is a bit more generic than what I alluded to in the question. However, both methods feel a bit clumsy. As a temporary fix, I implemented my thing and it turned out similar to this:

 public class Manager
 {
     protected Action action;
     public void RegisterAction (Action action)
     {
         this.action += action;
     }
     public void TriggerAction()
     {
         if (action != null)
         {
             action();
         }
     }
 }
     
 public class GameController : MonoBehaviour
 {
     public static GameController instance;
     // FIXME: This is nasty code to simulate a three-step init:
     public static bool isReadyForInit = true;
     public static List<MonoBehaviour> waitingList = new List<MonoBehaviour>();
     public static void WaitFor(MonoBehaviour b) { waitingList.Add(b); isReadyForInit = false; }
     public static void IsReady(MonoBehaviour b) { waitingList.Remove(b); isReadyForInit = waitingList.Count == 0; }
 
     public Manager manager;
     void Awake()
     {
         instance = this;
         manager = new Manager();
     }
     void Update()
     {
         if (isReadyForInit) // Wait until all relevant objects are ready
         {
             TriggerAction();
             isReadyForInit = false; // We have now initialised, we don't need to init again.
         }
     }
 }
     
 public class OtherController : MonoBehaviour
 {
     void Awake()
     {
         GameController.WaitFor(this);
     }
     void Start()
     {
         GameController.instance.manager.RegisterAction (OnAction);
         GameController.IsReady(this);
     }
     protected void OnAction()
     {
         // Do stuff!
     }
 }

As it is only one object, the GameController, that has to wait, I found this just a little bit simpler than the generic Init() functions called from a co-routine. It is ugly but it works. :-)

/Fredrik

Comment
Add comment · 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

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Initialising List array for use in a custom Editor 1 Answer

Oculus Rift S camera offset at start,Oculus rift s offset camera at start 2 Answers

Proper walk sound / audio play script c# 1 Answer

Timing of WaitForEndOfFrame relative to vertical blank onset? 3 Answers

Random Function Start()? 1 Answer


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