Ok here it goes.
I have one enemy in the scene. I create through script: 100 prefab instances that are spawned to the scene.
What methods do you all use if you want to change the attributes via script?
I might have like 7 attributes in the inspector and I want each instance to have different “stats” attached to it.
I know I can access the individual game object script component and change that way, but I’m talking about 100 characters. If that is the case then any techniques to be able to at least change the attributes via the inspector without adding the instances to the screen.
By definition a prefab is a single template for an object instance, so there is no way to directly assign different values to future instances of that prefab using the inspector. However, I use a technique which I call a “library” of settings, which are handed off when the prefab instance is created.
The settings are just a serializable class with the various parameters you want to change in the Inspector. This class isn’t “on” any object or prefab, it’s there to be used by other scripts:
[System.Serializable]
public class ShipLibrary : System.Object
{
public enum SHIPTYPE { LIGHTFIGHTER, HEAVYFIGHTER, CAPITAL, CIVILIAN }
public SHIPTYPE type;
public GameObject shipPrefab;
public GameObject explosionPrefab;
public float maxVelocity = 200f;
public float acceleration = 50f;
public float deceleration = 50f;
public int shieldStrength;
public int hullStrength;
}
Now assume each prefab has this ShipAI script attached. (I know in your case you have one prefab, but the principle is the same; my “library” of settings just happens to also include a prefab reference along with the other settings.) So this assigned to the prefab, and this allows the instance to receive the desired “library” settings:
using UnityEngine;
using System.Collections;
public class ShipAI : MonoBehaviour {
[HideInInspector]
public ShipLibrary settings; // this is assigned by Controller after instancing
}
In a script associated with another game object or prefab, I create an array of these settings. In this example the object also creates the new ships. When an instance is created, it is given a reference to its library of settings. Notice that the controller also uses the library of settings before the prefab is even created – you can get more mileage out of this technique than merely creating settings:
using UnityEngine;
using System.Collections;
public class Controller : MonoBehaviour {
public ShipLibrary[] shipLibrary;
public void CreateShip(int LibraryIndex) {
GameObject ship = (GameObject)Instantiate(shipLibrary[LibraryIndex].shipPrefab);
ShipAI ai = ship.transform.GetComponent<ShipAI>();
ai.settings = shipLibrary[LibraryIndex];
}
}
This way you can build a whole array of different settings in the Inspector.
I have read that ScriptableObjects are owned by the scene so they won’t serialize properly into a prefab. Using System.Serializable in a pure C# class means the owner of the library could also be a prefab (and you can still do “library of libraries” with the System.Serializable approach).
By what i understood. You wish for each enemy to have different stats.
Why not compose a script that generates a random number between 0 and 6.
And, according to the number, with logic. Load a set of stats onto the instanced prefab.
So each bunch of them will have different stats from your StatsList.
Also, it will always be randomized
You can then further develop the randomizing function. In order to make sure there’s only “Example again” 10 tanks, 10 archers etc… by using ifs and limits and such
I figured random wouldn’t work since he wrote “change the attributes via the inspector without adding the instances to the screen,” which I interpreted to mean he wants to assign specific values.
MV10 . I will try your method. Sounds good. Thanks everyone. My case is more of an example than an actual although I planned a scenario with randomized attributes as an option.
I tried last night using an empty game object nested with a script with all the attributes for all "100: and then passing them to the prebab when instantiated. It kind of works but not sure if this is any better than just adding all “100” prefabs right to the scene.That’s why the array approach seems ideal.
Thanks again
Where exactly did you read that? ScriptableObjects aren’t owned by any Scene, you shouldn’t even be able to bring them into any scene (I mean the asset itself, components can reference them in). ScriptableObjects are classes of data that exist project-wide, and persist from scene to scene and likewise can also be made into importable assets with some editor scripting.
ScriptableObjects can serialize just fine into prefabs, in fact I have a GameController Prefab that holds a default GameMode if one isn’t specified (GameMode is my custom ScriptableObject Class where each instance defines data such as Difficulty level, game rules per game mode, and game progression like the order levels are played). one of the primary reasons ScriptableObject exist is to (relatively) simplify the support for serialization of Unity’s classes.
When it comes to Serialization, it is reccomended that you keep most of your data stored in a ScriptableObject (at least data that needs to reference other UnityObject classes, or basically any class under the UnityEngine namespace). Doing so avoids broken/detached references when they are deserialized.
As for how to configure 100 instantiated prefabs its best that you set up pre-defined configurations first and then spawn those by choosing which prefab. If its something more minor such as a palette swap and stat change, while something you plan to do for hundreds of different enemies, you can make a base enemy prefab and then use the aformentioned ScriptableObjects to put the final touches in the enemy’s unique configuration.
I don’t have the link so I’m not sure where I read that. I was trying to figure out what the point of a ScriptableObject was and how it differs from straight System.Serialization. I never really did come up with a clear picture and my project was already using System.Serialization so I kind of just moved on and forgot about them until dfsantos mentioned them earlier today.
I think the scenarios in which ScriptableObjects are recommended (such as preservation of references) are more about run-time serialization than design-time, aren’t they? Save-game scenarios and such, was the impression I got…
The big advantage of ScriptableObjects is that they are assets, not classes, so, you can have many instances without the need to attach them to a component. (There exists other vantages, but I am talking specifically about the difference between Serializable classes and ScriptableObjects)