Iterating and reading text files from folder on Android - unity3d

I made a word game app for android in Unity, where the player has to find a word from a category previously loaded to the game.
The way I load the categories is:
There is a folder named Categories, inside Assets, I run through the folder and read each text file as a category.
The categories are stored in a dictionary where the key is name the of the file and the value is every line of the file as an array element.
It worked well on the PC however no luck on android. Tried changing the path to
"public string categoriesDirectoryPath = Application.persistentDataPath +"Categories";" still does not work.
Original path was "Assets/Categories"
Code for initiating the dictionary with the file values is (Happens on GameManager's Awake()):
private Dictionary<string, string[]> createCategories(string directoryPath)
{
Dictionary<string, string[]> categories = new Dictionary<string, string[]>();
string[] categoryPaths = Directory.GetFiles(directoryPath);
foreach (string path in categoryPaths)
{
if (!path.EndsWith("meta")) {
Debug.Log(path);
string categoryName = Path.GetFileNameWithoutExtension(path);
Debug.Log(categoryName);
string[] categoryData = File.ReadAllLines(path).ToArray();
categories.Add(categoryName, categoryData);
}
}
return categories;
}
Is there a way of iterating the folder and reading the text files that were in Assets/Categories after building the APK?

Is there a way of iterating the folder and reading the text files that
were in Assets/Categories after building the APK?
No.
If you want to access from the project, in a build, you have two options:
1.Put the file a folder named "Resources" then use the Resources to read the file and copy it to the Application.persistentDataPath path. By copying it to Application.persistentDataPath, you'll be able to modify it. Anything in the "Resources" is read only.
2.Put the file in the StreamingAssets folder then use UnityWebRequest, WWW or the System.IO.File API to read it. Atfer this, you can copy it to the Application.persistentDataPath.
Here is a post with code examples on how to do both of these.
3.AssetBundle(Recommended due to performance and loading reaons).
You can build the file as AssetBundle then put them in the StreamingAssets folder and use the AssetBundle API to read it.
Here is a complete example for building and reading AssetBundle data.

Related

How to load asset with same name, but placed in different folders from assetbundle?

I am using unity5.3.3, I would like to know how should I get the asset from an asset bundle, whose names are same but are kept in different folder. My AssetBundle Folder is set in the following manner:
MyAssets -> this Folder is packed as an AssetBundle
-ThemeOne(folder)
- Logo.png
-ThemerTwo(folder)
- Logo.Png
When I do AssetBundle.LoadAssetAsync("Logo"). I end getting the logo in the first(ThemeOne) folder. So how do I access the file in the other folder?
I have just created a sample project so that you can check it out. Check the Folder Assets\AssetBundleSample\SampleAssets\Theme and the script LoadAssets
You can put the ThemeOne(folder) and ThemeTwo(folder) in Resources Folder under assets and than use something like this
(AudioClip)(Resources.Load ("Sounds/" + "myaudioclip", typeof(AudioClip)) as AudioClip)
similarly load your png giving folder name first as i have given sounds and than name of file as i have given myaudioclip .
cast as texture or something as you want
As unity official docs provided
public string BundleURL;
public string AssetName;
IEnumerator Start() {
// Download the file from the URL. It will not be saved in the Cache
using (WWW www = new WWW(BundleURL)) {
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
BundleURL will use the path where your actual assets is located. You can also use Application.dataPath in conjunction with ur specified path string.
Seems to be a bug. Still present in Unity version 5.3.3.
See: http://answers.unity3d.com/questions/1083400/asset-bundle-cant-have-multiple-files-with-the-sam.html
I'm not really sure if this is possible, you should read Explicit naming of assets which is FYI obsolete as on Unity 5.6. This allows you to explicitly name assets that you are including in the bundle. Alternatively, you could try,
bundle.LoadAsset("/Assets/ThemerTwo/Logo.png")
But generally, this is a bad practice to have assets of the same naming in the same bundle.
You can use the method LoadAssetAtPath() to specify the full path instead of just the asset name.
Example:
LoadAssetAtPath("Assets/Texture/Logo.jpg", typeof(Texture2D));
Documentation here: http://docs.unity3d.com/ScriptReference/AssetDatabase.LoadAssetAtPath.html

Using resource files (CultureInfo) in C# class file

I need a help with using resource files in C# class files.
My code:
class errorMessages
{
private static ResourceManager LocRM = new ResourceManager("Project1.languageFile", typeof(errorMessages).Assembly);
public static void XMLParseError(String msg)
{
MessageBox.Show(LocRM.GetString("XMLParseError") + "\n" + msg, LocRM.GetString("error"),
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
}
}
+ created 2 .resx files named languageFile.en.resx and languageFile.pl-PL.resx in main Project1 folder
Now I want to use String from languageFile, in my class errorMessages, specified to localization which was set before. How can I do it?
I tried to add my Strings to WinForm .resx file, but that's clearing my data with any edit of WinForm.
I found answer for my question by myself, so I will write that solution, I hope it will help somebody.
Default resources file is located in [projectName]/Properties. I you want to add manually localizable resource files, you need to do that this way:
right click on Project in Solution Explorer -> Add new item -> resource file
Then set the name of file to Resources.[language].resx - in my case that are two files, Resources.pl-PL.resx and Resources.en.resx. After file is created, move it to Properties directory.
Now you can add your resources and use it this way:
MessageBox.Show(Project1.Properties.Resources.XMLParseError, Project1.Properties.Resources.information,
MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
Now chosen String will be in language setted in CultureInfo, or, if there is no that resource, default Resource file will be used.
source: MSDN - How to: Create a Localized Version of a Resource File

Why my System can not find one of two mp3 files which are in the same folder?

I just want to have 2 Objects from Type "Media". Therefore i have 2 .mp3 files.
The first is no problem, i can play it.
But if i enable the Code for the second file, the System throws an Error
"InvocationtargetException" it says "System can not find the file"
I checked both paths of the .mp3 files, here are the results:
file:/C:/Users/Lennie-Admin/Documents/NetBeansProjects/Lost/Rise.mp3
file:/C:/Users/Lennie-Admin/Documents/NetBeansProjects/Lost/TrueStrength.mp3
I checked my working directory with System.out.println( new File("").getAbsolutePath()); the Result is
C:\Users\Lennie-Admin\Documents\NetBeansProjects\Lost
And finally here is the java Code, which should create the 2 Objects:
String uriString1 = new File("Rise.mp3").toURI().toString();
Media hit1 = new Media(uriString1);
String uriString2 = new File("TrueStrength.mp3").toURI().toString();
Media hit2 = new Media(uriString2);
Hope you can help me :)

How to avoid two files in project view when creating a custom importer in Unity3D?

NOTE: I'm casting a wider net than Unity Answers, my original question can be found here.
I've created a ProTools CueSheet importer. It uses OnPostprocessAllAssets() to detect a files in the project that have a .cuesheet extension. It then runs those cuesheet files through my parser. This generates a ScriptableObject which is then turned into an asset via Database.CreateAsset().
The problem is, this leaves me with two files, the original cuesheet and the newly generated asset. Is there any way I can generate the asset in such as way that the original cuesheet acts as the asset, the same way textures or FBX files do?
public class CueSheetPostProcessor : AssetPostprocessor {
static string extension = ".cuesheet";
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
foreach (string assetPath in importedAssets) {
if (assetPath.EndsWith(extension, StringComparison.OrdinalIgnoreCase)) {
string newPath = assetPath + ".asset";
Session session = CueImporter.Load(assetPath);
AssetDatabase.CreateAsset(session, newPath);
AssetDatabase.SaveAssets();
}
}
}
}
I would create a PropertyDrawer for the Serializable class CueSheet such that it accepts the .cueSheet TextAsset or path to the .cueSheet file and create an instance of the class CueSheet and assign it or modify it.
Rather than create a new asset, have you tried using AssetDatabase.AddObjectToAsset instead? An file in Assets can "hold" multiple assets and multiple asset types. When importing a .fbx, the output in the project inspector is several things: a GameObject tree (ie, a prefab), some models, maybe a rig, and so on. All these are "contained" in the processed .fbx

Mirth: How to get source file directory from file reader channel

I have a file reader channel picking up an xml document. By default, a file reader channel populates the 'originalFilename' in the channel map, which ony gives me the name of the file, not the full path. Is there any way to get the full path, withouth having to hard code something?
You can get any of the Source reader properties like this:
var sourceFolder = Packages.com.mirth.connect.server.controllers.ChannelController.getInstance().getDeployedChannelById(channelId).getSourceConnector().getProperties().getProperty('host');
I put it up in the Mirth forums with a list of the other properties you can access
http://www.mirthcorp.com/community/forums/showthread.php?t=2210
You could put the directory in a channel deploy script:
globalChannelMap.put("pickupDirectory", "/Mirth/inbox");
then use that map in both your source connector:
${pickupDirectory}
and in another channel script:
function getFileLastModified(fileName) {
var directory = globalChannelMap.get("pickupDirectory").toString();
var fullPath = directory + "/" + fileName;
var file = Packages.java.io.File(fullPath);
var formatter = new Packages.java.text.SimpleDateFormat("yyyyMMddhhmmss");
formatter.setTimeZone(Packages.java.util.TimeZone.getTimeZone("UTC"));
return formatter.format(file.lastModified());
};
Unfortunately, there is no variable or method for retrieving the file's full path. Of course, you probably already know the path, since you would have had to provide it in the Directory field. I experimented with using the preprocessor to store the path in a channel variable, but the Directory field is unable to reference variables. Thus, you're stuck having to hard code the full path everywhere you need it.