• 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 Spokkazoni · May 14 at 10:19 AM · optimizationcomponents

How do I get a component from multiple objects?

Hello friends. I am trying to make an RTS game as my first completed project and I am stuck on something. I have a storage script that accesses all the mines in my game and gets their scripts. I have a general idea on how to do that but my question lies in the fact that I want to do it in the Start() method. If I do it there, when I add another mine, it wont be read, but if I do it in the Update() or the FixedUpdate() method it will be resource heavy? Any ideas?

my code is:

 using UnityEngine;
 public class StorageScript : MonoBehaviour
 {
     GameObject[] mines;
     GameObject[] farms;
     [SerializeField] MineScript ms;
     [SerializeField] FarmScript fs;
     [SerializeField] int storageFood;
     int maxStorageStone = 10000;
     int newStone;
     [SerializeField] int storageStone;
     int maxStorageFood = 10000;
     int newFood;
     void Start()
     {
         mines = GameObject.FindGameObjectsWithTag("Mine"); // me trying to fix what I told you
         farms = GameObject.FindGameObjectsWithTag("Farm");    
     }
     void FixedUpdate()
     {
         // Stone Storage
         newStone = storageStone - maxStorageStone;
         if (storageFood > maxStorageStone)
         {
                 storageStone = maxStorageStone;
                 ms.stone = newStone;
         }
         else if (ms.stone >= 80 && storageStone < maxStorageStone)
         {
             storageStone += ms.stone;
             ms.stone = newFood;
         }
         // Food Storage
         newFood = storageFood - maxStorageFood;
         if (storageFood > maxStorageFood)
         {
                 storageFood = maxStorageFood;
                 fs.food = newFood;
         }
         else if (fs.food >= 80 && storageFood < maxStorageFood)
         {
             storageFood += fs.food;
             fs.food = newFood;
         }
     }
 }


and

 using UnityEngine;
 
 public class MineScript : MonoBehaviour
 {
     public int stone;
     public int maxStone = 500;
     float timeToMine = 1;
 
     void FixedUpdate()
     {
         timeToMine -= Time.fixedDeltaTime;
 
         if (timeToMine <= 0 && stone < maxStone)
         {
             stone ++;
             timeToMine = 1;
         }
         if (stone < 0)
         {
             stone = 0;
         }
     } 
 }

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

3 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by yocat332mlg · May 14 at 11:00 AM

I have one idea. Make a static List that will contain mines, and then you can access it from mines themselves, so it would be something like:

 void -Awake or Start, what you prefer- ()
 {
        MineScript.Mines.Add(this.gameObject); 
        //Add the game object that this script is attached to to the list of mines
 }

However, it will work only if mines list is static! So it is basically the same for all the storages, kind of a part of MineScript class.

So now, when new mine is added, it will add itself to the storage's list of mines.

There are other solutions though, and other ways to do that, ask if you have any questions, I'll try to help!

Comment
Add comment · Show 7 · 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 yocat332mlg · May 14 at 11:07 AM 0
Share

In addition: if you need a list of MineScripts, instead of

 MineScript.Mines.Add(this.gameObject); 

you can

 MineScript.Mines.Add(this); 

so it will add the component itself instead of a GameObject that component is attached to.

avatar image Spokkazoni yocat332mlg · May 14 at 12:37 PM 0
Share

but will adding a new mine update the list or will it still show the starting mines (Awake/Start method). It is a good idea but putting it in Update() or FixedUpdate() will be extremely resource heavy. Tell me if I am wrong tho

avatar image yocat332mlg Spokkazoni · May 14 at 01:05 PM 0
Share

Adding a mine to the list simply adds a mine to the list! I may have misunderstood your comment, but if you'll put that code to the Update(), it will add all the mines to the list with each update over and over again. So you put that in Awake(), each Mine will add itself to the list once. Maybe I haven't explained clearly, that piece of code goes to the MineScript class!

Oh, and there is a mistake in my example - i thought about adding Mines list to the StorageScript class, but in my code it is MineScript.Mines. You could do that too, and it will make sense, but in this case, it absolutely has to be static.

Sorry if my answers are a little confusing, it feels like they may be. English is not my native language and I'm not that good in Unity, but I know the basics!

Show more comments
avatar image
0

Answer by Spokkazoni · May 14 at 01:32 PM

I found a solution myself through another forum. Here is the code I used.

GameObject[] mines; [SerializeField] MineScript ms; void Start() { mines = GameObject.FindGameObjectsWithTag("Mine"); } void Update() { foreach (GameObject mineObject in mines) { ms = mineObject.GetComponent<MineScript>(); } }

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 sharatachary · May 14 at 03:13 PM

Hello @Spokkazoni ,

Yes using fixed or update methods will populate the array every time they execute so please avoid it, will impact the runtime experience with the increase in number of mines.


Now addressing the part where you said how to detect a mine which is created runtime as the start method of StorageScript would have already been fired so will miss this new mine.


The answer to that is using events or Action, which means the mine should notify the StorageScript that I was just created please add me to your mines list. I would replace mines array with mines list as I can add a the newly created mine gameobject to the list.


Following is a sample for MineNotifier class which should be attached immediately to the newly instantiated mine gameobject so that it can raise the event which should be listened by StorageScript.


 /* author   : Sharat Achary
  * date     : 20220514
  */
 
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class MineNotifier : MonoBehaviour
 {
     public static Action<GameObject> OnMineInstantiated;
 
     private void Start()
     {
         OnMineInstantiated?.Invoke(gameObject);
     }
 }

Now a modified StorageScript should implement the methods shown below to listen to event and add the newly created mine gameobject to the mines list.


 /* author   : Sharat Achary
  * date     : 20220514
  */
 
 using System.Collections.Generic;
 using UnityEngine;
 
 public class StorageScript : MonoBehaviour
 {
     // Using list instead of array to add objects during runtime.
     List<GameObject> mines = new List<GameObject>();
 
     // Subscribe to the event.
     private void OnEnable()
     {
         MineNotifier.OnMineInstantiated += OnMineInstantiatedHandler;
     }
 
     // Unsubscribe from the event.
     private void OnDisable()
     {
         MineNotifier.OnMineInstantiated -= OnMineInstantiatedHandler;
     }
 
     // Add the mine gameobject to the list.
     private void OnMineInstantiatedHandler(GameObject newMineGameObject)
     {
         mines.Add(newMineGameObject);
     }
 }


This way there is no need to populate the mines every frame using Update or FixedUpdate methods. Update a mines whenever a new mine is added runtime. And those mines which are already in the scene, you should fetch in the Awake or Start method of the StorageScript.


Hope this helps

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

145 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 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

Flash raw animation data to Unity 0 Answers

Using multithreading to speed up an algorithm that interacts with components 1 Answer

How do I change GUI elements from outside of the OnGUI function? 3 Answers

Can someone explain SendMessage to me? 3 Answers

Any way to speed up WWW requests? 2 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