I have an assessment to create a weapon system for a first person game. Unfortunately the professor decided to opt to use java script which is something I am not very well acquainted with. I am just setting up the classes and structure and have come across an issue. I mainly use c++ so c# isn’t very difficult to get to grips with. However java script lacks certain feature such as the ability to implement abstract classes and functions. This leaves me with a slight problem.
I have an inventory class that is meant to store an array of weapons/items that the players is carrying. It deals with managing those weapons and leaves their functionality to the weapon and more specialized versions of the weapon class. My “Pistol” class extend the weapon class and has a function called “Use()”. In my inventory class I want to store an array of weapons and then call the Use() function without knowing which type of weapon it is Pistol, Rifle etc. In c# I can use a List class from the stl and then use abstract functions to create a common interface for all the classes derived from Weapon so that all will have a Use function.
How could I do something similar in java script. Here is my code.
//Inventory.js
#pragma strict
class Inventory
{
var equipment = Array(Weapon);
var toggle = Array(int);
var curWeapon : Weapon;
function AddWeapon(id : WeaponID)
{
if (WeaponExists(id))
{
return;
}
switch (id)
{
case WeaponID.PISTOL:
equipment.Add(new Pistol());
break;
}
}
function GetWeapon(id : WeaponID)
{
var i : int;
for (i=0; i<equipment.length; i++)
{
}
}
function WeaponExists(id : WeaponID)
{
var i : int;
for (i = 0; i < equipment.length; i++)
{
if (equipment*.GetID() == id)*
return true;*
}*
return false;*
}*
function ToggleUp()*
{*
}*
function ToggleDown()*
{*
}*
function AddToggle()*
{*
}* } //Weapon.js #pragma strict enum WeaponID{PISTOL} class Weapon {
var ID : WeaponID;*
var weaponName : String;*
var ammo : Magazine;*
var rateOfFire : double;*
var timeToNextShot : double;*
var reload : boolean;*
var reloadTime : double;*
function GetID()*
{*
return ID;*
}* } //Pistol.js #pragma strict class Pistol extends Weapon {
function Pistol()*
{*
ID = WeaponID.PISTOL;*
weaponName = "Pistol";*
ammo = new Magazine(8, BulletID.PISTOL);*
rateOfFire = 20;*
timeToNextShot = rateOfFire/60;*
reload = false;*
reloadTime = 1.5;*
}*
function Use()*
{*
}* } Currently the problem is that the array sees its contents as type “Object” which doesn’t have a GetID() function therefore causing an error in the WeaponExists() function.
Are you required to use Unity and UnityScript (Unity’s Javascript)? or is the only requirement to use [JavaScript (ECMAScript)][1] which is something completly different.
I guess we talk about UnityScript (if not this wouldn’t be the right place for the question ;)). In general you can do exactly the same UnityScript and C#. There are only a few language specific differences. Both languages are compiled to a .NET / Mono assembly. In the end both languages result in the same intermediate code.
That means you are free to use any classes in both languages. So to answer one part of your question, use a generic List instead of the untyped Array class. I guess since Unity version 3.0 (±X) UnityScript also has a syntax for using generic types. You can’t define generic types but you can use them. The only difference is an additionally dot “.”:
var myList : List.<Weapon>;
That should fix your casting problems.
Btw if you would use the Array class you would need to cast the object references into Weapon references:
var tmp : Weapon = equipment *as Weapon;*
tmp.GetID(); But casting all the time is slow so use the generic List unless you have to use the Array. Next thing is abstract classes are like normal classes but they can’t be instantiated on their own. Only derived classes can be created. As far as i know UnityScript doesn’t have the abstract keyword, but i could be wrong, i never use UnityScript Furthermore since Unity 3.0 in UnityScript all methods are by default virtual. If you want a function to be not virtual you have to use the “final” modifier. Also in UnityScript methods get automatically overridden: class JBase { function Blubb() : int { return 0; } }
class JDerived extends JBase { function Blubb() : int { return 5; } }
// Test case:
var T = new JDerived(); Debug.Log("JDerived: " + T.Blubb()); var B = new List.(); B.Add(T); Debug.Log("JBase: " + B[0].Blubb()); This will print: “JDerived: 5” “JBase: 5” That should answer your main questions. Just a final hint: In Unity you usually use Components (classes derived from MonoBehaviour) which have to be attached to a GameObject. In this case you can’t create an instance with “new”. Such classes have to be created with [AddComponent][2] or dragged onto a GameObject / prefab in the editor. You can of course use “normal” classes which are not derived from MonoBehaviour. However a weapon usually represents a GameObject with a Mesh, Renderer, Collider and of course a behaviour script. You can use normal classes to manage your weapons beside the actual engine representation of the weapon, but it usually complicates the whole thing. I can’t give you more specific hints since it depends on what you exactly have to create. [1]: ECMAScript - Wikipedia [2]: Unity - Scripting API: GameObject.AddComponent
Javascript arrays always contain Objects, no matter what the actual class is. If you want to access the GetID function you’re going to have to typecast the Object you get from the Array to whichever class it’s supposed to be.
for (i = 0; i < equipment.length; i++)
{
if (Weapon(equipment*).GetID() == id)*
Thanks for all the information. I knocked up a quick class diagram and Lists are how I have it down in that. Its just that when I use the List class it says "The name List doesn’t denote a valid type. I have access to the List interface (IList). I know that in c# you have use the System.Collection.Generic… How would I include that namespace in java script?