0
\$\begingroup\$

I need to read a text file containing two pieces of information on each line, and use that information to instantiate a prefab at the correct location in a Unity3D game (c# script). The locations are either North, South, East, or West (each a particular vector).

For example, the first line of the text file might read: landmark1, North

In a script, I need to instantiate landmark1 and assign it to case North vector.

The below script is what I've got so far. Basically, I can read from the text file but I don't know how to assign that information to different cases. I'm guessing I need to use an array somehow but I'm not sure how to do that here.

Any help would be appreciated. Thanks!

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using System.Linq;
using System.IO;
using System;

public class Landmarks : MonoBehaviour {

    //spawnable prefab gameobjects
    public GameObject castle;


    // Use this for initialization
    void Start()
    {

        StreamReader reader = new StreamReader(@"C:/Users/.../landmarks.txt"); //insert full path here
        String textContents = reader.ReadToEnd();

        // string[] dataArray = 

        for (int i = 0; i < (textContents.Length); i++)
        {

            //set case if first line = "castle, North" then instantiate object castle at vector 'north';

        }
    }
}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Here's how I'd approach an issue like this.

  1. Define an enum for each set of special keywords you want to reference in your file. eg.

    [System.Serializable]
    public enum Landmark : int {
       Castle,
       Mountain,
       Forest,
       Temple
    }
    
    [System.Serializable]
    public enum Site : int {
       North,
       East,
       South,
       West
    }
  2. Associate these enumeration values with their corresponding prefabs / vectors inside your game.

    In this answer, I show a method to create a friendly, inspector-editable list with entries for each enumeration value, that automatically adjusts if you add / remove / re-order values in your enumeration.

  3. Use a structured data format for your input file - I'd recommend something standard and in common use like JSON or XML.

    There are existing deserialization libraries for these data formats that will do the text parsing for you. So instead of manipulating strings of text yourself, you can let the deserializer digest it into a structured format something like this:

    [System.Serializable]
    public struct LandmarkLocation {
        public Landmark landmark;
        public Site site;
    }
  4. Now you can iterate over a collection of structured entries like the one above returned by the deserializer, look up the corresponding prefab / location from your table, and perform the instantiation. It'll look something like this:

    LandmarkLocation[] locations = MyDeserializer.Deserialize(text);
    
    foreach(var location in locations) {
        Transform prefab = landmarkIndex.GetPrefab(location.landmark);
        Vector3 position = siteIndex.GetVector(location.site);
        Instantiate(prefab, position, Quaternion.identity);
    }

    The advantage of this style is clean, readable code, without a lot of messy string parsing fussing in the middle of your gameplay logic. It lets the battle-tested deserializer do what it's good at, with a clear contract established by the enum and struct types to ensure your data is clean and conforms to the expected structure. If it doesn't, the deserializer can handle detecting & generating the appropriate errors.

\$\endgroup\$
4
  • \$\begingroup\$ Can I still use a text file that's editable after the game is built with this solution? I'm just trying to make a small game where students can edit their own text files and create a little game to test on each other as a learning project. \$\endgroup\$
    – Kandel
    Feb 25, 2019 at 22:09
  • \$\begingroup\$ Yes. The students won't be able to invent new landmark prefabs or new site vectors this way, since those are specified inside the game binary, but they can still edit the JSON (or other format) text file to specify which of the existing landmarks / sites to use. This strategy keeps the set of valid inputs fixed, while letting the text file select from those valid inputs. \$\endgroup\$
    – DMGregory
    Feb 25, 2019 at 22:14
  • \$\begingroup\$ Great! Thanks. How do I associate an enum with a vector 3? Would I use a public Transform or something similar? I'm a researcher rather than a coder so my programming knowledge is patchy. \$\endgroup\$
    – Kandel
    Feb 25, 2019 at 23:52
  • \$\begingroup\$ You could use a public transform, or a public Vector3, whatever you find convenient to work with. \$\endgroup\$
    – DMGregory
    Feb 25, 2019 at 23:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .