So I’m trying to figure this out in unity. I’ve seen it done in production games, but am unfamiliar with how the back end of it is done. Rather then create manually each spawn point for each mob in the editor, as an example you have your world made and there is a large area that pertains to a city.
I’ll use L2 as an example as it’s the easiest to use because it has a setup similar to what I am trying to accomplish.(most people probably know where this is from).
So the npcloc.txt would contain the xyz of each mob, seperated into commented sections. Here is an example
//starter town
npc_begin [Gremlin] pos={-18216;110597;-2500;16384} total=1 respawn=5 mins npc_end
So the question is how to make an npc generator recognize the outside text.
and would this be more efficient then running each spawn through the editor. I guess it’s more of an efficiency type problem.
so beyond having a npc generator and manually doing each spawn point, can this be done?
I was thinking if I create an array of all mobs/npc’s on startup I could then grab the npc from there and instantiate the npc’s vector3 to where I want it.
something like
using UnityEngine;
using System.Collections;
public class NPCPOS : MonoBehaviour {
//find all the gamebojects tagged as npc.
public GameObject NPC;
void NPCPOS() {
NPC = GameObject.Find("NPC");
}
}
// this is how I could do spawn locations
void FixedUpdate()
{
npc = Instantiate(gremlin, new Vector3(40, 2, 0), Quaternion.identity) as GameObject;
}
just trying to think of speed and efficiency. Does this make sense?
I have some example XML code for loading game objects from a text file I can show you tomorrow (after I wake up, as it has a lot of editing that needs to be done to show a snippet). Till then, good night.
Okay, bright and early in the morning. For reading and writing gameobjects to an xml file, this is what I use (well, with loads of stuff cut out to simplify it).
public class FileMonster : MonoBehaviour
{
//Objects we can save or load
public GameObject[] saveLoadables;
private string levelDirectory;
void Start()
{
//Set directory for data files
levelDirectory = Application.persistentDataPath + "/Levels/";
//Check to see if directory exists, and create if not
if(!Directory.Exists(levelDirectory))
Directory.CreateDirectory(levelDirectory);
}
public void SaveLevel(string levelName)
{
using(XmlTextWriter xml = new XmlTextWriter(levelDirectory + levelName + ".lvl", Encoding.ASCII))
{
//Start her up
xml.WriteStartDocument();
xml.WriteWhitespace("\n");
xml.WriteStartElement("Level");
xml.WriteWhitespace("\n");
//Write GameObject stuff
xml.WriteStartElement("GameObjects");
foreach(GameObject levelPiece in GameObject.FindObjectsOfType(typeof(GameObject)))
{
//Make sure the object has the ObjectName monobehaviour
if(levelPiece.GetComponent<ObjectName>() != null)
{
foreach(GameObject saveable in saveLoadables)
{
//Check if the object name in saveLoadables is the same as the object we are trying to save
if(levelPiece.GetComponent<ObjectName>().objName.Equals(saveable.GetComponent<ObjectName>().objName))
{
xml.WriteStartElement(levelPiece.GetComponent<ObjectName>().objName);
{
//Position
xml.WriteElementString("POSX", levelPiece.transform.position.x.ToString());
xml.WriteElementString("POSY", levelPiece.transform.position.y.ToString());
xml.WriteElementString("POSZ", "0");
//Rotation
xml.WriteElementString("ROTX", levelPiece.transform.rotation.x.ToString());
xml.WriteElementString("ROTY", levelPiece.transform.rotation.y.ToString());
xml.WriteElementString("ROTZ", levelPiece.transform.rotation.z.ToString());
xml.WriteElementString("ROTW", levelPiece.transform.rotation.w.ToString());
}
xml.WriteEndElement();
xml.WriteWhitespace("\n");
}
}
}
}
xml.WriteEndElement();
xml.WriteWhitespace("\n");
xml.WriteEndElement();
xml.WriteWhitespace("\n");
xml.WriteEndDocument();
}
}
public void loadLevel(string levelName)
{
//Delete EVERYTHING
foreach(GameObject levelPiece in GameObject.FindObjectsOfType(typeof(GameObject)))
{
Destroy(levelPiece);
}
Vector3 pos = new Vector3(0, 0, 0);
Quaternion rot = new Quaternion(0, 0, 0, 0);
using(XmlTextReader reader = new XmlTextReader(levelDirectory + levelName + ".lvl"))
{
while(reader.Read())
{
if(reader.IsStartElement())
{
foreach(GameObject obj in saveLoadables)
{
if(obj.GetComponent<ObjectName>() != null)
{
if(reader.Name.Equals(obj.GetComponent<ObjectName>().objName))
{
objectCount++;
//Position
pos.x = float.Parse(reader.ReadElementString());
pos.y = float.Parse(reader.ReadElementString());
pos.z = float.Parse(reader.ReadElementString());
//Rotation
rot.x = float.Parse(reader.ReadElementString());
rot.y = float.Parse(reader.ReadElementString());
rot.z = float.Parse(reader.ReadElementString());
rot.w = float.Parse(reader.ReadElementString());
Instantiate(obj, pos, rot);
}
}
}
}
}
}
}
}
Now, something you need to know is that the script ‘ObjectName’ is a script, that literally only holds the objects name. I used it because I didn’t want to have to parse the object name with (clone). Any questions just ask.