- Home /
Enable/Disable gameobject components with script from text file
Hello!
I want to make a car customization system but I have no idea about how to make it.
The car is spawned from a prefab and for example,it has 3 different spoilers(No spoiler,spoiler,carbon spoiler). When tuning the car,I will enable one of theese with a button and script will create a text file that says that this part is enabled and all the other ones are not. Then I'm loading the other level,and car prefab spawns with the chosen spoiler enabled. I think it works kinda like this ...?
Or maybe I could save a car to a prefab on runtime?(not likely)
Answer by Bunny83 · Dec 11, 2015 at 03:30 PM
First you should create a class that actually handles the different "states" of your customizable things. If you always just replace certain things with others you can use a simple script like this:
public class CustomizablePart : MonoBehaviour
{
[System.Seriaizable]
public class Stage
{
public string name;
public GameObject gameObject;
}
public Stage[] stages;
private int m_CurrentStageIndex = -1;
public int CurrentStageIndex
{
get { return m_CurrentStageIndex; }
set { SetStage(value);}
}
public Stage CurrentStage
{
get {
if (m_CurrentStageIndex >= 0 && m_CurrentStageIndex < stages.Length)
return stages[m_CurrentStageIndex];
return null;
}
}
public void SetStage(int aStage)
{
aStage = Mathf.Clamp(aStage, 0, stages.Length-1);
if (aStage == m_CurrentStageIndex)
return; // no change so just leave
for(int i = 0; i < stages.Length; i++)
{
if(stages[i].gameObject != null)
stages[i].gameObject.SetActive( i == aStage );
}
m_CurrentStageIndex = aStage;
}
public bool Upgrade()
{
if (CurrentStageIndex >= stages.Length-1)
return false;
CurrentStageIndex++;
return true;
}
void Awake()
{
SetState(0);
}
}
If you group your different objects which belong to the same part in an empty gameobject you can attach this script to the empty gameobject. Now you just need to specify the "stages" that this part can have. just adjust the length of the array. In the case of your spoilers just use "3". You can name your stages so it's easier to keep track of them. The first stage shouldn't have any gameobject reference. For the second and third stage you would assign the proper child object to the gameObject variable of the stage.
At startup the script will automatically deactivate all objects and activate stage "0". If you want to upgrade your spoiler you can simply do this from some manager script:
public CustomizablePart spoiler;
spoiler.Upgrade();
The Upgrade method returns true if the upgrade was successful or false if it has already reached the highest stage. It will automatically select the next stage when you "Upgrade".
To save the state of the spoiler you can store the spoiler.CurrentStageIndex
integer value "somewhere". You can also restore it the same way.
How to store those settings is another story on it's own. However with this script you can have as many customizable parts as you like.
In a manager class on your car you can define an array like this:
public CustomizablePart[] parts;
and assign all those empty gameobjects with a CustomizablePart script attached to that array. You might want to rename the empty gameobject according to their role. So in our example you would use the name "spoiler".
With that parts array you could store the current state of each part in playerprefs like this:
// save
foreach(var part in parts)
{
PlayerPrefs.SetInt(part.gameObject.name, part.CurrentStageIndex);
}
// load
foreach(var part in parts)
{
part.CurrentStageIndex = PlayerPrefs.GetInt(part.gameObject.name, part.CurrentStageIndex);
}
This is just a primitive example. If you have multiple cars you need to use some sort of prefix for the playerpref name since if both cars have a "spoiler" you can't distinguish them.
You don't have to use PlayerPrefs. You can of course read from / write to a file, however you have to handle the formatting and parsing yourself. It might be easier to use JSON or XML if you prefer to save to an external file.
Answer by toddisarockstar · Mar 24, 2016 at 05:53 AM
here is just a copy paste of another answer I gave to save and restore positions when the when the game restarts. you could modify it to represent whatever numbers instead of x,y and z. hopefully it helps if you are building for standalone. space bar saves the positions of all your objects that have this attached.
#pragma strict
import System.IO;
import System.Text.RegularExpressions;
import System.Diagnostics;
var saves:String;
var rd:String;
var posarray:String[];
var savefolder:String;
savefolder=Application.dataPath;
saves =savefolder+"/"+gameObject.name+".txt";
print(saves);
if(!System.IO.Directory.Exists(savefolder)){
System.IO.Directory.CreateDirectory(savefolder);}
var readsave :StreamReader = new StreamReader(saves);
var txt:String;
var p:Vector3;
if(File.Exists(saves)){
readsave = new StreamReader(saves);
rd = readsave.ReadToEnd();
readsave.Close();
posarray=rd.Split(","[0]);
float.TryParse(posarray[0],p.x);
float.TryParse(posarray[1],p.y);
float.TryParse(posarray[1],p.z);
transform.position=p;
}
function Update(){
if(Input.GetKeyDown("space")){
if(File.Exists(saves)){File.Delete(saves);}
var swreg2 : StreamWriter = new StreamWriter(saves);
txt=transform.position.x+",";
txt=txt+transform.position.y+",";
txt=txt+transform.position.z;
swreg2.WriteLine(txt);
swreg2.Flush();
swreg2.Close();}
}