Unity C# 可复用多门多杠杆气闸制作方案问询
可复用2D Unity气闸系统脚本实现方案
需求明确
- 每套气闸包含2扇门+至少2个控制杠杆
- 初始状态:两扇门全部关闭
- 操作逻辑:
- 触发第一个杠杆:仅打开第一扇门
- 触发第二个杠杆:关闭当前打开的门,同时打开另一扇门
- 需完全替代原有依赖全局变量、硬编码场景对象的不可复用脚本
现有脚本的核心问题
Lever.cs使用静态变量leverStatus,所有杠杆共享同一状态,复用必互相干扰- 硬编码查找特定标签对象(如
Vacuum、Lever-Door),无法实现独立气闸组 LeverDoor.cs逻辑冗余,Update中强制激活物体完全无意义
可复用脚本实现步骤
1. 通用门控制脚本 AirlockDoor.cs
负责单扇门的状态管理、视觉反馈与音效播放,可直接绑定到任意门物体:
using UnityEngine; public class AirlockDoor : MonoBehaviour { [Header("门基础设置")] [SerializeField] private bool initialOpen = false; // 初始状态默认关闭 [SerializeField] private Animator doorAnimator; // 可选:门开关动画组件 [SerializeField] private AudioClip openSound; // 可选:开门音效 [SerializeField] private AudioClip closeSound; // 可选:关门音效 private AudioSource audioSource; private bool isOpen; private void Awake() { audioSource = GetComponent<AudioSource>(); isOpen = initialOpen; UpdateDoorState(); } // 切换门的开关状态 public void ToggleDoor() { isOpen = !isOpen; UpdateDoorState(); PlayDoorSound(); } // 直接指定门的开/关状态 public void SetDoorState(bool shouldOpen) { if (isOpen != shouldOpen) { isOpen = shouldOpen; UpdateDoorState(); PlayDoorSound(); } } // 更新门的视觉/碰撞状态 private void UpdateDoorState() { if (doorAnimator != null) { doorAnimator.SetBool("IsOpen", isOpen); } else { // 无动画时,直接控制碰撞体和渲染器 Collider2D collider = GetComponent<Collider2D>(); SpriteRenderer renderer = GetComponent<SpriteRenderer>(); if (collider != null) collider.enabled = !isOpen; if (renderer != null) renderer.enabled = !isOpen; } } // 播放门操作音效 private void PlayDoorSound() { if (audioSource == null) return; AudioClip clip = isOpen ? openSound : closeSound; if (clip != null) audioSource.PlayOneShot(clip); } // 外部获取门当前状态 public bool IsDoorOpen() => isOpen; }
2. 气闸组核心管理器 AirlockManager.cs
每套气闸对应一个管理器,负责统筹门与杠杆的逻辑,确保气闸组完全独立:
using UnityEngine; using System.Collections; public class AirlockManager : MonoBehaviour { [Header("气闸组件关联")] [SerializeField] private AirlockDoor entranceDoor; // 入口门(第一扇门) [SerializeField] private AirlockDoor exitDoor; // 出口门(第二扇门) [SerializeField] private AudioClip leverUseSound; // 杠杆操作音效 [SerializeField] private AudioClip pressureEqualizeSound; // 气压平衡音效(可选) private AudioSource audioSource; private bool entranceLeverActivated = false; // 标记入口杠杆是否已触发 private void Awake() { audioSource = GetComponent<AudioSource>(); // 初始化:两扇门全部关闭 entranceDoor.SetDoorState(false); exitDoor.SetDoorState(false); } // 入口杠杆触发逻辑:仅打开入口门 public void TriggerEntranceLever() { if (entranceLeverActivated) return; // 防止重复触发 PlaySound(leverUseSound); entranceDoor.SetDoorState(true); entranceLeverActivated = true; } // 出口杠杆触发逻辑:关闭当前门 → 气压平衡 → 打开另一扇门 public void TriggerExitLever() { PlaySound(leverUseSound); StartCoroutine(EqualizePressureAndSwitchDoors()); } // 模拟气压平衡流程(可根据需求调整延迟时间) private IEnumerator EqualizePressureAndSwitchDoors() { // 先关闭当前打开的门 if (entranceDoor.IsDoorOpen()) entranceDoor.SetDoorState(false); PlaySound(pressureEqualizeSound); yield return new WaitForSeconds(1.5f); // 气压平衡等待时间 // 打开出口门 exitDoor.SetDoorState(true); } private void PlaySound(AudioClip clip) { if (audioSource != null && clip != null) audioSource.PlayOneShot(clip); } }
3. 通用交互杠杆脚本 InteractableLever.cs
处理玩家与杠杆的交互逻辑,可绑定到任意杠杆物体,通过Inspector指定对应气闸组:
using UnityEngine; public class InteractableLever : MonoBehaviour { [Header("交互设置")] [SerializeField] private AirlockManager targetAirlock; // 关联的气闸管理器 [SerializeField] private bool isEntranceLever; // 标记是否为入口杠杆 [SerializeField] private Animator leverAnimator; // 可选:杠杆触发动画 [SerializeField] private string interactPrompt = "按E操作杠杆"; // 交互提示文本 private bool playerInRange = false; private bool leverActivated = false; private void Update() { if (playerInRange && !leverActivated && Input.GetAxisRaw("Interact") != 0) { ActivateLever(); } } private void ActivateLever() { leverActivated = true; // 播放杠杆动画 if (leverAnimator != null) leverAnimator.SetTrigger("Activate"); // 触发对应气闸逻辑 if (isEntranceLever) targetAirlock.TriggerEntranceLever(); else targetAirlock.TriggerExitLever(); } private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Player")) { playerInRange = true; // 显示交互提示(需你的UIHandler实现对应方法) UIHandler.Instance.ShowUseInfo(interactPrompt); } } private void OnTriggerExit2D(Collider2D other) { if (other.CompareTag("Player")) { playerInRange = false; UIHandler.Instance.DisableUseInfo(); } } }
使用流程
- 创建空物体作为气闸组容器,挂载
AirlockManager,在Inspector中关联两扇门与音效 - 给两扇门分别挂载
AirlockDoor,设置初始状态为关闭,按需添加动画和音效 - 创建两个杠杆物体,分别挂载
InteractableLever:- 入口杠杆:勾选
isEntranceLever,关联对应AirlockManager - 出口杠杆:取消勾选
isEntranceLever,关联同一个AirlockManager
- 入口杠杆:勾选
- 确保玩家物体带有
Player标签,且有2D触发器碰撞体用于交互检测 - 确保你的
UIHandler实现ShowUseInfo(string)和DisableUseInfo()方法,用于显示交互提示
核心优势
- 每套气闸独立管理,完全不会干扰其他场景或区域的气闸
- 模块化设计,所有脚本可直接复制复用,无需修改核心逻辑
- 逻辑分层清晰,新手易理解和调整,无全局变量或硬编码依赖
内容的提问来源于stack exchange,提问作者Sascha
相关产品推荐
相关产品推荐

