How to ship a build with text file assets in Unity

Hey folks, hope your Sunday is going well. I was following along with the Terminal Hacker lectures and decided I didn’t like the way I had my code split up between a few files so I deleted everything and rewrote the entire code in a few hours last night.

The game is ready to build but the problem I’m running into is that the text files I have in my TextFiles folder under Assests isn’t loading with the build. I’ve done some reading and found out that when you build something in Unity things like text files don’t ship (build) with it. I’ve also read a work around is either using Application.Data or Resources.Load and dropping my text files in a Resources folder but I can’t figure out how to get either of these options to work.

Here’s my code:

using UnityEngine;

public class SceneManager : MonoBehaviour
{
    // config params
    string welcomeMessageTextPath = "Assets/TextFiles/Introduction_and_directions.txt";
    string menuTextPath = "Assets/TextFiles/Menu_Text.txt";
    string libraryPasswordTextPath = "Assets/TextFiles/Easy_Password.txt";
    string policeStationPasswordTextPath = "Assets/TextFiles/Medium_Password.txt";
    string nasaPasswordTextPath = "Assets/TextFiles/Hard_Password.txt";

    string invalidInput = "Invalid input, try again.";
    string menu = "menu";
    string levelOne = "1";
    string levelTwo = "2";
    string levelThree = "3";
    string level;
    string activePassword;
    string scrambledPassword;

    int min = 0;


    string[] libraryPasswords;
    string[] policeStationPasswords;
    string[] nasaPasswords;

    TextManager myTextReader;

    // State variables
    enum Screen { Welcome, MainMenu, Password, Win };
    enum PasswordLevel { Library, PoliceStation, NASA };
    PasswordLevel currentLevel;
    Screen currentScreen = Screen.Welcome;

    // Starts the game
    void Start()
    {
        myTextReader = GetComponent<TextManager>();
        WelcomeScreen();
    }

    private void Update()
    {
        EscapeToQuit();
    }

    // Initializes welcome screen and game instructions
    private void WelcomeScreen()
    {
        currentScreen = Screen.Welcome;
        myTextReader.ReadText(welcomeMessageTextPath);
    }

    // initializes the actual password-guessing game when player types a number and hits return key
    private void StartGame(string level)
    {
        Terminal.ClearScreen();
        Terminal.WriteLine("You have chosen level " + level);
        Terminal.WriteLine("Enter the password:");
    }

    // Allows user to go back to menu at any time,
    // resets active password,
    // displays menu text if on the menu screen

    void OnUserInput(string input)
    {
        if (input.ToLower() == menu)
        {
            Terminal.ClearScreen();
            activePassword = "";
            currentScreen = Screen.MainMenu;
            myTextReader.ReadText(menuTextPath);
        }
        else if (currentScreen == Screen.MainMenu)
        {
            RunMainMenu(input);
        }
        else if (currentScreen == Screen.Password)
        {
            PasswordCheck(input);
        }
        else if (currentScreen == Screen.Win)
        {
            Terminal.WriteLine("Congratualtions you guessed right! Type menu to play again.");
        }
    }

    // On user choice switches to chosen scenario and prompts user for a password
    private void RunMainMenu(string input)
    {
        if (input == levelOne)
        {
            ScreenChange(input);
            StartGame(input);
            SetPasswordLevel(input);
        }
        else if (input == levelTwo)
        {
            ScreenChange(input);
            StartGame(input);
            SetPasswordLevel(input);
        }
        else if (input == levelThree)
        {
            ScreenChange(input);
            StartGame(input);
            SetPasswordLevel(input);
        }
        else
        {
            Terminal.WriteLine(invalidInput);
        }
    }

    private void ScreenChange(string input)
    {
        currentScreen = Screen.Password;
    }

    private void SetPasswordLevel(string input)
    {
        if (input == levelOne)
        {
            libraryLevel();
        }
        else if (input == levelTwo)
        {
            PoliceLevel();
        }
        else
        {
            NASALevel();
        }
    }

    /// These three functions read a text file with pre-typed words as passwords,
    /// writes those to a string array and then randomly selects one as the active password
    private void NASALevel()
    {
        currentLevel = PasswordLevel.NASA;
        nasaPasswords = File.ReadAllLines(nasaPasswordTextPath);
        activePassword = nasaPasswords[Random.Range(min, nasaPasswords.Length)];
        passwordShuffler(activePassword);
        Terminal.WriteLine("The password is " + scrambledPassword);

    }

    private void PoliceLevel()
    {
        currentLevel = PasswordLevel.PoliceStation;
        policeStationPasswords = File.ReadAllLines(policeStationPasswordTextPath);
        activePassword = policeStationPasswords[Random.Range(min, policeStationPasswords.Length)];
        passwordShuffler(activePassword);
        Terminal.WriteLine("The password is " + scrambledPassword);
    }

    private void libraryLevel()
    {
        currentLevel = PasswordLevel.Library;
        libraryPasswords = File.ReadAllLines(libraryPasswordTextPath);
        activePassword = libraryPasswords[Random.Range(min, libraryPasswords.Length)];
        passwordShuffler(activePassword);
        Terminal.WriteLine("The password is " + scrambledPassword);
    }
    // Uses variation of the fisher-yates shuffle to scramble a string
    private void passwordShuffler(string activePassword)
    {
        char[] characterArray = activePassword.ToCharArray();
        System.Random rng = new System.Random();
        int n = characterArray.Length;
        while (n > 1)
        {
            n--;
            int k = rng.Next(n + 1);
            var value = characterArray[k];
            characterArray[k] = characterArray[n];
            characterArray[n] = value;
        }
        scrambledPassword = new string(characterArray);
    }

    private void PasswordCheck(string input)
    {
        input = input.ToLower();
        if (input == activePassword)
        {
            Terminal.ClearScreen();
            Terminal.WriteLine("Welcome, user. You are now root.");
            currentScreen = Screen.Win;
        }
        else
        {
            Terminal.WriteLine("Password incorrect. Did you remember to unscrambled your eggs?");
        }
    }

    private void EscapeToQuit()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Quit();
        }
    }

    private void Quit()
    {
        Application.Quit();
    }
}
using System.IO;
using UnityEngine;

public class TextManager : MonoBehaviour
{
   public void ReadText(string filePathName)
    {
        StreamReader streamReader = new StreamReader(filePathName);
        Terminal.WriteLine(streamReader.ReadToEnd());
        streamReader.Close();
    }
}

Pls Halp

Regarding generating builds to include the text files I think this will work:
You need to create a special folder called “StreamingAssets” in the root of you assets folder. Details in the doc link below
https://docs.unity3d.com/Manual/StreamingAssets.html

Another option If you dont plan on allowing the end user to edit your text files is some manner is that you could use “Scriptable Objects” to store the password etc for you game instead of text files. SOs are covered in the course I dont recall which section though but they are part of unity and designed to be used as data containers.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms