- Home /
Multiple Else Statments?
Hey, so I have a situation in which a person can open something with openable parts inside. Say for example an dishwasher with the dishracks inside. When a person opens the dishwasher door they can open up the racks at will. This all works fine in script, but Im having trouble figuring out how to close the dishwasher, as if the racks are open they just stay open even if the door is closed (and therefore poke through the door). This is the script I am attempting at, and its probably more complicated than need be;
#pragma strict
private var open : boolean;
var playOpen : AnimationClip;
var openSound : AudioClip;
var playClose : AnimationClip;
var closeSound : AudioClip;
var part1 : GameObject;
var part2 : GameObject;
function Start(){
open = false;
}
function OnMouseDown () {
if (open == false) {
animation.Play(playOpen.name);
audio.PlayOneShot(openSound);
open = true;
} else {
if (part1.GetComponent(Open_ClosePart1).open1 == true){
animation.Play(playClose.name);
audio.PlayOneShot(closeSound);
part1.GetComponent(Open_ClosePart1).open1 = false;
open = false;
}
else{
if (part2.GetComponent(Open_ClosePart2).open2 == true){
animation.Play(playClose.name);
audio.PlayOneShot(closeSound);
part2.GetComponent(Open_ClosePart2).open2 = false;
open = false;
}
else{
if (part1.GetComponent(Open_ClosePart1).open1 == true){
if (part2.GetComponent(Open_ClosePart2).open2 == true){
animation.Play(playClose.name);
audio.PlayOneShot(closeSound);
part1.GetComponent(Open_ClosePart1).open1 = false;
part2.GetComponent(Open_ClosePart2).open2 = false;
open = false;
}
}
}
}
}
}
This script is attached to the main door and is referencing two other scripts that look like this;
#pragma strict
var open1 : boolean = false;
var playOpen : AnimationClip;
var openSound : AudioClip;
var playClose : AnimationClip;
var closeSound : AudioClip;
function OnMouseDown () {
open1 = !open1;
if (open1) {
animation.Play(playOpen.name);
audio.PlayOneShot(openSound);
} else {
animation.Play(playClose.name);
audio.PlayOneShot(closeSound);
}
}
Except the 2nd version of this script has 'open2' instead of 'open1' everywhere. These scripts are attached one to the first rack and the second to the second rack. When I use the script the Main door opens correctly and the two racks move correctly. However when I press the main door to close, it shuts the second rack, and on a second click shuts the main door without shutting the first rack. Can someone please help me figure out what I'm doing wrong? I have never tried to do multiple 'else' statements like this and Im sure that's why it's all going wrong. Thanks in advance!
And this is all done with clicks, event if the click is not on the dishwasher or its parts?
You've certainly got too many elses :) And the indentation makes it hard to follow.
I think you are making it hard for yourself by doing these binary checks - how about we mod it a bit to make it more of a simple state model? It'll be easier to think about.
I can help with that, but first can you tell me what is supposed to happen when the dishwasher is clicked and both racks are open? Do they both shut, then the dishwasher? Does just one of them shut then the user clicks again?
Good idea, @whydoidoit. It seems like you would need an integer (to define what state the dishwasher is in) and a boolean (to define whether or not the dishwasher has been completely closed [0] or completely open [1] most recently).
That's where I was going - plus cleaning up some of those GetComponents
@You I would use an enum ins$$anonymous$$d of an integer to describe the state. Less magic numbers, easier to read, extend and debug :)
Answer by whydoidoit · May 28, 2012 at 02:24 PM
Ok so I've modified your code a bit to make a basic state machine and remove some of those complexities. You now have an array of parts (which you can drop your two parts into). And only a single script to attach to both parts.
Just a thought:
If you start writing routines with lots of elses in them think:
Can I write a list of states down.
Can I write a function to work out step by step what state I'm in - OR can I dictate each state.
Write your code as separate functions and keep the control logic simple. That way you've just got a couple of routines to debug, no syntax and indentation getting in the way.
Note
Also I should point out that while I used some fancy LINQ in here:
parts.Any(function(part){return part.open;})
That could have been achieved that with a normal for next loop - but the LINQ is just elegant and in a single line, it takes getting your head around but when you do it really simplifies the logic because the code is neater and expressive. I want to know is Any part open etc. There's lot's more to LINQ, but that's a nice first usage of it.
Using this code
ou will need to attach the script to the parts and drag the game objects onto the members of the array.
Here is the main script:
OpenClose_Main.js
#pragma strict
import System.Collections.Generic;
import System.Linq;
var open : boolean;
var playOpen : AnimationClip;
var openSound : AudioClip;
var playClose : AnimationClip;
var closeSound : AudioClip;
var parts : Open_ClosePart[];
//Status for the dishwasher
enum status {
closed,
open,
drawsOpen,
animating
}
//Work out the current status
function GetStatus() : status {
//If anything is animating then return status.animating
if(animation.isPlaying ||
parts.Any(function(part) { return part.animation.isPlaying;}))
{
return status.animating;
}
//If any draws are open then return drawsOpen
if(parts.Any(function(part) {return part.open;})) {
return status.drawsOpen;
}
//Else return the state of the dishwasher
return open ? status.open : status.closed;
}
function Start(){
open = false;
for(var part in parts) {
part.door = this;
}
}
//Coroutine to close everything
function Close() : IEnumerator {
for(var part in parts) {
//Tell the part to close, it just
//returns immediately if it is
//otherwise animates
part.Close();
yield WaitForEndOfFrame();
//Wait for it to be closed and finished
while(part.open || part.animation.isPlaying)
yield WaitForEndOfFrame();
}
//Close the dishwasher
animation.Play(playClose.name);
yield WaitForEndOfFrame();
//Wait for it to be closed
while(animation.isPlaying)
yield WaitForEndOfFrame();
//It's closed now
open = false;
}
function OnMouseDown () {
//Check the status and react accordingly
//NOTE: we don't do anything if it is
//animating
switch(GetStatus())
{
case status.closed:
animation.Play(playOpen.name);
audio.PlayOneShot(openSound);
open = true;
break;
case status.open:
case status.drawsOpen:
StartCoroutine(Close());
break;
}
}
And this is the parts script which must be called Open_ClosePart.js (to match the array definition above)
OpenClose_Part.js
#pragma strict
var open : boolean = false;
var playOpen : AnimationClip;
var openSound : AudioClip;
var playClose : AnimationClip;
var closeSound : AudioClip;
var door : Open_CloseMain;
function OnMouseDown()
{
if(!door.open)
return;
if(open)
Close();
else
Open();
}
function Close() {
if(!open)
return;
animation.Play(playClose.name);
audio.PlayOneShot(closeSound);
open = false;
}
function Open() {
if(open)
return;
animation.Play(playOpen.name);
audio.PlayOneShot(openSound);
open = true;
}
Setting the parts:
What I've tried to do is break it into multiple simple bits (because I'm a simple guy!) Then all you have to do is think about that bit. Like "What is the status of the dishwasher?" look at the GetStatus() code, not mix it up with everything else.
It may of course not work yet - I don't have a dishwasher and any racks to try it out on!
Okay So I overwrote the original one I had with your first script, then made a new script called Open_ClosePart.js. Put the first script on the main diswasher door, and the second script on the two parts. I then added all the animations and sounds, then put the two parts into the array of the main script. I can open the main door, open the racks inside, but when I go to close the door it closes on the racks still? The compiler isn't throwing any errors. Did I miss something? Thank you so much for you help by the way, I never expected someone to put so much time into helping me!
No problem - you want to get this stuff right in your head when you are building code, learn it once and it'll help you out for a long time.
Now that said from my soapbox - I probably ought to help you make it work :)
Do the racks close, just afterwards? If not does closing a single rack work?
The 3 objects seem to be working completely independantly, when the racks are open and the door closes, nothing happens beyond the door closing. They function as if every object is opening and closing irregardless of what the state of the other objects are?
Answer by Eric5h5 · May 27, 2012 at 10:34 PM
Use this:
if () {
}
else if () {
}
else {
}
Not this:
if () {
}
else {
}
else {
}
There can be only one ... else, that is. One else for each if. You can nest more if/else stuff inside an else though.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Open door on input key 1 Answer