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

224 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
[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;
}
public virtual int NeedSignalCount
{
get => needSignalCount;
set => needSignalCount = value;
}
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)
{
CurrentNeedSignalCount++;
}
else
{
CurrentNeedSignalCount = Mathf.Max(0, CurrentNeedSignalCount - 1);
}
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);
}
}
}