Files
2025TapTapGameJam/Assets/Script/Gameplay/Facility/BaseFacilityController.cs

224 lines
6.6 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using Script.Gameplay.Connect;
using Script.Gameplay.Global;
using Script.Gameplay.Interface;
using UnityEngine;
using UnityEngine.Experimental.GlobalIllumination;
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 bool isOpenInEditor = true;
2025-10-26 22:13:15 +08:00
[SerializeField] protected int needSignalCount = 1;
[SerializeField] protected int currentSignalCount = 0;
[SerializeField] protected string componentName;
[SerializeField] protected bool isEnableSendSignal = false;
[SerializeField] protected bool isEnableDeliverSignal = false;
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;
}
2025-10-26 22:13:15 +08:00
public virtual int NeedSignalCount
{
get => needSignalCount;
set => needSignalCount = value;
}
2025-10-26 22:13:15 +08:00
public virtual int CurrentNeedSignalCount
{
get => currentSignalCount;
set => currentSignalCount = 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)
{
2025-10-26 22:13:15 +08:00
CurrentNeedSignalCount++;
}
else
{
CurrentNeedSignalCount = Mathf.Max(0, CurrentNeedSignalCount - 1);
}
2025-10-26 22:13:15 +08:00
if (CurrentNeedSignalCount < NeedSignalCount)
{
return;
}
if (isEnableDeliverSignal)
{
SendSignal(active, sender);
}
// Implement signal received logic here
}
public bool IsEnableSendSignal
{
get => isEnableSendSignal;
set => isEnableSendSignal = value;
}
/// <summary>
///
/// </summary>
/// <param name="active">发送true or false</param>
/// <param name="sender">让此物体触发发送的来源者</param>
public virtual void SendSignal(bool active, GameObject sender)
{
if (!IsEnableSendSignal) return;
if (ConnectionLines != null)
{
// 利用DFS检测是否存在连接环
if (DfsCheckConnectionRing(this.gameObject))
{
BUGManager.Instance.LogStackOverflowBug(this.transform);
StartCoroutine(GameManager.Instance.ReStartGame());
return;
}
foreach (var line in ConnectionLines)
{
// 排除掉为sender的连接线
if (line.gameObject == sender)
{
continue;
}
line.OnSignalReceived(active, this.gameObject);
}
}
}
public static bool DfsCheckConnectionRing(GameObject root)
{
if (root == null) return false;
var rootConnect = root.GetComponent<IConnectable>();
if (rootConnect == null) return false;
var visited = new HashSet<GameObject>();
// 内部递归 DFSparent 用于避免把返回到父节点误判为环
bool Dfs(GameObject current, GameObject parent)
{
if (current == null) return false;
visited.Add(current);
var conn = current.GetComponent<IConnectable>();
if (conn == null) return false;
foreach (var line in conn.ConnectionLines)
{
if (line == null) continue;
GameObject a = line.PointA?.GetGameObject();
GameObject b = line.PointB?.GetGameObject();
GameObject neighbor = null;
if (a == current) neighbor = b;
else if (b == current) neighbor = a;
else continue; // 如果这条线并未连接到 current跳过
if (neighbor == null) continue;
// 如果邻居是父节点,跳过(因为这是无向边回到父)
if (neighbor == parent) continue;
// 已访问到其他非父节点,说明存在环
if (visited.Contains(neighbor))
{
return true;
}
if (Dfs(neighbor, current))
{
return true;
}
}
return false;
}
return Dfs(root, null);
}
}
}