1
\$\begingroup\$

How do I check which object was activated before the other? Let's say that there's door to open. To open the door you need to press firstly the second button and then the first button...but not the other way around.

I have these scripts for now:

Switch script (it's on 2 objects that are switches and both objects have colliders with IsTrigger checked):

public var IsPressed : boolean = false;
public var triggered : boolean = false;

function OnTriggerEnter() { triggered= true; }
function OnTriggerExit()  { triggered= false;}

function Update()
{
    if (triggered && Input.GetKeyDown(KeyCode.JoystickButton1))
        IsPressed = true;     
}

SwitchCheck script (it's on door that should be opened)

public var Switch1 : Switch;
public var Switch2 : Switch;

function Update()
{
    if (Switch1.IsPressed && Switch2.IsPressed)
    {
        Destroy (gameObject);
    }
}

EDIT: Let me explain this in detail. If Button1/ Switch1 is pressed, door opens to World1.(no Button2 needs to be pressed.) If Button2 and then Button1 is pressed, door opens to the World2.

\$\endgroup\$
  • \$\begingroup\$ Are you meant to be able to turn on Switch 2 if Switch 1 is not activated (as in Switch 2 is disabled completely until you activate Switch 1?) \$\endgroup\$ – Tom 'Blue' Piddock Jul 31 '14 at 10:21
2
\$\begingroup\$

To add a puzzle like quality to this you need to generate some sort of dependency on the switch values (the door shouldn't really know about this, the switches should notify the door it can open.) I would use a parent object much like indeed005 is suggesting but with some important changes:

//List references
import System.Collections.Generic; //Always a nice idea
import System.Linq;

//Unity3D
import UnityEngine;

public class Switch : MonoBehaviour 
{
    public var IsPressed : boolean = false;
    public var Door : Door = null;    
    public var DependantSwitches : List<Switch>;

    private var triggered : boolean = false;

    function OnTriggerEnter() { triggered= true; }
    function OnTriggerExit()  { triggered= false;}

    function Update()
    {
        if (
            triggered &&
            Input.GetKeyDown(KeyCode.JoystickButton1) &&
            DependantSwitches.All(function(o){ return o.IsPressed;})
           )
        {
            IsPressed = true;
        }

        if(IsPressed && Door != null)
        {
            Door.Open();
        }
    }
}

And the door class needs:

public class Doorextends MonoBehaviour
{    
    function Open()
    {
        // Open your door
    }
}

This allows you to make a series of switches with any degree of dependance:

If you wanted you could make a series of switches in a linear formation:

SwitchA -> SwitchB -> SwitchC -> Door

Or even do a branched series of switches:

      SwitchA
       /   \
SwitchB     SwitchC
   |         /
SwitchD     /
       \   /
      SwitchE
         |
        Door

Amending for Question Edit:

static var switchesList : List<Switch> = new List<Switch>();

public var switchNumber : int;

function Awake(){
    switchesList.Add(this);
}

function Update()
{
    if (
        triggered &&
        Input.GetKeyDown(KeyCode.JoystickButton1) &&
        DependantSwitches.All(function(o){ return o.IsPressed;})
       )
    {
        IsPressed = true;

        // Put to start of list.
        list.Remove(this);
        list.Insert(0, this);
    }

    if(IsPressed && Door != null)
    {
        Door.Open(switchesList);
    }

Door changes:

 function Open(switches : List.<Switch>)
 {
     // Check order of switches and open correct door/portal
     if( switches[0].switchNumber == 1  && switches[0].switchNumber == 2)
     {
          OpenPortalOne();
     } else if (switches[0].switchNumber == 2  && switches[0].switchNumber == 1)
     {
          OpenPortalTwo();
     } 
 }
\$\endgroup\$
0
\$\begingroup\$

There are a number of ways. This is a really open ended problem, you can solve it however you want. Three options off the top of my head...

  1. Store the game tick or timestamp that each switch was pressed on, and then compare ticks/timestamps to ensure Switch1 was pressed first.
  2. Have Switch2 trigger an event on the door if it is pressed while Switch1 is down. That way Switch2 opens the door, instead of the door checking to see if it can open, a
  3. Only set Switch2's IsPressed flag if Switch1 is already pressed, that way Switch1.IsPressed and Switch2.IsPressed can only both be true if they were pressed in the same order.

Option 1 requires adding some new information to the Switch class (a timestamp) whereas options 2 and 3 just require you to slightly reorganize the way your door is scripted. I personally would choose option 2 or 3.

\$\endgroup\$
  • \$\begingroup\$ Let me explain this in detail. If Button1/ Switch1 is pressed, door opens to World1.(no Button2 needs to be pressed.) If Button2 and then Button1 is pressed, door opens to the World2. \$\endgroup\$ – Samurai Fox Jul 31 '14 at 10:49
0
\$\begingroup\$

How I'd do it would be the following:

(Sorry for the lack of code, on my lunch break!)

First:

Create a new class.

A door controller, or something similar, give it a number of different (probably non-returning) update functions that correspond to the switches.

Give it variables to record the state of the object at the current time.

Each update function may cause a change in the state of the object, but only if the current state allows it.

When it enters a specific state, open the door.

Instance it.

Second:

Each instance of the switch class is passed a function when it is created, corresponding to the in-level object it represents.

This function is called when the switch is triggered.

State Machine

This is an example of a state machine, and they are quite a useful pattern for modelling this kind of behavior.

\$\endgroup\$
0
\$\begingroup\$

Think about this: Should the second switch even be able to be flipped if the first switch is not already ON? If so, it may lead to some strange logic.

Assume door checks if switch1 was activated before switch 2

  1. Player flips switch 2 to ON
  2. Door does not open
  3. Player flips switch 1 to ON
  4. Door does not open
  5. Player flips switch 2 to OFF
  6. Door does not open
  7. Player flips switch 2 back to ON
  8. Door opens!
  9. Door opens every time player sets switch2 to ON as long as they have turned on switch 1 once.

    *EDIT: This could cause the player confusion if they forget which order and when they turned the switches on/off. But if that is part of the puzzle, you'll have to set a timestamp for each switch and compare these

My advice is:

Add something like

public var ParentSwitch : Switch;

and

if (triggered && Input.GetKeyDown(KeyCode.JoystickButton1))
{
    if (ParentSwitch != null) 
    {
        if (ParentSwitch.IsPressed) IsPressed = !IsPressed;
    }
    else
    {
        IsPressed = !IsPressed;   
    }
}

to the switch script. That way the player can't flip the dependant switch until they flip the parent. This also means that if you decide to re-use the switch script later, you can just leave the reference empty if you don't want special logic.

\$\endgroup\$
  • \$\begingroup\$ I would amend this logic as this means the user cannot disable the child switch after the fact. Use an inverter instead of making it equal to it's parent value : IsPressed = !IsPressed; \$\endgroup\$ – Tom 'Blue' Piddock Jul 31 '14 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.