Reusable Classes, Unit test and Assert

Hello,

I have been using Unity for a few months now, and I read though several of the tutorials and documentation I found, so now I feel ready to start creating a somewhat large project.

I have a lot of experience programming outside of Unity and for a larger project I found myself missing some features that greatly help keep things in order.

So, I came seeking your help with the following:

1- I want to create a reusable class and access it in all my scripts (the same way I can access Vector3 for instance). What would be the best way to do that?

2- Is there any support for Asserts in Unity?(specifically in javascript, but any language would be nice)

3- What is the best way to implement Unit tests for my scripts?

4- If I want to implement a Value Object to access from all my scripts, where and how should I code such a class? (this relates with question 1)

That´s it I think. I did search this with no success, so any help will be deeply appreciated.

Thanks in advance,
G. Otranto

To answer question 1 (and maybe 4?), using Javascript I’ve been able to get most of what I need done globally with Static functions and variables in seperate scripts, which don’t need to be assigned to any object.

For example, a lot of utility calculations I create I put as static functions in a script called Toolbox, so in any script I can say

variable = Toolbox.CalcSlope(x1,x2,y1,y2), if I had a slope calculation function.

It doesn’t quite replace the Object Class system, but this can be emulated with scripts applied to actual object prefabs that are instantiated, if there aren’t too many required in existence at one time.

you say you’ve got a lot of programming experience, so those are probably old news to you. I don’t know if any of that helped, but I hope so.

It does help, actually. I did look into this as a solution for a few of our requirements, and it is so far the best approach I could think of.

I haven´t really implemented anything using it though, so it´s good to know it will work, thanks!

Just realized I needed some further clarification. This solution will work nicely to expose some kind of API in a organized way. It would simulate the function Vector3.Distance for instance.

The problem here is that this solution won´t allow me to actually have several instances of some value object I might need. Suppose I want to implement a Vector5 for some reason, and I would like to deal with this Vector5 the same way I deal with its existing relatives (Vector3 and Vector4).

It gets a bit over my head at that point, since I’m pretty new to JS and Unity.

hmm, the only thing I can think of would be prefabs of empty game objects with individually defining scripts and group tags. Each prefab, when kept in a resource folder, can be instantiated as needed using its name (and path within the resource folder) as a string with ResourceLoad, which helps remove the need to link it to the inspector in a lot of scripts, and allows you to use string variables.

These objects, when instanced, would ideally be stored in a variable in the instancing script, which can perhaps add it to a static array holding all the currently active emulated objects, (or a hashtable with their type), to be used by any script later. So the game object will exist as a code object in this form, though it might be best to store its script instead of the object itself (to allow changes to variables as needed, and calling of functions).

This does little to get around the lack of inheritance (other than cloning), but I think its possible that creating objects in this manner would allow you to deal with, create, and destroy multiple code objects of various types, working around any limitations. Although it might require a bit more thinking ahead, and perhaps the occaisional switch(typeof …).

Well, I got what I wanted working after a bit of trial and error here. It seems obvious to me now, but I will post it nevertheless.

I got a reusable class working for me now, in both C# and later JS too. Here´s what I wrote:

The reusable class, stays only in the Assets folder, it´s not bound to any GameObject:

using UnityEngine;
using System.Collections;

public class ReusableClass {

	private int myNumber;
	
	public ReusableClass(int n)
	{
		myNumber = n;
	}
	
	public void sayHi()
	{
		MonoBehaviour.print("Hello, my number is "+ myNumber);
	}
}

And to use it, I attached the following script to my player game object (just as an example):

using UnityEngine;
using System.Collections;

public class TestClass : MonoBehaviour {

	ReusableClass h;
	ReusableClass l;
	
	// Use this for initialization
	void Start () {
		h = new ReusableClass(5);
		l = new ReusableClass(2);
	}
	
	// Update is called once per frame
	void Update () {
		h.sayHi();
		l.sayHi();
	}
}

As expected, the player proceeded to print out 5 and 2 every game cicle.

The reusable class in this case does not inherit from MonoBehaviour, so I expect that if one tries to attach it to a game object, all kinds of errors will appear (But this script was not made for that purpose, it´s meant to be used the same way Vector3 is used).

Hopefully this will help some lost souls. =)

Oh, and if one prefers the JavaScript Solution, here it is (Yes, the class name is …Java and not …Javascript or …JS, this is due to my laziness to change it, no need to point that these are two very, very different things. I just needed a different name because I was unwilling to delete my c# code - or move it, for that matter).

The reusable class code (this sits in the assets folder and it is NOT attached to a GameObject):

class ReusableClassJava {

	private var myNumber;
	
	public function ReusableClassJava(n)
	{
		myNumber = n;
	}
	
	public function sayHi():void
	{
		MonoBehaviour.print("From JS: Hello, my number is "+ myNumber);
	}
}

And this is how to use it, the following script was attached to a GameObject in the scene:

var h : ReusableClassJava;
var l : ReusableClassJava;
	
function Start () 
{
	h = ReusableClassJava(5);
	l = ReusableClassJava(2);
}
	
function Update () 
{
	h.sayHi();
	l.sayHi();
}

I did use the facility of not declaring the class in this one, but you could just as well have the whole class code on the file (just remember to inherit from MonoScript in this one)

Again, hope this helps, and if anyone has a clue as to the other questions, I will appreciate a notch in the right direction.

Very useful. Thanks for posting this.
Glad to know that a class/script doesn’t HAVE to be assigned to a game object :slight_smile:

but it isn’t needfully good design to instantiate monobehaviours with new as shown in above example.

in that case you would likely extend something like Object or ScriptableObject, not MonoBehaviour (which is implicitely extended if nothing else is specified) which is for adding as component

You´re right about not being a good idea to instantiate MonoBehaviour with new, but I believe I skipped that problem in the definition.

At least in C#, the default doesn´t automatically extend MonoBehaviour:

“All behaviour scripts must inherit from MonoBehaviour (directly or indirectly). This happens automatically in Javascript, but must be explicitly explicitly inside C# or Boo scripts.”

Now, for javascript I am not sure what the default is if you define the class the way I did (actually using class keyword, etc). My guess is that if you don´t specify the class then it automatically assumes MonoBehaviour, but if you do (through the class keyword), then the default changes (to Object i think).
Keep in mind that the JS part of my post is mostly guesswork, but I am pretty sure about the C# code part.

Anyhow, sorry about the delay to check this thread back, I got caught up with some non-related work. Any answers to my previous questions will still be much appreciated.

G. Otranto

p.s.: My quote is from “Overview: Writing Scripts in C#”, and the typo is there too…

Hello,

I made some tests about classes inside game assets, and I found them VERY interesting!

I wish to send my contribute supplying some information more about Javascript.

To define a function in Javascript (inside assets) you can use either:

public function ReusableClassJavascript(n)

Or…

static function ReusableClassJavascript(n)

It seems they give the same results if you do not use internal variables (static functions can be used only if you don’t need to store private vars). Typical usage is, for example, to implement direct calculations.

More: you can even use inheritance in this way (an example):

  1. Create a Javascript file called “TSubtract”, with the following code:
class TSubtract {
	static function subtract(argNum1:int, argNum2:int) {
		return(argNum1 - argNum2);
	}
}
  1. Create another Javascript file called “TCalc”:
class TCalc extends TSubtract {
	static function sum(argNum1:int, argNum2:int) {
		return(argNum1 + argNum2);
	}
}

NOw you can create a Javascript code, to be attached to an object instance, with the following code:

var calc1:TCalc;
	
function Start () {
	print(calc1.sum(3, 5));
	print(calc1.subtract(3, 5));
}

Very cool (thank you Unity!). :smile:

Another very nice trick is the javascript code, inside assets, can be located in any Folder/Subfolders (CREATE->FOLDER). Inheritance works well even in this way… cool!!!

I hope this will help you!

Thank you.

Interesting indeed..

When I posted the reusable class solution I did not think to test if there were any restrictions, like the ability to extend them (I had actually assumed it would work).

Your example shows just how useful this can be (simple, but very illustrative).

Since I´m here, a little about Unit Testing with Unity and how we are using it in a project:

What we ended up doing was going around Unity for the unit testing.
Using C# classes we managed to get them working and compile them outside of unity (using mono and the UnityEngine.dll - pretty straight forward), them we wrote unit tests using NUnit (www.nunit.org).
With that we could already run test for a single class, as simple as compile (both class and test) and run the NUnit on it.
Then the next step is to automate the process, you can do this with any sort of batch script. We got fancy here and used a tool called SCons (www.scons.org). This made it possible for us to run a single command and compile and test a whole bunch of C# utility classes.

The idea was to get this a little more integrated, but this solution works pretty well also. Hope it helps. It does require a little more programming knowledge, specially if one decides to use SCons.. Be warned.

G. Otranto