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 /
  • Help Room /
avatar image
0
Question by podian · Nov 04, 2016 at 02:45 PM · arraylistloopefficiency

How to compress iterative code, perhaps using a list and/or loops?

Hi! I looked around and I tried a few of the answers that looked similar (that I could understand!) but alas I was unable to find what I want; my problem is extremely simple and the solution is most likely simple too! But as a newbie to programming and Unity I can't seem to find the most efficient or elegant way to get to it; I have a flat level with five (for now) floor tiles that trigger when a sphere GameObject is placed on them.

 using UnityEngine;
 using System.Collections;

   public class FloorTrigger : MonoBehaviour {
   public bool triggered;    

     void OnTriggerEnter(Collider col)  {
          if (col.tag == "TriggerObj")
              triggered = true;
     }

      void OnTriggerExit(Collider col)  {
         if (col.tag == "TriggerObj")
             triggered = false;
     }
 }

When all floor tiles have spheres on them, the current level ends and the next level is unlocked!

 using UnityEngine;
 using System.Collections;
 
 public class Level02Manager : MonoBehaviour {
   
     FloorTrigger floorTrigger;
     bool trigger1, trigger2, trigger3, trigger4, trigger5;
     public bool nextlevel;
 
  
     void Start ()  {
     floorTrigger1 = GameObject.Find("Trigger1").GetComponent<FloorTrigger>();
     floorTrigger2 = GameObject.Find("Trigger2").GetComponent<FloorTrigger>();
     floorTrigger3 = GameObject.Find("Trigger3").GetComponent<FloorTrigger>();
     floorTrigger4 = GameObject.Find("Trigger4").GetComponent<FloorTrigger>();
     floorTrigger5 = GameObject.Find("Trigger5").GetComponent<FloorTrigger>();
     }
     
     void Update ()  {
     trigger1 = floorTrigger1.triggered;
     trigger2 = floorTrigger2.triggered;
     trigger3 = floorTrigger3.triggered;
     trigger4 = floorTrigger4.triggered;
     trigger5 = floorTrigger5.triggered;
    
     if (trigger1 && trigger2 && trigger3 && trigger4 && trigger 5 && nextlevel == false)  {
         nextlevel = true;
         Debug.Log("Win State");
         }
 
     }
 
 }

As one can see, the iterative list of FloorTrigger's and trigger's can get quite expansive and will bloat rapidly with the complexity or size of the level! Also, the if statement will grow to a silly length as well.

What would be a clean solution to either or both problems, that will ultimately reduce the length of the script?

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 Landern · Nov 04, 2016 at 03:54 PM

Have a single game manager with a List of FloorTrigger type (List).

 using System.Linq;
 using System.Collections.Generic;
 
 // http://wiki.unity3d.com/index.php/Singleton
 public class GameManager : MonoBehavior
 {
   public List< FloorTrigger > CurrentFloorTriggers = new List< FloorTrigger >();
 }

In the Start/Awake function of each component script of type FloorTrigger have it add itself to the List of FloorTriggers that are in play(between levels always Clear() the List.

 void Start()
 {
   GameManager.GetInstance().CurrentFloorTrigger.Add(gameObject.GetComponent<FloorTrigger>());
 }

Use a linq (like the All extension) statement (Your complexity is already O(n) meaning you're going over all the objects of FloorTrigger anyways) and check for the bool property.

 if (GameManager.GetInstance().CurrentFloorTriggers.All(floorTrigger => floorTrigger.triggered == true) && !nextlevel)
 {
   nextlevel = true;
   Debug.Log("Win State");
 }

The cool thing about "registering" the reference to the new FloorTriggers in a GameManager script is you already have the instances and don't have to find the Component on the fly all the time.

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 podian · Nov 05, 2016 at 07:51 AM 0
Share

Well, being "new to program$$anonymous$$g"--these words being frequently lost or unparsable on many such websites-- I didn't understand 90% of your response but I managed to infer enough to ask some CS-savvy friends to explain it to me that, I need to create a list, which I did like you suggested:

 using System.Collections.Generic;
 using UnityEngine;

 public class FT$$anonymous$$anagertest : $$anonymous$$onoBehaviour {

     public static List<FloorTriggertest> CurrentFloorTriggers = new List<FloorTriggertest>();

and then I made sure that my FloorTriggertest scripts all had that line with the "Add" extension (function? method?) that you suggested:

 using UnityEngine;

 public class FloorTriggertest : $$anonymous$$onoBehaviour {

 public bool triggered;

 void Start()  {
     FT$$anonymous$$anagertest.CurrentFloorTriggers.Add(gameObject.GetComponent<FloorTriggertest>());

 void OnTriggerEnter(Collider col)  {
     if (col.tag == "TriggerObj")
         triggered = true;
 }
 void OnTriggerExit(Collider col)  {
     if (col.tag == "TriggerObj")
         triggered = false;
     }
 }

Then finally, in the script that checks the conditions to be met or not:

 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;

 public class Newclasstest : $$anonymous$$onoBehaviour {

 public static bool nextlevel;

 void Update() {
     if (FT$$anonymous$$anagertest.CurrentFloorTriggers.All(FloorTriggertest => FloorTriggertest.triggered) && !nextlevel)  {
     nextlevel = true;
     Debug.Log("Win State");
     }
 }

 }

Thanks.

P.S. Oh yeah, as suggested, either use a Singleton pattern (way beyond my level of understanding at the moment) or just remember to clear the List between levels by placing this somewhere smart:

     FT$$anonymous$$anagertest.CurrentFloorTriggers.Clear();

I'm not very creative so I just put it in the line immediately above

  Scene$$anonymous$$anager.LoadScene(n);

Also, since my requirement is only one-dimensional info (number of switches pressed) and the order or permutation of the switches pressed don't matter in this example, I switched the entire code to simply using a counter:

 public class FT$$anonymous$$anagertest : $$anonymous$$onoBehaviour {
 public static int CurrentFloorTriggers = 0; }

Which is then incremented in each FloorTrigger script ins$$anonymous$$d of setting a boolean:

   void OnTriggerEnter(Collider col) {
     if (col.tag == "TrigSphere")    {
         FT$$anonymous$$anagertest.CurrentFloorTriggers ++;
     }
 }

   void OnTriggerExit(Collider col) {
     if (col.tag == "TrigSphere")    {
         FT$$anonymous$$anagertest.CurrentFloorTriggers --;
     }
 }

And ultimately the checking condition no longer needs to use All to check (O(n)) but simply:

     if (CurrentFloorTriggers == 5 && !nextlevel)

Thanks. Is there a hook I should know about that can let me run code when CurrentFloorTriggers is changed, to run my if statements? That way I won't even have to put it in Update() to cool my CPU even more!

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Which one to use for, while or something else? 1 Answer

How to convert the dynamic list into a array and save it to next scene. 0 Answers

Roughly how much processing power is needed to loop through string-Lists/Arrays when loading/saving stored data? 0 Answers

infinite loop when adding item to list??? 2 Answers

Simple way to access data of different types within a nested array? 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