You could use data tables to achieve this. Data Tables will allow you to use a CSV file that can be loaded to memory during game play and iterated. While iterating the data table you can use the “Weight” CSV column to determine the “weight” or likelihood of the current row being selected.
The nice thing about this is being able to separate this type of configuration (which is normally tweaked for game balancing) from your code so in the future you only have to change a CSV file instead of code. This can reduce the amount of regression bugs.
Read more about data tables here Data Driven Gameplay Elements in Unreal Engine | Unreal Engine 5.1 Documentation
Please note, I didn’t actual run this code/blueprints so you may have to iron out kinks. It will get you moving in the right direction.
Step #1 - Create CSV Data Table
Create a CSV file that looks like this (note the header name of the first column should be a blank string, each row thereafter requires a unique value for the first column). UE4 engine uses this column as an “ID” to reference this row.
Also note the BlueprintGeneratedClass’PATH_TO_CLASS’ is critical. When the Data Table is loaded from the CSV into the DataTable object, each DataTable row will be loaded into our Structure we create during the next step. This Structure will contain a “ActorClass” variable that is actually of type “Actor” class so we can use this value for the Spawn Actor From Class node.
Step #2 - Create Data Table and Data Table Row Structure
Create a Structure that represents each row of your data table (CSV column names and Structure variable names must match as well as CSV column value types and Structure variable value types).
Create a new DataTable and select your newly created Structure as the row Structure. Select your CSV file as your Data Table source.
Here’s what your Data Table and Structure would look like.
Step #3 - Load the Data Table
Create a GameState replicated variable of type Array (an array of our Data Table row structure).
Load the Data Table into our new GameState replicated variable. This should be a performance improvement so we don’t have to reload the data table over and over.
NOTE: I cropped out the class name, but this loading is in my GameState::BeginPlay event so it’s only run during GameState’s BeginPlay (hopefully once during map load). You shouldn’t alter this array structure after the data table is loaded.
Step #4 - Provide a Public Method on the GameState to get a random row
This method can either return an instance to a newly spawned Actor, or you can return the SObjectType structure or the Actor class name. You choose.
(Ran out of available photo upload slots so you have to view the last image on Imgur)
Random Probability reference:
https://forums.unrealengine.com/showthread.php?75982-Weighted-random-number&p=329872&viewfull=1#post329872