2
\$\begingroup\$

I'm trying to design a wiring system that allows players to connect power sources to switches via wires. Think redstone in Minecraft. When a wire is placed, if it is not initially connected to the power source, it has no power (behaving as expected). The PROBLEM occurs when the wire is connected to power, detecting that it is powered, and then disconnects from power. After it has touched the power source, it then becomes it's own source if disconnected, which is not what it should be doing.

This is what SHOULD be happening enter image description here

Here's what is ACTUALLY happeningenter image description here

And here is my code:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class Wire_Moveable : MonoBehaviour {

 public static Wire_Moveable control;

 public bool IsBlue;
 public bool IsRed;
 public bool powered;

 void Start () {
     IsBlue = false;
     IsRed = false;
 }

 void Update () {
 if (Input.GetMouseButtonUp (0)) {
         following = false;
         this.gameObject.GetComponent<Wire_Moveable>().SnapWire ();
     }
 }

 void OnTriggerStay2D (Collider2D trigger) {
     if (trigger.tag == "wire") {
         if (trigger.gameObject.GetComponent<Wire_Moveable>().powered) {
             powered = true;
         }

         if (trigger.gameObject.GetComponent<Wire_Moveable> ().IsBlue) {
             IsBlue = true;
             IsRed = false;
         } else if (trigger.gameObject.GetComponent<Wire_Moveable> ().IsRed){
             IsBlue = false;
             IsRed = true;
         }
     }
 }

 void OnTriggerExit2D (Collider2D trigger) {
     if (trigger.tag == "startnode_blue") {
         IsBlue = false;
         powered = false;
     }

     if (trigger.tag == "wire") {
         if (trigger.gameObject.GetComponent<wire_Moveable>().powered) {
             powered = false;
         }
     }
 }

 void SnapWire () {
     if (this.gameObject.name == "Wire_Basic" || this.gameObject.name == "Wire_Basic(Clone)") {
         StartCoroutine ("ActivatePower", 0);
     }
 }

 IEnumerator ActivatePower () {
     yield return new WaitForSeconds (0.1f);
     if (powered) {
         PowerBeam.SetActive (true);
     } else if (!powered) {
         PowerBeam.SetActive (false);
     }
 }
\$\endgroup\$
2
\$\begingroup\$

You can solve this one of two ways, either try to path to a source of power, or the tiles need to keep track of who its source neighbor is.

Pathing can get expensive as your wires become complex, so I'd suggest the second approach.

Basically you need to keep track of where the tile got power from, and check regularly to see if a neighbor has power when the tile doesn't.

I'm going to pseudocode this a bit, because i don't usually use colliders for this when I'm working in 2d, and event handling complicates the solution for future readers.

public class WireSegment : MonoBehaviour {

    public bool powered=false;//whether or not we are powered
    public WireSegment source;

    //called when first created
    void Start () {
        checkNeighborsForPower();
    }

    //called each frame
    void Update () {
        if(powered && !source.powered){
            //then our source is unpowered, and we need to turn off
            source=null;
            powered=false;
        }
        if(!powered){ 
            //We lost our source, so see if we can find a new one.
            checkNeighborsForPower();
        }
    }

    private void checkNeighborsForPower() {
       //we'll require adjacency to get power
       WireSegment left= findMyNeighbor(transform.position+Vector2.LEFT);
       WireSegment right= findMyNeighbor(transform.position+Vector2.RIGHT);
       WireSegment top= findMyNeighbor(transform.position+Vector2.UP);
       WireSegment bottom= findMyNeighbor(transform.position+Vector2.DOWN);

       if(top.powered && top.source!=this){
           source=top;
           powered=true;
       }else if(right.powered && right.source!=this){
           source=right;
           powered=true;
       }else if(bottom.powered && bottom.source!=this){
           source=bottom;
           powered=true;
       }else if(left.powered && left.source!=this){
           source=left;
           powered=true;
       }
    }

    private WireSegment findMyNeighbor(Vector2 neighborLocation){
        //Do a lookup from wherever we are storing our collection of WireSegments
    }

}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I don't know why it never occurred to me to check if each tile is the source, and to actually flag the source in the code. I have not tried the above suggestion yet, but I plan on doing so today, and I'll let you know what happens. \$\endgroup\$ – Trey Van Zandt Apr 19 '18 at 18:53

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.