简体   繁体   中英

How to create an efficient objects activation and deactivation system to progress the game?

I am currently working on a personal project which is an action adventure puzzle game. Basically, there are levels with puzzles involved to challenge the player.

Assume that Level 1 has two stages of puzzles: (Stage 1) Puzzle A, B and C with Clue A, B and C provided. (Stage 2) Puzzle D, E and F with Clue D, E and F provided.

If the respective puzzle is completed, the respective clue will be deactivated, such as Puzzle A has completed, Clue A will be deactivated. Vice versa.

If all Stage 1 puzzles has completed, all Stage 1 puzzles will be deactivated and all Stage 2 puzzles will be activated.

I have tried by hard-coding them. If using array class is a must, is there any way to reduce the redundancy? If not using array class, is there a better way to code?

public class Item
{
    public GameObject[] puzzle;
    public GameObject[] clue;
    public GameObject[] prop;

    public GameObject[] puzzleStartNode;
    public GameObject[] puzzleEndNode;
    public GameObject[] clueNode;
    public GameObject[] propNode;
}

public Item[] Stages;

// Start is called before the first frame update
public void ObjectActivation(string stageActivation)
{
    //stageOne
    if (stageActivation == "StageOne")
    {
        for (int i = 0; i < Stages[1].clue.Length; i++)
        {
            Stages[1].clue[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].puzzle.Length; i++)
        {
            Stages[1].puzzle[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].prop.Length; i++)
        {
            Stages[1].prop[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].puzzleStartNode.Length; i++)
        {
            Stages[1].puzzleStartNode[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].puzzleEndNode.Length; i++)
        {
            Stages[1].puzzleEndNode[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].clueNode.Length; i++)
        {
            Stages[1].clueNode[i].GetComponent<BoxCollider>().enabled = false;
        }

        for (int i = 0; i < Stages[1].propNode.Length; i++)
        {
            Stages[1].propNode[i].GetComponent<BoxCollider>().enabled = false;
        }
    }

    //stageTwo
    if (stageActivation == "StageTwo")
    {
        for (int i = 0; i < Stages[1].clue.Length; i++)
        {
            Stages[1].clue[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].puzzle.Length; i++)
        {
            Stages[1].puzzle[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].prop.Length; i++)
        {
            Stages[1].prop[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].puzzleStartNode.Length; i++)
        {
            Stages[1].puzzleStartNode[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].puzzleEndNode.Length; i++)
        {
            Stages[1].puzzleEndNode[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].clueNode.Length; i++)
        {
            Stages[1].clueNode[i].GetComponent<BoxCollider>().enabled = true;
        }

        for (int i = 0; i < Stages[1].propNode.Length; i++)
        {
            Stages[1].propNode[i].GetComponent<BoxCollider>().enabled = true;
        }
    }
}

What I meant with "teach the item class what it means to activate" was the following. In your Item class add the method SetActive(bool) and let it handle activation/deactivation.

//I'd call it Stage, or the stages field below items for consistency
//but I took your names :D
public class Item
{
    //It's kinda better to store the right thing right away
    //unless ofc you need the GameObject reference for something you didnt mention
    public BoxCollider[] puzzles; 
    public BoxCollider[] clues;
    // ... and so on

    public void SetActive(bool activate) {
        foreach(var puzzle in puzzles) {
            puzzle.enabled = activate;
        }
        foreach(var clue in clues) {
            clue.enabled = activate;
        }
        // ... same for the other stuff
        // Basically, everything that has to do with activation/deactivation
        // of the stage goes in here
    }
}

When you want to activate/deactivate the stage you can now simply do

public Item[] stages;

public void ObjectActivation(string stageActivation) //I'd use an int tho, see below
{
    //stageOne
    if (stageActivation == "StageOne") {
        stages[0].SetActive(true);
        stages[1].SetActive(false);
    }
    // ...
}

To expand on the comment that I would use int and not string as argument, you could do the following with it

public Item[] stages;

//Arrays are zero indexed, so "StageOne" would actually be id 0
public void ActivateOneStageAndDeactivateTheRest(int stageId) {
    for(int i = 0; i < stages.Length; i++) {
        stages[i].SetActive(i == stageId);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM