Javascripting a pair of doors opening

I have been working with the Unity Game Development Essentials book for a project at work that involves an interactive walkthrough of a building. There is a set of double doors that should open when approached, and I have used the script in the book as a basis, but when I run the game, the doors fail to open but the script shows no errors. Any advice or direction would be greatly appreciated.

Code as follows:

private var doorIsOpen : boolean = false;
private var doorTimer : float = 0.0;
private var currentDoor : GameObject;

var doorOpenTime : float = 3.0;
var doorOpenSound : AudioClip;
var doorShutSound : AudioClip;

function OpenDoor (){
audio.PlayOneShot(doorOpenSound);
doorIsOpen = true;
var Arena : GameObject = GameObject.Find (“BCSArena”);
Arena.animation.Play (“DoorsOpen”);
}

function Update () {

var hit : RaycastHit;
if (Physics.Raycast (transform.position, transform.forward, hit, 5)){
if (hit.collider.gameObject.tag == “MDoorA” “MDoorB” doorIsOpen == false){
currentDoor = hit.collider.gameObject;
Door (doorOpenSound, true, “DoorsOpen”, currentDoor);
}
}
if (doorIsOpen){
doorTimer += Time.deltaTime;

if (doorTimer > 3){
shutDoor();
doorTimer = 0.0;
}
}

}

function shutDoor (){
audio.PlayOneShot (doorShutSound);
doorIsOpen = false;

var Arena : GameObject = GameObject.Find (“BCSArena”);
Arena.animation.Play (“DoorsClose”);
}

function Door (aClip : AudioClip, openCheck : boolean, animName : String, thisDoor : GameObject){
audio.PlayOneShot (aClip);
doorIsOpen = openCheck;

thisDoor.transform.parent.animation.Play (animName);
}

@script RequireComponent (AudioSource)

Some advice:

  1. post your code using [ code][ /code] tags, makes reading it much easier

  2. Litter your code with Debug.Log statements, validate that all your variables are what you expect them to be, and all your functions are being called.

I would suggest using a sphere collider (or a box collider, whatever) instead of raycast. Make the collider big enough so it’s triggered when your character is approaching the door. use OnTriggerEnter() to open the door and OnTriggerExit() to close it. There will be a few technical details, but it may be more predictable than the raycast thing. I haven’t used raycasts much and not as triggers at all. I think colliders are more common for this sort of thing.

@FizixMan is right. It would be easier to read the format code. Anyway, you need to change a few statements in your code. First of all,

Your condition statement is incorrect:

if (hit.collider.gameObject.tag == "MDoorA"  "MDoorB"  doorIsOpen == false)

Secondly, Raycasting most likely can hit one game object at time. Therefore; you cannot use the AND () conditional statement, but use OR (||) conditional statement instead for the MDoorA or MDoorB.

You new conditional statement should look like this:

if ((hit.collider.gameObject.tag == "MDoorA" || hit.collider.gameObject.tag == "MDoorB")  doorIsOpen == false)

You can also call the function Door to shut the door as the following:

Door(doorShutSound, false, "doorshut", currentDoor);

Well, use ray casting is fine in this case so that you will not bum into another game object, such as a box collider.

Thanks for the info. As a side note, does it matter if the door is a group object or a single mesh?

Okay, I made the changes to the script, but the new issue is that it can’t find the animation attached to the model.
When I go to test the game I get this error-

I have the door nested in the model as follows-

BCSArena (main group)

->Arena (sub-group)

–>MDoorA (part of Arena group)

Here is the adjusted Code:

private var doorIsOpen : boolean = false;
private var doorTimer : float = 0.0;
private var currentDoor : GameObject;

var doorOpenTime : float = 3.0;
var doorOpenSound : AudioClip;
var doorShutSound : AudioClip;

function Update () {

var hit : RaycastHit;

	if (Physics.Raycast (transform.position, transform.forward, hit, 5)) {
		if (hit.collider.gameObject.tag == "MDoorA"  doorIsOpen == false){
			currentDoor = hit.collider.gameObject;
			Door(doorOpenSound, true, "doorOpen", currentDoor);
		}
	}
	if(doorIsOpen){
		doorTimer += Time.deltaTime;
		
		if (doorTimer > 3){
			Door (doorShutSound, false, "doorShut", currentDoor);
			doorTimer = 0.0;
			}
		}	
	}
function OpenDoor (){
	audio.PlayOneShot (doorOpenSound);
	doorOpen = true;
	var myArena : GameObject = GameObject.Find ("BCSArena");
	myArena.animation.Play ("doorOpen");
}
	
function shutDoor (){
	audio.PlayOneShot (doorShutSound);
	doorIsOpen = false;
	
	var myArena : GameObject = GameObject.Find ("BCSArena");
	myArena.animation.Play ("doorShut");
}	

function Door(aClip : AudioClip, openCheck : boolean, animName : String, thisDoor : GameObject){
	audio.PlayOneShot(aClip);
	doorIsOpen = openCheck;
	thisDoor.transform.parent.animation.Play(animName);
}

@script RequireComponent(AudioSource)

Is it better to have each model imported separately or as part of a group? Does it make for easier coding?

The animation is on the door itself, right? You need to call the animation on the object that contains it. You can put an animation on the parent object and have that animation move one of its children, but for now…

Try changing this:

	var myArena : GameObject = GameObject.Find ("BCSArena");
	myArena.animation.Play ("doorOpen");

to this:

	var myArena : GameObject = GameObject.Find ("MDoorA");
	myArena.animation.Play ("doorOpen");

The door is part of the Arena group and the animation is attached to the Arena group. The model has been imported into Unity as an .fbx object. The model and animation was assembled in Maya 2011.

I have altered the code but I still get the same message saying that there is no animation attached to the ‘Arena’ game object.

Hmmm…

I have always added a script to the object with the animations and gotten the animations to play by accessing the script, not the animations directly… You may need to create a script and access that script to get the animations to play.

You can also try something to treat the animations as a Component (which I think they are) like this:

Change (my suggestion) of this:

	var myArena : GameObject = GameObject.Find ("MDoorA");
	myArena.animation.Play ("doorOpen");

to this:

	var myArena : GameObject = GameObject.Find ("MDoorA");
        var animationComponent = myArena.GetComponent(animations);
	animationComponent.Play ("doorOpen");

Something like that. I’m just not sure if Animations can be accessed directly. I always made a script for them.

I went back into Maya and adjusted the hierarchy of the model and the door is opening properly now. Thanks for your help