public void removeActivePiece()
    {
        GameObject           activePiece       = raycastingScript.activePiece;
        PiecePrefabBehaviour activePieceScript = activePiece.GetComponent <PiecePrefabBehaviour>();

        // mark the snap-to target GameObject that the piece is currrently occupying, if there is one, as unoccupied
        GameObject target = activePieceScript.currOccupiedSnapToTarget;

        if (target != null)
        {
            target.GetComponent <SnapToTargetBehaviour>().occupied = false;
        }

        // remove activePiece's colliders from the collidersInContact lists of any other GameObjects in contact with activePiece
        foreach (Collider colliderInContact in activePieceScript.collidersInContact) // for each collider in contact with activePiece
        {
            Transform parent = colliderInContact.gameObject.transform.parent;
            if (parent == null || parent.gameObject.name != "Workspace Boundaries")                                                               // presumably, therefore, the collider in question belongs to a machine piece that's in contact with activePiece
            {
                PiecePrefabBehaviour pieceInContactScript = getCompletePiece(colliderInContact.gameObject).GetComponent <PiecePrefabBehaviour>(); // get that collider's piece and its script
                int lastIndex = pieceInContactScript.collidersInContact.Count - 1;
                for (int i = lastIndex; i >= 0; i--)                                                                                              // for each collider in contact with the piece in question
                {
                    Collider colliderInContactWithOtherPiece = pieceInContactScript.collidersInContact[i];
                    if (isDescendent(colliderInContactWithOtherPiece.gameObject.transform, activePiece.transform)) // if the collider belongs to activePiece
                    // remove the collider from the collidersInContact list of the piece in question
                    {
                        pieceInContactScript.collidersInContact.RemoveAt(i);
                    }
                }
            }
        }

        // finally, actually take care of removing the piece
        if (resetButtonScript.getResettable())
        {
            raycastingScript.piecesRemovedWhileResettable.Add(activePiece);
            activePiece.SetActive(false);
        }
        else
        {
            Destroy(activePiece);
        }
        raycastingScript.pieces.Remove(activePiece); // needs to be before the call to clearActivePiece
        raycastingScript.ClearActivePiece();
    }
    public void OnConfirmClearButtonPress()
    {
        foreach (GameObject piece in raycastingScript.pieces)
        {
            Destroy(piece);
        }
        foreach (GameObject piece in raycastingScript.piecesRemovedWhileResettable)
        {
            Destroy(piece); // since they were merely set to be inactive, not actually destroyed, before
        }
        raycastingScript.pieces.Clear();
        raycastingScript.piecesRemovedWhileResettable.Clear();
        resetButtonScript.setResettable(false);

        // put this after the list is cleared so it knows to undisplay the piece controls panel, etc.
        // also put it after resettable is set to false so it knows to redisplay the scroll view, etc.
        raycastingScript.ClearActivePiece();

        // undisplay the dialog and resume raycasting detection
        raycastingScript.clearDialogShowing = false;
        clearDialogPanel.SetActive(false);
    }
    public void OnStartStopPress()
    {
        physicsOn = !physicsOn;

        foreach (GameObject piece in raycastingScript.pieces)
        {
            PiecePrefabBehaviour pieceScript = piece.GetComponent <PiecePrefabBehaviour>();
            if (physicsOn && !raycastingScript.resetButtonScript.getResettable())
            {
                // If physics is on, save positions, if positions haven't already been saved since the last reset (or since the Contraption Designer loaded, if there hasn't been a reset yet)
                // i.e. this code runs when the user pressed a button that said, "start"
                pieceScript.saveTransforms();
            }
            else if (physicsOn)
            {
                // Here, physics is being turned on and has already been turned on before since the last reset, so resume those velocities
                // i.e. this code runs when the user pressed a button that said, "resume"
                pieceScript.resumeVelocities();
            }
            else
            {
                // Here, physics is being turned off, so save the velocities in case the user wants to resume subsequently
                // i.e. this code runs when the user pressed a button that said, "pause"
                pieceScript.saveVelocities();
            }
        }

        raycastingScript.resetButtonScript.setResettable(true);

        if (physicsOn)
        {
            raycastingScript.ClearActivePiece(); // probably not necessary since pressing the button should clear active piece anyway, but might as well play it safe
            setButtonState("pause");             // change the text and color of the button
        }
        else
        {
            setButtonState("resume"); // change the text and color of the button
        }

        // disable piece control buttons (even when turning physics off, since we still don't have an active piece yet at that point. But it's all irrelevant anyway if we don't allow paused-machine editing)
        raycastingScript.SetAllPieceControlsButtonsInteractable(false);

        // toggle the visibility of elements that are only visible when physics is off
        clearAllObject.SetActive(!physicsOn);

        // turn off visibility of pieces scroll view and piece controls panel, since we don't want to allow user to add or edit pieces before resetting
        piecesScrollView.SetActive(false);
        pieceControlsPanel.SetActive(false);

        // toggle isKinematic and isTrigger for all pieces
        foreach (GameObject piece in raycastingScript.pieces)
        {
            PiecePrefabBehaviour pieceScript = piece.GetComponent <PiecePrefabBehaviour>();
            pieceScript.setKinematic(!physicsOn);
            pieceScript.setTriggers(!physicsOn); // needs to be after the ClearActivePiece call
        }

        // toggle isTrigger for all workspace boundary colliders
        foreach (Transform bound_trans in workspaceBoundariesObject.transform)
        {
            GameObject boundary = bound_trans.gameObject;
            boundary.GetComponent <Collider>().isTrigger = !physicsOn;
        }
    }