2025-10-19 19:38:52 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using Core;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using Script.Gameplay.Connect;
|
|
|
|
|
using Script.Gameplay.Input;
|
|
|
|
|
using System;
|
|
|
|
|
|
2025-10-20 10:12:07 +08:00
|
|
|
|
namespace Script.Gameplay.Player
|
2025-10-19 19:38:52 +08:00
|
|
|
|
{
|
|
|
|
|
public class PlayerConnectController : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
public bool IsEnableConnecting = true; // 是否启用连接功能
|
|
|
|
|
[SerializeField] private FirstPersonRaycaster raycaster; // 第一人称射线检测器
|
2025-10-20 10:42:32 +08:00
|
|
|
|
[SerializeField] private float maxConnectDistance = 10f; // 最大连接距离
|
2025-10-19 19:38:52 +08:00
|
|
|
|
|
|
|
|
|
private IConnectable currentTarget; // 当前注视的可连接对象
|
|
|
|
|
private IConnectable previousGazedTarget; // 上一次注视的 IConnectable(用于触发进入/离开)
|
|
|
|
|
private InputManager inputManager;
|
|
|
|
|
|
|
|
|
|
private IConnectable outTarget;
|
|
|
|
|
private IConnectable inputTarget;
|
|
|
|
|
public event Action<IConnectable> OnSetOutputTarget;
|
|
|
|
|
public event Action<IConnectable> OnSetInputTarget;
|
|
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
|
|
|
|
inputManager = InputManager.Instance;
|
|
|
|
|
inputManager.Input.Player.SetOutput.performed += ctx => SetOutTarget(currentTarget);
|
|
|
|
|
inputManager.Input.Player.SetInput.performed += ctx => SetInputTarget(currentTarget);
|
|
|
|
|
inputManager.Input.Player.Connect.performed += ctx => CreateConnection();
|
2025-10-20 10:33:00 +08:00
|
|
|
|
inputManager.Input.Player.CutLine.performed += ctx => CutConnectLine(currentTarget);
|
2025-10-19 19:38:52 +08:00
|
|
|
|
|
|
|
|
|
if (raycaster == null)
|
|
|
|
|
raycaster = GetComponent<FirstPersonRaycaster>() ?? GetComponentInChildren<FirstPersonRaycaster>();
|
|
|
|
|
if (raycaster == null)
|
|
|
|
|
raycaster = FindObjectOfType<FirstPersonRaycaster>();
|
|
|
|
|
if (raycaster == null)
|
|
|
|
|
Debug.LogWarning("FirstPersonRaycaster not found! Please assign or add it to the player.");
|
|
|
|
|
|
|
|
|
|
ControllerLocator.Instance.Register(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
|
|
|
|
DetectConnectable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DetectConnectable()
|
|
|
|
|
{
|
|
|
|
|
if (raycaster == null) return;
|
|
|
|
|
|
|
|
|
|
GameObject lookAtObj = raycaster.CurrentLookAtObject;
|
|
|
|
|
IConnectable hitConnectable = lookAtObj != null ? lookAtObj.GetComponent<IConnectable>() : null;
|
|
|
|
|
|
|
|
|
|
// 注视对象变化时触发进入/离开(使用接口方法)
|
|
|
|
|
if (hitConnectable != previousGazedTarget)
|
|
|
|
|
{
|
|
|
|
|
if (previousGazedTarget != null)
|
|
|
|
|
{
|
|
|
|
|
previousGazedTarget.OnGazeExit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hitConnectable != null)
|
|
|
|
|
{
|
|
|
|
|
hitConnectable.OnGazeEnter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
previousGazedTarget = hitConnectable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentTarget = hitConnectable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public IConnectable GetCurrentTarget()
|
|
|
|
|
{
|
|
|
|
|
return currentTarget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetOutTarget(IConnectable target)
|
|
|
|
|
{
|
|
|
|
|
if (target == null) return;
|
|
|
|
|
if(!IsEnableConnecting) return;
|
|
|
|
|
if (!target.IsConnectedOutput)
|
|
|
|
|
{
|
|
|
|
|
outTarget = target;
|
|
|
|
|
OnSetOutputTarget?.Invoke(outTarget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetInputTarget(IConnectable target)
|
|
|
|
|
{
|
|
|
|
|
if (target == null) return;
|
|
|
|
|
if(!IsEnableConnecting) return;
|
|
|
|
|
if (!target.IsConnectedInput)
|
|
|
|
|
{
|
|
|
|
|
inputTarget = currentTarget;
|
|
|
|
|
OnSetInputTarget?.Invoke(inputTarget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 10:33:00 +08:00
|
|
|
|
public void CutConnectLine(IConnectable target)
|
|
|
|
|
{
|
|
|
|
|
if (target == null) return;
|
|
|
|
|
if(target.OutputConnectionLine != null && target.InputConnectionLine != null) return;
|
|
|
|
|
target.OutputConnectionLine?.DeleteConnection();
|
|
|
|
|
target.InputConnectionLine?.DeleteConnection();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 19:38:52 +08:00
|
|
|
|
private void CreateConnection()
|
|
|
|
|
{
|
|
|
|
|
if(!IsEnableConnecting) return;
|
|
|
|
|
if (outTarget != null && inputTarget != null && outTarget != inputTarget)
|
|
|
|
|
{
|
2025-10-20 10:42:32 +08:00
|
|
|
|
//计算距离
|
|
|
|
|
float distance = Vector3.Distance(outTarget.GetPosition(), inputTarget.GetPosition());
|
|
|
|
|
if (distance > maxConnectDistance)
|
|
|
|
|
{
|
|
|
|
|
Debug.Log("Cannot create connection: targets are too far apart.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 创建连接线
|
2025-10-19 19:38:52 +08:00
|
|
|
|
ConnectionLine connectionLine = ConnectionLineManager.Instance.GenerateConnectionLine(outTarget, inputTarget);
|
2025-10-20 11:02:10 +08:00
|
|
|
|
|
2025-10-19 19:38:52 +08:00
|
|
|
|
// 重置信号目标
|
|
|
|
|
outTarget = null;
|
|
|
|
|
inputTarget = null;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.Log("Cannot create connection: invalid targets.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnDrawGizmos()
|
|
|
|
|
{
|
|
|
|
|
// 射线可视化交由 FirstPersonRaycaster 处理
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|