Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 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 /
avatar image
0
Question by AlexGLFC · Nov 22, 2021 at 11:16 PM · arrayslists

Access random GameObject from List on another script.

Sadly I've wasted quite a few hours trying to crack this using an Array, but I keep failing.


With an Array I've been able to select a random GameObject and populate an object field using...

 WayPointArray = (GameObject.FindGameObjectsWithTag("WayPoint"));

with

 other.GetComponent<NPC_AI>().WayPoint = NPCWayPoint;

To find a way to get my NPCs to walk to random waypoints.


Naturally rather than having my NPCs active across a large map, I'm trying to keep them local to the player. Having a map of Spawn and WayPoint objects which direct the NPCs where to walk to next within an area.


On 'Start' the WayPoint script finds GameObjects tagged with 'WayPoint', and when it's collider is triggered by an NPC, the script delivers a position for the NPC to go to. ...using the code exampled above.


Only the problem is, my coding isn't great and I can't get the individual Arrays to only find tagged WayPoints within a small distance from each other, building a mesh of points that help the NPCs go A>B rather than A>Z across the map. My limitations in code means each WayPoint finds every WayPoint Tag across the map. Not ideal.


So I've now turned to Lists instead (for the first time), finding that On Start I can now get each WayPoint to find each other within a distance using a collider. (Couldn't with an Array)

 public List<GameObject> WayPoints;
 void OnTriggerStay(Collider other)
 {
     if (other.tag == "WayPoint")
     {
         if (!WayPoints.Contains(other.gameObject))
         {
             WayPoints.Add(other.gameObject);
         }
     }
 }

With that working as hoped, I now have the opposite problem where I can't get my other NPC_AI script to select a random WayPoint GameObject from the above.


Is there anyone that can help? The only way I could easily get my WayPoints to find each other close by, was to switch to lists instead.


As I mentioned, I'm not brilliant at coding generally and have managed with Arrays till now, but Lists so far have been alien to me and not as similar as I was hoping.
Any help I'd be really grateful. Thank you!!

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
1
Best Answer

Answer by Captain_Pineapple · Nov 23, 2021 at 10:29 AM

Hey there,

as this information is only needed to be created once and using colliders is smart but bad on performance let me introduce you to the wonderful world of editor scripts:

 #if UNITY_EDITOR
 using UnityEditor;
 using UnityEngine;
 
 //assuming your waypoint class has these variables:
 public class Waypoint : MonoBehaviour
 {
     public Waypoint[] nextWaypoints;
     // distance value of this specifc waypoint. if distance between 2 points is less then their dist sum you can move between them.
     public float maxWaypointDistance = 100f; // point of this is to give individual waypoints a way to generate a smaller grid..
 }
 
 public class EditorCustomCommands
 {
     [MenuItem("CustomCommand/Initialize Waypoints")]
     public static void initializeWaypoints()
     {
         //find all "waypoints" in the current open scene:
         var allWaypoints = UnityEngine.Object.FindObjectsOfType<Waypoint>();
         //create an array of buffer lists for neighbour waypoints of each waypoint:
         var waypointBuffer = new System.Collections.Generic.List<Waypoint>[allWaypoints.Length];
         for (int i = 0; i < allWaypoints.Length; i++)
         {
             for (int j = 0; j < allWaypoints.Length; j++)
             {
                 //check if the relation between these 2 points has already been discovered:
                 if (waypointBuffer[i].Contains(allWaypoints[j]))
                     continue;
                 //check if the distance between these 2 waypoints is less than their added max waypoint distances:
                 if (allWaypoints[i].maxWaypointDistance + allWaypoints[j].maxWaypointDistance > Vector3.Magnitude(allWaypoints[i].transform.position - allWaypoints[j].transform.position))
                 {
                     //in this case we can move between the 2 waypoints and thus buffer this information:
                     waypointBuffer[i].Add(allWaypoints[j]);
                     waypointBuffer[j].Add(allWaypoints[i]);
                 }
             }
         }
         // now we have processed all waypoints so it is time to save the information on the object:
         for (int i = 0; i < allWaypoints.Length; i++)
         {
             //this is needed to be able to save the changes in the scene later on:
             Undo.RecordObject(allWaypoints[i], "set new next waypoint array");
             allWaypoints[i].nextWaypoints = waypointBuffer[i].ToArray();
             //this is needed to be able to save the changes in the scene later on as well:
             PrefabUtility.RecordPrefabInstancePropertyModifications(allWaypoints[i]);
         }
     }
 }
 #endif

What this does (in theory at least) is create a button in your top menu in the editor which you can click to automatically set all waypoint relations in your current scene. These are then saved in the nextWaypoints array of each waypoint.

Let me know if anything in there is unclear. I hope the comments in the code explain everythin as needed.

Comment
Add comment · Show 10 · 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 AlexGLFC · Nov 23, 2021 at 12:55 PM 0
Share

Wow @Captain_Pineapple thank for such detailed help and effort on my behalf. I never knew something like that was possible. Great that you can get the editor to do the leg work, rather than manually or in game.


However I'm having issues making it work. I've tried changing some of my labelling to accommodate your script, but so far it doesn't seem to be making any changes. It'll tell you what I've got setup...


I have a test scene with a grid of waypoints 10x&y apart. Generally labelled NPC_Destination(XX) and have made sure the tags on these are 'Waypoint' as described in your code, and reinstated the Arrays again with your na$$anonymous$$g convention 'nextWaypoints'.


Hitting 'Initialise Waypoints' does nothing so far. :(


After my first failed attempt, I wasn't sure of FindObjectsOfType<Waypoint> so I tried changing all tags to that and even also the name on some of the waypoints to 'Waypoint', in case. But no joy, and not sure how to get your script to recognise my waypoints, or change my objects to match that label.


How should I be setting up my waypoints?
Thank you so much, this help is incredible and far beyond what I expected.


[Edit] For some reason the Waypoint script didn't show properly in the inspector when attached to an object/waypoint, despite the console being clear. ...went to lunch, came back, suddenly they're now loading properly. FindObjectOfType I'm guessing must relate to the script - find all objects with 'Waypoint' attached.


Now when I hit 'Initialise Waypoints', I get an error ...Object reference not set to instance of an object - line 30 if (waypointBuffer[i].Contains(allWaypoints[j]))


I'm now trying to work that one out. Thanks again!

avatar image Captain_Pineapple AlexGLFC · Nov 23, 2021 at 03:43 PM 0
Share

Hey there,

glad you like the approach.

Just realized that you'll have to initialize all Lists in the buffer array after creating it with this:

    for (int i = 0; i < allWaypoints.Length; i++)
         waypointBuffer[i] = new System.Collections.Generic.List<Waypoint>(); 

Should have been more clear about what FindObjectsOfType does i guess. :)

avatar image AlexGLFC Captain_Pineapple · Nov 23, 2021 at 04:42 PM 0
Share

Thank you, not at all - even though I hadn't come across that command before, I think it was still clear. However the script not loading in the inspector threw me off, until it was suddenly working.


I added the line as suggested, then I got the same error on line 38. So duplicated your line with the J alternative within the next for(int... and now it works!!! Brilliant.


Only... not 100%
I have 8 identical waypoints in close proximity, and they're each only finding one waypoint - the same waypoint. And if I turn that object off, it finds the next one and only that one. I would wonder if there's a limit on how many waypoints each can list, but that one waypoint lists itself - twice!

Sorry to keep asking - this is brilliant, I'm really grateful - I just wish I was at the point where I can interpret C# like Neo see's the Matrix. Thank you!

Show more comments
avatar image
0

Answer by elkawee · Nov 23, 2021 at 09:34 AM

the lazy way to do it would be linq

convert to array and reuse your old code

 using System.Linq;
 
 //  ... 
 WayPoint [] waypointsArray  = WayPoints.ToArray();
 yourOriginalMethodOfRandomSelection ( waypointsArray );
 //  ...
 

or keep the lists and work directly on them

 using System.Linq;
 // .... 
 var R  = new Random();
 var randomWP = WayPoints.Skip(R.Next(WayPoints.Count())).First();

  • both have a performance impact

  • which one is faster depends on how long your list is

( the collider idea is kinda clever :) )

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 AlexGLFC · Nov 23, 2021 at 01:06 PM 0
Share

Thank you so much @elkawee, I did look into Linqs, but they just scrabbled my brain further.


My intention was for each waypoint to have only around 3-6 findable other waypoints on each. Thank you, the intention for the collider was to log other waypoints that are near on Start and then disable the collider after the Array was populated. So hopefully $$anonymous$$imal impact once it's done the job.


If I fail with what the Captain has suggested, using a script in the Editor to do the graft rather than in-game, I'll come back to your post and see if the Linq conversion method works. Again thank you

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

133 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

Related Questions

Copying lists cross-class not working correctly 1 Answer

Custom Inspector: For every new element in one array create a brand new array? 0 Answers

How can you do calculations on two lists? 1 Answer

Creating a list using a list from another script? 1 Answer

Problem with arrays in a list 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