Developer's Diary
How not to do it:
using System; using UnityEngine; using System.Collections; using System.Collections.Generic; /// <summary> /// Needs work. /// </summary> public class Inventory : MonoBehaviour { private Dictionary<string, int> backpack; private bool showInventory; void Awake () { } void Start () { DisplayInventory (true); } public void DisplayInventory (bool state) { showInventory = state; } public bool RemoveObject (string iObject, int number) { try { backpack[iObject] = backpack[iObject] - number; if (backpack[iObject] <= 0) { backpack.Remove (iObject); } return true; } catch (Exception ex) { print ("[" + this.GetType ().ToString () + "] The object " + iObject + " does not exist."); return false; } } public bool AddObject (string iObject, int number) { if (backpack.ContainsKey (iObject)) { backpack[iObject] += number; } else { backpack[iObject] = number; } return true; } void OnGUI () { if (showInventory) { int counter = 0; foreach (KeyValuePair<string, int> kv in backpack) { string displayString = kv.Key + ": " + kv.Value.ToString (); GUI.Label (new Rect (10, counter * 40, 200, 30), displayString); counter++; } } } }
How to do it instead:
using System; using UnityEngine; using System.Collections; public class ChickenCounter : MonoBehaviour { private int counter = 0; public GameObject particleEffect; void OnTriggerEnter (Collider hit) { if (hit.tag == "bonus") { counter++; Instantiate (particleEffect, hit.transform.position, hit.transform.rotation); Destroy (hit.gameObject); } } void OnGUI () { GUI.Label(new Rect(10,10,200,30),
Just a few notes from the battlefield that is my game for Fantoche:
Build Order Matters
Whenever you get the error message «The type or namespace name <type/namespace> could not be found (are you missing a using directive or an assembly reference?)» in Unity when trying to access a component on another GameObject, do not bother to rewrite your complete code.
Just check the folders your classes are in: If your referenced classes are somewhere in the top Assets folder while your referencing class is in the Standard Assets, you will have a problem, since scripts in Standard Assets are compiled first – and as such, compiled before the referenced classes even exist.
Reverse the placement or just put them all in one folder, and you are set.
Yield Instructions in C#
yield instructions in C# are a bit unwieldy. Most of all, they need a Coroutine that returns a IEnumerator. To get this type in MonoDevelop, add using System.Collections; to the top of your class.
Load Resources Dynamically
Assets residing in a folder called Resources (big surprise) can be loaded at runtime using Resources.Load(). To get the assets as the right type, use
AudioClip clipObj = Resources.Load("GoodAfternoon") as AudioClip;
On Other News
The XMLStringReader has been rewritten to support path strings for audio files (residing, as you might have guessed, in the Resources folder). Also: a trigger script with which those strings can be accessed and the audio played.
More of that in a later post, though. My hair is dry enough to go to bed now.
Since I already played around with XML in C#, this part of the project was easier to do than before.
What is it supposed to do?
Basically, I could simply hard-code most of my strings used in the game directly into the code – no one would notice the difference anyway. But obviously, this is not a very good idea, both because editing strings and later translating them becomes a pain.
Creating some data that would allow me to get strings out of an XML file would solve this problem – and, if the code is good enough, be reusable in later games.
It would allow me to edit text independently of the game code and add translations on a later date.
Since I want to make some basic statistics for my game at Fantoche, I needed some basic logging function of the player's position.
Of course, this could also be done using a simple CSV file, but the perfectionist in me insisted on an XML format. A preliminary test showed me, that I would be able to transform the XML to a CSV later on, so that my S.O. would be able to use it in his own programs.1
Having set up my development environment in MonoDevelop, I started to work on the problem on how to get my data into a well-formed XML representation and onto the hard disk.
The first approach was to use serialisation. I created a Location class, with all the necessary attributes – until I realised that this would only allow me to get one dataset into a file. I wouldn't be able to add more data to the file.
Conclusion: Serialisation is only good when you have one clearly defined object you want to dump onto the drive as a well-formed XML file.
So I tried to work with the XMLWriter.
-
So why again am I doing it with XML? Good question. Because I can? Does that make me a nerd? ↩
(Articles tagged with "Developer's Diary" are more sketches – ideas and thought processes behind current projects, so that they can be assembled as documentation at a later date. Comments and further thoughts are highly encouraged.)
The exercise consists of creating an autonomous software agent that interacts on a 2D plane. Also, it has to work together with other available agents.
In order to let the agent choose an appropriate action, it should contain a stack with possible tasks with priorities. In every turn, the task with the highest priority is executed.
Every task contains different actions that have to be done. Those actions are universal and can be shared.
Possible actions may be:
- Finding the way to an object
- Moving
- Avoiding obstacles
Possible task could be:
- Finding and absorbing food
The stack is used in order to allow for interruptions to happen. The agent will be able to answer to the interruption and take up the interrupted task afterwards. Given the assigned priority, the agent can also choose to ignore some interruptions and continue the started task.