Making an Air Lock (Multiple doors, multiple levers, reusable, Unity, C#) - Stack Overflow

For my last university project I'm making a small 2D Unity game. There I want to create an air loc

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
  • 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 using static 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
  • Yes, I think that has to do with the fact, that when the game starts you start in zero gravity ans when you use the second lever, gravity is restored so it relies on that boolean for that matter. So, I want to leave the code above as it is, and make a new one for other airlocks. But I keep the static in mind. – Sascha Commented Mar 17 at 9:43
Add a comment  | 

1 Answer 1

Reset to default 0

Your 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

相关推荐

  • dll文件丢失怎么办?一文让你3分钟解决这个问题

    电脑用着用着&#xff0c;突出提示&#xff1a;安装程序缺少DLL文件&#xff01; 这通常意味着你的电脑遇到了运行障碍。DLL文件是程序正常工作不可或缺的组件&#xff0c;一旦缺失&#xf

    1小时前
    00
  • 多语言编写的图片爬虫教程

    可能他们需要几个不同编程语言的示例,比如Python、JavaScript(Node.js)、Ruby之类的。然后我要考虑每个语言常用的库和框架,确保示例简单易懂,适合不同水平的开发者。接下来,我需要分步骤来思考每个语言的实现方式。比如Py

    1小时前
    00
  • 如何用基本临床数据预测癌症免疫检查点抑制剂疗法的疗效

    年04月10日 09:00 中国香港Basic Information 英文标题:Prediction of checkpoint inhibitor immunotherapy efficacy for cancer using rout

    1小时前
    00
  • 从C盘到D盘,应用迁移用这招太简单了

    正用电脑用得爽的时候&#xff0c;啪一个C盘驱动器已满的提示就糊到了脸上。 Windows中常见的问题&#xff0c;很多小白同学初次尝试&#xff0c;一不小心就给软件装C盘了&#xff0c;要是普通的一

    1小时前
    00
  • Flutter实现不依赖Firebase的多平台的Google登录

    GoogleConsole配置官网:点击创建OAuth2.0客户端,选择对应的应用类型。推荐的应用类型如下,多个应用类型可以共用一个client_id,也可以考虑创建多个client_id。平台应用类型AndroidWebiOSiOSMac

    1小时前
    00
  • AI新手村:Huggingface

    HuggingFaceHugging Face 最早作为 NLP 模型的社区中心,成立于 2016 年,但随着 LLM 的大火,主流的 LLM 模型的预训练模型和相关工具都可以在这个平台上找到,此外,上面也有很多计算机视觉(Computer

    1小时前
    00
  • 圈子系统源码:如何解决VUE页面刷新数据丢失问题

    <在Vue项目中,使用Vuex进行状态管理时,页面刷新导致数据丢失是一个常见的问题。这是因为Vuex的状态是存储在内存中的,而当页面刷新时,浏览器会重新加载页面,导致Vuex中的状态被重置。为了解决这个问题,我们可以采用以下几种方法:

    1小时前
    00
  • “破解”GPT

    最近 GPT-4o 生图模型横空出世,效果和玩法上都有突破性的进展,笔者整理了一下目前相关的技术,抛砖引玉一下,希望有更多大神分享讨论。图源小红书@恶魔幼崽,本文使用已获原作者授权。关注腾讯云开发者,一手技术干货提前解锁

    1小时前
    00
  • AI敏捷协作精研班来袭!解锁AI时代敏捷研发新姿势

    AI浪潮汹涌而至,全球产业格局正在被重塑。你是否还在为技术与业务的融合而头疼?是否还在为研发效率的瓶颈而焦虑?腾讯TAPD AI敏捷协作精研班重磅来袭,为你带来一场关于敏捷研发与AI融合的头脑风暴! 为什么你需要这场精研班?1. 打破业务与

    57分钟前
    10
  • 【嵌入式】嵌入式系统可以用哪些编程语言实现(系统全面讲解)

    嵌入式系统可以用哪些编程语言实现(系统全面讲解)这是一个条形图,展示了嵌入式开发中不同编程语言的使用频率和适用度评分:C语言 得分最高,达到 95,是嵌入式系统开发的主力语言。C++ 和 汇编 紧随其后,得分分别为 80 和 70,说明在需

    51分钟前
    00
  • 算法训练之动态规划(二)

    不同路径不同路径这个题目需要讨论的是由左上角到右下角的路径总数~我们可以按照动态规划的步骤来进行一步步分析~1、状态表示 结合这里的题目要求+经验:我们这里的状态表示dp[i][j]到达该位置的路径总数2、状态转移方程

    44分钟前
    00
  • C++程序诗篇的灵动赋形:多态

    本篇将开启 C++ 三大特性中的多态篇章,多态允许你以统一的方式处理不同类型的对象,通过相同的接口来调用不同的实现方法。这意味着你可以编写通用的代码,而这些代码可以在运行时根据对象的实际类型来执行特定的操作1.什么是多态? 通俗来说,就是多

    43分钟前
    00
  • 比云存储更安全?自建宝塔FTP实现企业级远程文件管理全攻略

    前言在数字化时代,谁不想随时随地掌控自己的服务器呢?今天,我们就来聊聊如何用宝塔面板搭配内网穿透工具,让局域网内的FTP服务变得触手可及。想象一下,在咖啡馆里也能轻松上传下载文件,是不是有种成为IT高手的既视感?赶紧跟着我一起揭开这层神秘面

    38分钟前
    00
  • 初识MySQL · 复合查询(内外连接)

    前言:在前文我们学习了MySQL的基本查询,就是简单的套用了select语句,最多不过是加上了一些聚合函数,使用了group by或者是having等。但是对于MySQL语句来说,查询往往是最复杂的,比如在一次查询中我们可能涉及到多个表的查

    35分钟前
    00
  • Spring Boot中的 5 种API请求参数读取方式

    使用Spring Boot开发API的时候,读取请求参数是服务端编码中最基本的一项操作,Spring Boot中也提供了多种机制来满足不同的API设计要求。接下来,就通过本文,为大家总结5种常用的请求参数读取方式。如果你发现自己知道的不到5

    29分钟前
    00
  • 【C++篇】C++模板初阶:从泛型编程到函数模板与类模板的全面解析

    前言在C++编程中,重复编写功能相同但类型不同的代码既低效又容易出错。例如,实现一个通用的交换函数时,若为每种类型都重载一次,代码将臃肿且难以维护。C++模板技术应运而生,它通过“泛型编程”的思想,允许开发者定义类型无关的代码框架,由编译器

    26分钟前
    00
  • win10 远程桌面卡顿_win10远程桌面连接卡如何解决_windows10远程连接桌面很卡怎么处理...

    大家都知道我们可以使用远程连接桌面来对其他计算机进行控制操作&#xff0c;而在win10系统中&#xff0c;也自带有远程桌面连接功能&#xff0c;可是有win10正式版系统用户却发现远程桌面连接卡&#x

    14分钟前
    00
  • 【MySQL】001.MySQL安装

    一. MySQL在Ubuntu 20.04 环境安装1.1 更新软件包列表代码语言:javascript代码运行次数:0运行复制root@hcss-ecs-eaf1:~MySQL# sudo apt-get update1.2 安装MyS

    14分钟前
    00
  • Spring Boot实现微信小程序支付功能

    Spring Boot实现微信小程序支付功能一、引言在当今数字化时代,小程序支付功能已成为众多应用的核心需求之一。通过小程序支付,用户可以便捷地完成购物、充值等操作,极大地提升了用户体验和业务效率。Spring Boot作为一款流行的Jav

    8分钟前
    00
  • 基于Python+Vue开发的房产销售管理系统源码+运行

    本项目是一款基于 Python 和 Vue 开发的房产销售管理系统,采用前后端分离架构设计,专为大学生课程设计作业而开发。其主要目的在于帮助学生掌握 Python 编程技能,同时强化其在项目设计与开发方面的实践能力。通过开发这一房产销售管理

    57秒前
    00

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信