Script Weirdness (Or Confusion?)

Take Two:

Hello all,

I am working with the trial and I’m seeing some script weirdness which is a good chance of my misunderstanding, too.

I have a C# Script object which is the heart of my game logic and it keeps track of variables. One is which object is currently being hovered over with the mouse. So I have a GameWorld script attached to an empty “Game” GameObject.

I then have a JS script with OnMouseEnter/Exit functions that call update the GameWorld script that looks like this:

private var engine = null;

function Awake () {
	engine = GameObject.Find("Game").GetComponent("GameWorld");
	if(engine) {
		Debug.Log("Found GameWorld: "+engine.name);
	}
	else {
		Debug.LogWarning("Did NOT find GameWorld");
	}
}

function OnMouseEnter() {
	engine.StartMouseOver(this);
}

function OnMouseExit () {
	engine.EndMouseOver(this);
}

The Engine class looks like this:

using UnityEngine;
public class GameWorld : MonoBehaviour {
	static GameWorld singleton;
	private GameObject mouse_over = null;

	// Use this for initialization
	void Start () {
		singleton = this;
		mouse_over = gameObject;
		Debug.Log("GameWorld initialized!");
	}
	
	// Update is called once per frame
	void Update () {
	}
	
	static public void StartMouseOver (GameObject obj)
	{
		Debug.Log("SetMouseOver: "+obj.name);
	}
	
	static public void EndMouseOver (GameObject obj)
	{
		Debug.Log("EndMouseOver: "+obj.name);
	}
	
	static public GameObject MouseOver
	{
		get
		{
			return singleton.mouse_over;
		}
	}
}

I then attached this to a palm tree GameObject in the world.

Here’s the issues:

  • The JS script complains that GameWorld.StartMouseOver and EndMouseOver methods do not exist.

  • I added a call in the JS to “engine.MouseOver” and it reads that property just fine. (I have another component displaying the name of that property so I know it’s seeing the GameWorld class and interacting with it.

If anyone can see anything I’m doing wrong on why the script won’t see those two methods, that would be great!

Thanks for your time and help!

Edited: solved my first issue so edited this post to show what I’m currently having problems with

Edit: Figured this one out, too. I’ll leave it for other noobies like me, though.
1. I realized if I put the GameWorld class under a folder called Plugins, I can refer to it directly. Yay!
2. In the JS script I sent in ‘this’ which is not the GameObject but the Script component. I changed to StartMouseOver(gameObject) and it’s all good!

For the first issue, javascript and C# compile differently. One or the other works fine, but when mixing, you need to watch complication order. I don’t remember what the exact order was, but placing the C# script in Standard Assets should make it compile first and fix the problem.

As for the infernal gameObject.Find, I would consider either
A) putting the code in the object itself, of
B) if the code needs to be reused, make it a static function

A static function, or varible, is declared (in javascript, at least) like:

static function Blah ()
{
    Yada.yada();
}

They can be accessed from any script (excluding cross-language compilation issues) like any other function in Unity:

scriptName.Blah();

Static functions are particularly good for game logic that is independent of any object, as they do not need to be put onto an object to work. But keep in mind that they don’t mingle well with standard functions and variables. Since there can be many copies of the same script in the scene, all with different values, and only one static, it’s variables need to be static as well (good for global stuff like scores), passed to it like:

static function Blah (val : String)
{
    Debug.Log(val);
}
scriptName.Blah("hello function");

or found with the good ol’ gameObject.Find.

Also, I would stick with one language and save myself headaches. Furthermore, unless you already know or need C#, I would recommend javascript since most of the examples in the documentation use it and it requires less typing. Read: faster development, fewer mistakes. (IMO)

I hope I helped.

Edit: added line break

Thanks for your input, Omega. Good stuff!

Well, it seems some mixing is in order since I like JS for the quick stuff but if you want to do a bunch of game support classes you almost have to use C# as it looks like 1 file in JS = one class.

C# isn’t a problem, although I haven’t used it in five years. I’m a coder by trade so, it’s the GUI/art stuff that’ll confuse me :wink:

It looks like the problem was a mismatch in parameters but it was giving me a weird error on that. Once I moved the GameWorld object to the Plugins/ folder, I got a more sensible error that pointed to the mismatch.

Thanks for the headsup on the static JS function. I’ll have to see how that relates to C# (and the Plugins folder). I’m just doing the learn-by-trial-n-error right now.

Again, thanks!

I would recommend not mixing; it usually ends up being too annoying in the long run. There are a few things that you can do in C# but not in JS, and a few things you can do in JS but not C#, but 99% can be done in both. There’s no problem having classes in JS if you’d rather use that.

One good way of having functions easily accessible by other scripts (not limited to static functions):

// Assumes script is called Manager.js
static var use : Manager;

function Awake () {
   use = this;
}

function DoStuff () {
   // blah blah
}

Then in other scripts you can do:

Manager.use.DoStuff();

without having to do GameObject.Find() or other methods. You just have to be sure that Awake function is called before you attempt to call Manager functions in other scripts.

–Eric

I never really used C# since if I ever had the nerve to gasp rename one of my files, Unity would sit there and pout until I brought up my editor and fixed the class name to match. Painful.

I did some research, and found that, well, for starters, Unity’s “javascript” is actually Jscript .Net, so google accordingly, and found that it supports classes. I tried it and not a peep from Unity, which was surprising. (I taught myself using trial/error, and I still sometimes hold my breath when I hit save)
This code actually seems to work:

class ClassTestDummy
{
	var hello = "world";
}

I think we both learned something. Now all I have to do is figure out how this is useful…

Not really (it’s based off Unity’s Boo and there are differences), but it’s probably closer to that than web Javascript.

This is a very nice example.

–Eric