222 lines
6.5 KiB
C#
222 lines
6.5 KiB
C#
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;
|
||
|
||
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 (isEnableSendSignal)
|
||
{
|
||
SendSignal(active, sender);
|
||
}
|
||
|
||
if (active)
|
||
{
|
||
CurrentNeedSignalCount++;
|
||
}
|
||
else
|
||
{
|
||
CurrentNeedSignalCount = Mathf.Max(0, CurrentNeedSignalCount - 1);
|
||
}
|
||
|
||
if (CurrentNeedSignalCount < NeedSignalCount)
|
||
{
|
||
return;
|
||
}
|
||
// 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))
|
||
{
|
||
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>();
|
||
|
||
// 内部递归 DFS,parent 用于避免把返回到父节点误判为环
|
||
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);
|
||
}
|
||
}
|
||
} |