# C# class works in Unity, but not in Android build

I am using Unity to program a simple Android game in C#. Right now, all the game does is to randomly load one of 196 flags upon startup (view: https://hastebin.com/suxonayoce.cs or code below). This class file is currently the only class file there is. When I play the game in Unity everything works as expected (i.e. each time the game is started a random flag is displayed). However, when I build and run the game on my Android phone only the placeholder flag is displayed and never a randomly chosen one.

So far I've tried relaunching Unity, re-importing all assets, and recreating the game in a new project. Nothing of this has resolved the problem.

using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
private int _flagCount = 196;

private string[] _ccTlds;
private void GenerateCctldsArray()
{
_ccTlds = new string[_flagCount];
}

private void DisplayRandomFlagSprite()
{
// Randomly gets the file name of a flag.
int flagArrayPosition = Random.Range(0, 195);
string flagImageName = _ccTlds[flagArrayPosition];

// Gets the sprite of the flag called "flagName".
Sprite sprite = Resources.Load<Sprite>(@"FlagSprites\" + flagImageName);

// Loads the image associated with "flagName".
FlagImage.GetComponent<Image>().sprite = sprite;
}

[SerializeField]
private GameObject _flagImage;
public GameObject FlagImage
{
get { return _flagImage; }
set { _flagImage = value; }
}

private void Awake()
{
GenerateCctldsArray();
DisplayRandomFlagSprite();
}
}


Does anyone have any ideas why the games stops working when it is run on the phone and how this can be fixed?

Disclaimer: I don't have an Android test setup at present, so the following is speculation.

I suspect this has to do with how you're trying to read your text file.

The file exists at {ProjectPath}\Assets\ccTLDs.txt on your development machine, but that's not necessarily where the file gets packed into an Android build. In fact, if Unity can't detect anything referencing that text file, it might not include it in your game build at all (since it tries to prune unused assets)

So, instead of trying to load it from a path using File IO APIs, I'd recommend assigning the asset file to a public TextAsset ccTLDs; member variable you configure in the Inspector.

This ensures you have a portable reference to it that will work on any platform, and that Unity can see the reference so it doesn't try to prune it out of your build.

Then you can replace these lines:

_ccTlds = new string[_flagCount];                  // <-- This line does nothing useful
_ccTlds = File.ReadAllLines(@"Assets\ccTLDs.txt"); // (since it's immediately replaced)


with

_ccTlds = ccTLDs.text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

• I just want to mention, that sometimes when you are trying to read/write files in a "custom way" android doesn't like it. I tried writing to a local file inside my project, and the android build would hung there and run infinitely. Not sure if this has anything to do with permissions, as you are messing with local project files, but there's definitely something going on there. Sep 12, 2018 at 14:34
• I think your answer works around this point, but might it be worth mentioning that only Windows likes backslashes? Dec 29, 2021 at 19:10

I too believe there is something wrong in reading the file.

First things, first.Debug it. When you read succesfully the file, show a text in the screen , etc.

Secondly use this for the applications path in Android.

 Application.persistentDataPath


It could be because you need to set a random seed before using the random range, considering this similar problem.

Although I think that UnityEngine.Random's seed is deprecated after 5.3, so maybe use the System.Random?

Example with UnityEngine.Random:

public class Example : MonoBehaviour
{
public float bias;

public void GenerateRandom()
{
#if !UNITY_EDITOR
Random.seed = Input.acceleration.magnitude * (1f + bias); /// Maybe you could use the accelerometer to get the seed.
#endif

float randomNumber = Random.Range(0.0f, 100.0f);
Debug.Log(randomNumber.ToString());
}
}


Example with System.Random:

public class SystemExample : MonoBehaviour
{
public int maxRange;

public void GenerateRandom()
{
/// Maybe you could use the accelerometer to get the seed.
int seed = (int)(Input.acceleration.magnitude * (1f + bias));
Random rng = new Random(seed);

/// Returns a non-negative random integer that is less than the specified maximum.
int randomIndex = Random.Next(maxRange);
Debug.Log(randomIndex.ToString());
}
}


To know more about random seeds. Hope it helps.

• I believe that your solution might work in the case where one is generating the same "random" number(s) every single time. However, in my case, the image that shows is one that cannot be loaded no matter which number is generated as the image is not part of the array to which the random numbers are fed in. I think that my problem may be caused by inadequate permission, but I have not figured out how to test this hypothesis yet. Jun 11, 2018 at 8:56
• Setting a seed is not required when using UnityEngine.Random, so I doubt this would be the cause of the issue. Jul 13, 2018 at 1:29