Let’s Make a 4X Space Game with Unity – Part 4 Seeding the Galaxy
Hey guys and welcome to part 4 of this series. In the last part we started setting things up so when we click on the stars in the galaxy we can see a solar system.
In this part we will continue towards this goal by:
- Adding a Seed Number for our Random Numbers
- Setting up Input Controls so we can Click on the Stars
1. Adding a Seed Number
So far we have used a lot of random numbers in our code. Random numbers in C# are not completely random but based on calculations the computer makes. This means we can predict what numbers will appear if we know where the computer is. Unity has a handy method for setting this start point, Random.InitState().
Open up the Galaxy script and add a new public int called seedNumber. You can set it equal to whatever you like but in this example I have used 100. Making it public will mean it will be easy for us to play around with the number in the inspector.
Now we need to add a Random.InitState to the Start method using seedNumber. Put this after the call to the SanityChecks method.
If we press play in Unity now you should notice the galaxy always looks the same. Not only that but all the planet data appearing in the console will always be the same!
That is until we change the seed number. Try playing around and find a number you like the look of.
2. Setting up Input Controls
Open up the SolarSystem script, its time to add some code to it.
We will be using a Ray and RayCastHit to determine if the mouse is over a star GameObject on every frame of the game. This means we need to declare a Ray and a RaycastHit in the Update method. Call them mouseRay and hit respectively. But how do we know where the mouse is in the game?
Luckily Unity has a handy method we can use to get this without much hassle, Camera.ScreenPointToRay. We pass this the Input.mousePosition method to get our mouseRay. As for hit we simply make it equal to a new RaycastHit.
The solar system should appear when the mouse pointer is above a star AND the left mouse button is pressed down, so add an && between the Raycast and GetMouseButtonDown methods. Pass the Raycast method mouseRay and hit.
Note: hit requires out put before it because reasons.
Finally, pass the GetMouseButtonDown method 0 (zero) as that is the index Unity assigns the left mouse button.
Whats next? Well at the moment we have no way of relating the GameObjects to the Stars they are meant to represent. We will need to add some stuff to our Galaxy script before we continue with this if statement.
To associate the object with the data we will be using a Dictionary. In the Galaxy script below our availablePlanetTypes array declare a Dictionary with Keys Star and Values GameObject. Call this Dictionary starsToObjectMap and make it public with a get and protected set function.
After we have carried out the sanity checks we need to initialise starToObjectMap.
After we create starGO we need to add starData and starGO to starToObjectMap.
This Dictionary now allows us to associate both the Star and the GameObject which is exactly what we want. Now we just need to be able to find the Star data from the GameObject. To do this we require a new method (in the Galaxy script).
Call the new method ReturnStarFromGameObject, make it public and have it return a star. It will also need to be passed a GameObject.
If our Dictionary includes the GameObject passed to the method, it should find its index and return the Star associated with it. Unfortunately Dictionaries don’t use indexes directly so we have to convert the Values part (GameObjects) into a list and find the index from that list. We then need to convert the Keys part (Stars) into a list and find the Star at the same index as the GameObject. To do this we need to add “using System.Linq” to the top of the script.
This sounds very complicated but it isn’t really. Just copy the code in the pictures. If you are having problems understanding what is going on leave me a comment and I will try to help :).
There’s just one more thing we need to do before we can get some feedback from the mouse click. The SolarSystem script needs to be able to get data from the Galaxy script. There are several ways we could do this. We could add a public Galaxy to the SolarSystem script and add it in the inspector. I don’t like this method however because we could easily forget to do this or something else could go wrong. Instead what we will do is in our Galaxy script we will declare a public static Galaxy called GalaxyInstance. Then we use the Unity built in method OnEnable to make GalaxyInstance equal this script.
We can do this because there will always only be one Galaxy script in our game. We can also say the same about the SolarSystem script so we may as well do the same thing with that now.
There are some fail safes we could add to this to make sure we don’t accidentally have two instances but I think for now it will be fine.
We can finally start clicking on stars and getting feedback!
In the Update method in SolarSystem, we need to look up the Star we have clicked on and we can now do that using our GalaxyInstance and ReturnStarFromObject method. Declare a Star called star and make it equal to “Galaxy.GalaxyInstance.ReturnStarFromObject” and pass it “hit.transform.gameObject”.
Add a Debug.Log to show this stars name and the number of planets it has.
Before pressing play go to the Galaxy script and comment out all the other Debug.Logs (using Ctrl/Command F is useful here) and change the camera Y position to about 20 (this makes it easier to click on the stars).
Press play click to your hearts content as the Star name and how many planets it has appear in the console!
And that concludes this part! In the next part we will finish this off so we can finally see some solar systems appear!
scripts_for_part_4 (zip file)