For my last university project I'm making a small 2D Unity game. There I want to create an air lock: two doors with at least two buttons/levers that can open them. Both doors start closed, using the first lever opens the first door but keeps the other one closed, using the next lever closes the door behind you, while opens the door in front of you.
The last time I coded something was in like 2018 or so, and I've never touched C# before. There is already two scripts in the game (see below; not made by me), but it is tied to two specific doors at the start of the level (hence the reference to "vacuum"). I want to make new scripts that is reusable, for as many instances as I like and need. The old script isn't reusable, and apparently rely on a "global" boolean, so if I would reuse it, it could open/close doors in other parts of the level, that I don't want.
So how would I code this problem, when I would start from scratch?
Lever.cs
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lever : MonoBehaviour
{
private static bool leverStatus = false;
private static bool canOpen = false;
private static GameObject[] leverDoors;
public AudioClip audioClip;
private AudioController audioController;
private GameObject vacuum;
private PlayerMovementController playerMovement;
private void Start()
{
audioControler = GameObject.Find("SFX_Controler").GetComponent<AudioController>();
leverDoors = GameObject.FindGameObjectsWithTag("Lever-Door");
vacuum = GameObject.FindGameObjectWithTag("Vacuum");
playerMovement = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerMovementController>();
}
private void Update()
{
checkDoors();
if( canOpen)
{
FindObjectOfType<UIHandler>().showUseInfo();
if (Input.GetAxisRaw("Interact") != 0)
{
changeStatus();
StartCoroutine(changeStatus());
}
}
}
private void checkDoors()
{
foreach(GameObject g in leverDoors)
{
if (g.GetComponent<LeverDoor>().neededLeverStatus == leverStatus)
{
g.SetActive(false);
}
else
{
g.SetActive(true);
}
}
}
IEnumerator changeStatus()
{
audioController.playSFX(audioClip);
playerMovement.interruptMovement(true);
canOpen = false;
yield return new WaitForSeconds(0.5f);
audioController.playSFX(vacuum.GetComponent<Vacuum>().audioClip);
yield return new WaitForSeconds(1.2f);
if (leverStatus)
{
leverStatus = false;
vacuum.transform.localScale = new Vector2(1, 1);
}
else
{
leverStatus = true;
vacuum.transform.localScale = new Vector2(2.5f, 1);
}
playerMovement.interruptMovement(false);
canOpen = true;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = false;
FindObjectOfType<UIHandler>().disableUseInfo();
}
}
}
LeverDoor.cs
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeverDoor : MonoBehaviour
{
[SerializeField]
public bool neededLeverStatus;
// Update is called once per frame
void Update ()
{
gameObject.SetActive(true);
}
}
For my last university project I'm making a small 2D Unity game. There I want to create an air lock: two doors with at least two buttons/levers that can open them. Both doors start closed, using the first lever opens the first door but keeps the other one closed, using the next lever closes the door behind you, while opens the door in front of you.
The last time I coded something was in like 2018 or so, and I've never touched C# before. There is already two scripts in the game (see below; not made by me), but it is tied to two specific doors at the start of the level (hence the reference to "vacuum"). I want to make new scripts that is reusable, for as many instances as I like and need. The old script isn't reusable, and apparently rely on a "global" boolean, so if I would reuse it, it could open/close doors in other parts of the level, that I don't want.
So how would I code this problem, when I would start from scratch?
Lever.cs
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lever : MonoBehaviour
{
private static bool leverStatus = false;
private static bool canOpen = false;
private static GameObject[] leverDoors;
public AudioClip audioClip;
private AudioController audioController;
private GameObject vacuum;
private PlayerMovementController playerMovement;
private void Start()
{
audioControler = GameObject.Find("SFX_Controler").GetComponent<AudioController>();
leverDoors = GameObject.FindGameObjectsWithTag("Lever-Door");
vacuum = GameObject.FindGameObjectWithTag("Vacuum");
playerMovement = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerMovementController>();
}
private void Update()
{
checkDoors();
if( canOpen)
{
FindObjectOfType<UIHandler>().showUseInfo();
if (Input.GetAxisRaw("Interact") != 0)
{
changeStatus();
StartCoroutine(changeStatus());
}
}
}
private void checkDoors()
{
foreach(GameObject g in leverDoors)
{
if (g.GetComponent<LeverDoor>().neededLeverStatus == leverStatus)
{
g.SetActive(false);
}
else
{
g.SetActive(true);
}
}
}
IEnumerator changeStatus()
{
audioController.playSFX(audioClip);
playerMovement.interruptMovement(true);
canOpen = false;
yield return new WaitForSeconds(0.5f);
audioController.playSFX(vacuum.GetComponent<Vacuum>().audioClip);
yield return new WaitForSeconds(1.2f);
if (leverStatus)
{
leverStatus = false;
vacuum.transform.localScale = new Vector2(1, 1);
}
else
{
leverStatus = true;
vacuum.transform.localScale = new Vector2(2.5f, 1);
}
playerMovement.interruptMovement(false);
canOpen = true;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = false;
FindObjectOfType<UIHandler>().disableUseInfo();
}
}
}
LeverDoor.cs
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeverDoor : MonoBehaviour
{
[SerializeField]
public bool neededLeverStatus;
// Update is called once per frame
void Update ()
{
gameObject.SetActive(true);
}
}
Share
Improve this question
edited Mar 15 at 19:31
marc_s
756k184 gold badges1.4k silver badges1.5k bronze badges
asked Mar 15 at 10:26
SaschaSascha
113 bronze badges
2
|
1 Answer
Reset to default 0Your script is completely usable, simply needs some tweaking! I have placed below a version of the script that works with the existing LeverDoor.cs
, with plenty of comments explaining the script. The issue with the previous script is that it looked for every single door in the level and changed it's status, instead of just being assigned to one door.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lever : MonoBehaviour
{
//[SerializeField] lets private variables be seen in the inspector
private bool leverStatus = false; // The status of the lever (opened of closed)
private bool canOpen = false; // If the lever can be opened
[SerializeField] private GameObject leverDoor; // The door that the lever opens
public AudioClip audioClip; // The sound of the lever
[SerializeField] private AudioController audioController; // Reference to the audio controller script
[SerializeField] private PlayerMovementController playerMovement; // Reference to the player movement script
private void Update()
{
checkDoor();
if(canOpen) // If the player can interact with the lever
{
FindObjectOfType<UIHandler>().showUseInfo(); // Show the use info on the screen
if (Input.GetAxisRaw("Interact") != 0) // If the player presses the interact button
{
StartCoroutine(changeStatus()); // Change the status of the lever
}
}
}
private void checkDoor() // Check if the door should be open or closed
{
if (g.GetComponent<LeverDoor>().neededLeverStatus == leverStatus)
{
g.SetActive(false);
}
else
{
g.SetActive(true);
}
}
// Change the status of the lever
IEnumerator changeStatus()
{
audioController.playSFX(audioClip); // Play the sound of the lever
playerMovement.interruptMovement(true); // Stop the player from moving
canOpen = false; // The player can't interact with the lever anymore
yield return new WaitForSeconds(0.5f); // Wait for the sound to finish playing
//audioController.playSFX(vacuum.GetComponent<Vacuum>().audioClip);
if (leverStatus) // If the lever is up, put it down
{
leverStatus = false;
// Add something that happens when the lever is down
}
else // If the lever is down, put it up
{
leverStatus = true;
// Add something that happens when the lever is up
}
playerMovement.interruptMovement(false); // Let the player move again
canOpen = true; // The player can interact with the lever again
}
// If the player enters the trigger area, the player can interact with the lever
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = true;
}
}
// If the player leaves the trigger area, the player can't interact with the lever anymore
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
canOpen = false;
FindObjectOfType<UIHandler>().disableUseInfo(); // Hide the use info on the screen
}
}
}
Best of luck =D
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744617977a4584167.html
and apparently rely on a "global" boolean, so if I would reuse it, it could open/close doors in other parts of the level, that I don't want.
.. it is usingstatic
that's your issue .. it makes this flag not belong to any instance but the entire type itself (in other words is shared between all instances) – derHugo Commented Mar 16 at 20:07