refactor(Facility): 使用继承让所有机关都拥有了独自的 可交互 可编辑 可连接设定。大面积重构
This commit is contained in:
124
Assets/Script/Gameplay/Facility/BaseFacilityController.cs
Normal file
124
Assets/Script/Gameplay/Facility/BaseFacilityController.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System.Collections.Generic;
|
||||
using Script.Gameplay.Connect;
|
||||
using Script.Gameplay.Interface;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class BaseFacilityController : MonoBehaviour, IInteractable, IEditableComponent, IConnectable, ISignalSender,
|
||||
ISignalReceiver, IGaze
|
||||
{
|
||||
[SerializeField] protected bool isEnableInteract = true;
|
||||
[SerializeField] protected bool isEnableEdit = true;
|
||||
[SerializeField] protected bool isEnableConnect = true;
|
||||
[SerializeField] protected string componentName;
|
||||
[SerializeField] protected int needSignalCount = 1;
|
||||
[SerializeField] protected bool isOpenInEditor = true;
|
||||
protected int CurrentSignalCount = 0;
|
||||
|
||||
public virtual bool IsEnableInteract
|
||||
{
|
||||
get => isEnableInteract;
|
||||
set => isEnableInteract = value;
|
||||
}
|
||||
|
||||
public virtual bool IsEnableEdit
|
||||
{
|
||||
get => isEnableEdit;
|
||||
set => isEnableEdit = value;
|
||||
}
|
||||
|
||||
public virtual bool IsOpenInEditor
|
||||
{
|
||||
get => isOpenInEditor;
|
||||
set
|
||||
{
|
||||
isOpenInEditor = value;
|
||||
IsEnableInteract = value;
|
||||
IsEnableConnect = value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsEnableConnect
|
||||
{
|
||||
get => isEnableConnect;
|
||||
set => isEnableConnect = value;
|
||||
}
|
||||
|
||||
public string ComponentName
|
||||
{
|
||||
get
|
||||
{
|
||||
// 如果没有自定义名称,则使用组件名称
|
||||
return string.IsNullOrEmpty(componentName) ? GetType().Name : componentName;
|
||||
}
|
||||
set => componentName = value;
|
||||
}
|
||||
|
||||
public List<ConnectionLine> ConnectionLines { get; set; } = new List<ConnectionLine>();
|
||||
|
||||
public string GetConnectableName()
|
||||
{
|
||||
return gameObject.name;
|
||||
}
|
||||
|
||||
public GameObject GetGameObject()
|
||||
{
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
public virtual string GetInteractPrompt()
|
||||
{
|
||||
return $"Interact with {componentName}";
|
||||
}
|
||||
|
||||
public Vector3 GetPosition()
|
||||
{
|
||||
return transform.position;
|
||||
}
|
||||
|
||||
public virtual void Interact(GameObject interactor)
|
||||
{
|
||||
// Implement interaction logic here
|
||||
}
|
||||
|
||||
public virtual void OnGazeEnter(GameObject go)
|
||||
{
|
||||
// Handle gaze enter
|
||||
}
|
||||
|
||||
public virtual void OnGazeExit(GameObject go)
|
||||
{
|
||||
// Handle gaze exit
|
||||
}
|
||||
|
||||
public virtual void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
CurrentSignalCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSignalCount = Mathf.Max(0, CurrentSignalCount - 1);
|
||||
}
|
||||
|
||||
if (CurrentSignalCount < needSignalCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Implement signal received logic here
|
||||
}
|
||||
|
||||
public virtual void SendSignal(bool active, GameObject sender)
|
||||
{
|
||||
if (ConnectionLines != null)
|
||||
{
|
||||
foreach (var line in ConnectionLines)
|
||||
{
|
||||
line.OnSignalReceived(active, this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e9f3dfa12a48a74ab978e8c7c8cb0af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/Script/Gameplay/Facility/ButtonInteractController.cs
Normal file
38
Assets/Script/Gameplay/Facility/ButtonInteractController.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Interface;
|
||||
using Script.Gameplay.Connect;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class ButtonInteractController : BaseFacilityController
|
||||
{
|
||||
[SerializeField] private float signalDuration = 1.0f; // 信号持续时间(秒)
|
||||
private bool IsPressing = true;
|
||||
|
||||
public override string GetInteractPrompt()
|
||||
{
|
||||
return "按F按下按钮";
|
||||
}
|
||||
|
||||
public override void Interact(GameObject interactor)
|
||||
{
|
||||
if (!IsPressing) return;
|
||||
StartCoroutine(SendSignalCoroutine());
|
||||
Debug.Log("Button pressed");
|
||||
}
|
||||
|
||||
private IEnumerator SendSignalCoroutine()
|
||||
{
|
||||
SendSignal(true, this.gameObject);
|
||||
IsPressing = false;
|
||||
// 按钮压下的动画或效果可以在这里添加
|
||||
|
||||
yield return new WaitForSeconds(signalDuration);
|
||||
SendSignal(false, this.gameObject);
|
||||
IsPressing = true;
|
||||
// 按钮弹起的动画或效果可以在这里添加
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5359facd804a0cb94d416c9c54a167
|
||||
timeCreated: 1760923022
|
||||
50
Assets/Script/Gameplay/Facility/ConsoleController.cs
Normal file
50
Assets/Script/Gameplay/Facility/ConsoleController.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using Script.Gameplay.Connect;
|
||||
using Script.Gameplay.Interface;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class ConsoleController : BaseFacilityController
|
||||
{
|
||||
[SerializeField] private List<MonoBehaviour> controlTarget;
|
||||
[SerializeField] private bool IsBeActive = false;
|
||||
private List<ISignalReceiver> controlTargetSignalReceiver = new List<ISignalReceiver>();
|
||||
private bool lastSendSignal = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
foreach (var target in controlTarget)
|
||||
{
|
||||
if (target is ISignalReceiver receiver)
|
||||
{
|
||||
controlTargetSignalReceiver.Add(receiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target != null)
|
||||
Debug.Log(target.name + " is not a supported control target");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
base.OnSignalReceived(active, sender);
|
||||
IsBeActive = active;
|
||||
}
|
||||
|
||||
public override void Interact(GameObject interactor)
|
||||
{
|
||||
if (IsBeActive && controlTargetSignalReceiver != null)
|
||||
{
|
||||
var signal = !lastSendSignal;
|
||||
foreach (var receiver in controlTargetSignalReceiver)
|
||||
{
|
||||
receiver.OnSignalReceived(signal, this.gameObject);
|
||||
}
|
||||
lastSendSignal = signal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc0b1376aefb4cccb530717966b48bf5
|
||||
timeCreated: 1761039706
|
||||
58
Assets/Script/Gameplay/Facility/DoorInteractController.cs
Normal file
58
Assets/Script/Gameplay/Facility/DoorInteractController.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Script.Gameplay.Player;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Interface;
|
||||
using Script.Gameplay.Connect;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class DoorInteractController : BaseFacilityController
|
||||
{
|
||||
private bool isOpened = false;
|
||||
public override string GetInteractPrompt()
|
||||
{
|
||||
return "按F进行交互";
|
||||
}
|
||||
|
||||
public override void Interact(GameObject interactor)
|
||||
{
|
||||
if (isOpened)
|
||||
{
|
||||
CloseDoor();
|
||||
isOpened = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenDoor();
|
||||
isOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGazeEnter(GameObject go)
|
||||
{
|
||||
// 可扩展:门被注视时的逻辑
|
||||
}
|
||||
|
||||
public override void OnGazeExit(GameObject go)
|
||||
{
|
||||
// 可扩展:门离开注视时的逻辑
|
||||
}
|
||||
|
||||
private void OpenDoor()
|
||||
{
|
||||
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + new Vector3(0, -90, 0));
|
||||
}
|
||||
|
||||
private void CloseDoor()
|
||||
{
|
||||
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + new Vector3(0, 90, 0));
|
||||
}
|
||||
|
||||
|
||||
public override void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
Interact(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bdc5380046d4cacb0dd579877f320eb
|
||||
timeCreated: 1760693181
|
||||
64
Assets/Script/Gameplay/Facility/EmitterController.cs
Normal file
64
Assets/Script/Gameplay/Facility/EmitterController.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Connect;
|
||||
using Script.Gameplay.Interface;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class EmitterController : BaseFacilityController
|
||||
{
|
||||
[Header("发射器设置")]
|
||||
[SerializeField] private GameObject prefabToEmit;
|
||||
[SerializeField] private Transform emitPoint;
|
||||
[SerializeField] private Vector3 emitDirection = Vector3.forward;
|
||||
[SerializeField] private float emitForce = 10f;
|
||||
[SerializeField] private float emitInterval = 1f;
|
||||
[Header("生成对象销毁时间")]
|
||||
[SerializeField] private float destroyDelay = 5f; // 生成对象多少秒后销毁
|
||||
|
||||
private Coroutine emitCoroutine;
|
||||
|
||||
// 接收信号
|
||||
public override void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
base.OnSignalReceived(active, sender);
|
||||
if(!isOpenInEditor) return;
|
||||
if (active)
|
||||
{
|
||||
if (emitCoroutine == null)
|
||||
emitCoroutine = StartCoroutine(EmitRoutine());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (emitCoroutine != null)
|
||||
{
|
||||
StopCoroutine(emitCoroutine);
|
||||
emitCoroutine = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator EmitRoutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Emit();
|
||||
yield return new WaitForSeconds(emitInterval);
|
||||
}
|
||||
}
|
||||
|
||||
private void Emit()
|
||||
{
|
||||
if (prefabToEmit == null || emitPoint == null) return;
|
||||
var obj = Instantiate(prefabToEmit, emitPoint.position, emitPoint.rotation);
|
||||
var rb = obj.GetComponent<Rigidbody>();
|
||||
if (rb != null)
|
||||
{
|
||||
rb.AddForce(emitPoint.TransformDirection(emitDirection.normalized) * emitForce, ForceMode.Impulse);
|
||||
}
|
||||
// 添加销毁逻辑
|
||||
Destroy(obj, destroyDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a5a563132c84e50b983b557eb3da442
|
||||
timeCreated: 1761028056
|
||||
36
Assets/Script/Gameplay/Facility/LeverInteractController.cs
Normal file
36
Assets/Script/Gameplay/Facility/LeverInteractController.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Interface;
|
||||
using Script.Gameplay.Connect;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class LeverInteractController : BaseFacilityController
|
||||
{
|
||||
private bool isPulled = false;
|
||||
|
||||
public override string GetInteractPrompt()
|
||||
{
|
||||
return "按F拉动拉杆";
|
||||
}
|
||||
|
||||
public override void Interact(GameObject interactor)
|
||||
{
|
||||
if (!IsEnableInteract) return;
|
||||
isPulled = !isPulled;
|
||||
SendSignal(isPulled, this.gameObject);
|
||||
// 可选:拉杆动画
|
||||
//Debug.Log(isPulled ? "Lever pulled down" : "Lever reset");
|
||||
}
|
||||
|
||||
public override void OnGazeEnter(GameObject go)
|
||||
{
|
||||
// 可选:高亮拉杆
|
||||
}
|
||||
|
||||
public override void OnGazeExit(GameObject go)
|
||||
{
|
||||
// 可选:取消高亮
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b9b9a895b0d40edb9a6d7213afbb256
|
||||
timeCreated: 1760925436
|
||||
62
Assets/Script/Gameplay/Facility/MovingPlatformController.cs
Normal file
62
Assets/Script/Gameplay/Facility/MovingPlatformController.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Connect;
|
||||
using Script.Gameplay.Interface;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class MovingPlatformController : BaseFacilityController
|
||||
{
|
||||
[SerializeField] private GameObject startPositionObject;
|
||||
[SerializeField] private GameObject targetPositionObject;
|
||||
[SerializeField] public float moveSpeed = 2f;
|
||||
private Vector3 startPosition;
|
||||
private Vector3 targetPosition;
|
||||
|
||||
private bool isMoving = false;
|
||||
private bool forward = true;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
startPosition = startPositionObject.transform.position;
|
||||
targetPosition = targetPositionObject.transform.position;
|
||||
transform.position = startPosition;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isMoving) return;
|
||||
|
||||
Vector3 destination = forward ? targetPosition : startPosition;
|
||||
transform.position = Vector3.MoveTowards(transform.position, destination, moveSpeed * Time.deltaTime);
|
||||
|
||||
if (Vector3.Distance(transform.position, destination) < 0.01f)
|
||||
{
|
||||
forward = !forward;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
base.OnSignalReceived(active, sender);
|
||||
if (active)
|
||||
{
|
||||
isMoving = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isMoving = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 可选:如果需要编辑激活状态,可以重写属性
|
||||
public override bool IsEnableEdit
|
||||
{
|
||||
get => base.IsEnableEdit;
|
||||
set
|
||||
{
|
||||
base.IsEnableEdit = value;
|
||||
isMoving = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 115d4e847c444833bc8dce4a03a78e55
|
||||
timeCreated: 1761038093
|
||||
53
Assets/Script/Gameplay/Facility/NumberSlotController.cs
Normal file
53
Assets/Script/Gameplay/Facility/NumberSlotController.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Connect;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
// 号码枚举类型
|
||||
public enum NumberType
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
// Six,
|
||||
// Seven,
|
||||
// Eight,
|
||||
// Nine
|
||||
}
|
||||
|
||||
// 号码槽
|
||||
public class NumberSlotController : BaseFacilityController
|
||||
{
|
||||
[Header("号码槽设置")]
|
||||
[SerializeField] private NumberType currentNumber = NumberType.Zero;
|
||||
[SerializeField] private NumberType correctNumber = NumberType.One;
|
||||
|
||||
// 接收信号
|
||||
public override void OnSignalReceived(bool active, GameObject sender)
|
||||
{
|
||||
base.OnSignalReceived(active, sender);
|
||||
if (active)
|
||||
{
|
||||
SwitchToNextNumber();
|
||||
}
|
||||
}
|
||||
|
||||
// 切换到下一个号码
|
||||
private void SwitchToNextNumber()
|
||||
{
|
||||
currentNumber = (NumberType)(((int)currentNumber + 1) % System.Enum.GetValues(typeof(NumberType)).Length);
|
||||
CheckNumberAndSendSignal();
|
||||
}
|
||||
|
||||
// 检查号码并发信号
|
||||
private void CheckNumberAndSendSignal()
|
||||
{
|
||||
bool isCorrect = currentNumber == correctNumber;
|
||||
SendSignal(isCorrect, this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 301178d89b6b43e0844e3d39aa579442
|
||||
timeCreated: 1760961220
|
||||
35
Assets/Script/Gameplay/Facility/PressurePlateController.cs
Normal file
35
Assets/Script/Gameplay/Facility/PressurePlateController.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Script.Gameplay.Connect;
|
||||
|
||||
namespace Script.Gameplay.Facility
|
||||
{
|
||||
public class PressurePlateController : BaseFacilityController
|
||||
{
|
||||
[SerializeField] private LayerMask detectLayer = ~0; // 检测所有层,可在Inspector中指定
|
||||
[SerializeField] private Vector3 plateSize = new Vector3(1, 0.2f, 1);
|
||||
[SerializeField] private Vector3 plateOffset = Vector3.up * 0.1f;
|
||||
|
||||
private bool lastState = false;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!isEnableInteract) return;
|
||||
bool hasObject = Physics.CheckBox(transform.position + plateOffset, plateSize * 0.5f, Quaternion.identity, detectLayer);
|
||||
if (hasObject != lastState)
|
||||
{
|
||||
SendSignal(hasObject, this.gameObject);
|
||||
lastState = hasObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireCube(transform.position + plateOffset, plateSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2557c7d42f7a4d8896712ab2ae980b6f
|
||||
timeCreated: 1760924285
|
||||
Reference in New Issue
Block a user