지하 생성 및 터널 구조 개선
This commit is contained in:
@@ -1,41 +1,79 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
|
||||
public class TunnelNode : NetworkBehaviour, IInteractable
|
||||
public class TunnelNode : MonoBehaviour, IInteractable
|
||||
{
|
||||
public TunnelNode aboveNode;
|
||||
public TunnelNode belowNode;
|
||||
public bool isTop;
|
||||
[SerializeField] private TunnelNode partnerNode; // 같은 프리팹 내 반대쪽 노드
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
// [자동 연결] 닿아있는 다른 터널의 노드
|
||||
private TunnelNode neighborNode;
|
||||
|
||||
// 물리적으로 닿으면 자동으로 연결 고리 생성
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// 모든 클라이언트에서 각자 장부에 등록
|
||||
Vector3Int myPos = BuildManager.Instance.WorldToGrid3D(transform.position);
|
||||
BuildManager.Instance.RegisterTunnel(myPos, this);
|
||||
|
||||
// 모든 노드가 등록될 시간을 벌기 위해 서버에서 약간 지연 후 연결 명령
|
||||
if (IsServer) Invoke(nameof(SyncLinks), 0.2f);
|
||||
if (other.TryGetComponent<TunnelNode>(out var neighbor))
|
||||
{
|
||||
// 상단 노드는 하단 노드와만, 하단은 상단과만 연결 (잘못된 조립 방지)
|
||||
if (this.isTop != neighbor.isTop)
|
||||
{
|
||||
neighborNode = neighbor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SyncLinks() => LinkVerticalRpc();
|
||||
|
||||
[Rpc(SendTo.Everyone)]
|
||||
private void LinkVerticalRpc() => LinkVertical();
|
||||
|
||||
public void LinkVertical()
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
Vector3Int myPos = BuildManager.Instance.WorldToGrid3D(transform.position);
|
||||
aboveNode = BuildManager.Instance.GetTunnelAt(myPos + Vector3Int.up);
|
||||
belowNode = BuildManager.Instance.GetTunnelAt(myPos + Vector3Int.down);
|
||||
|
||||
if (aboveNode != null) aboveNode.belowNode = this;
|
||||
if (belowNode != null) belowNode.aboveNode = this;
|
||||
if (other.TryGetComponent<TunnelNode>(out var neighbor))
|
||||
{
|
||||
if (neighborNode == neighbor) neighborNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Interact(GameObject user)
|
||||
public void Interact(GameObject player)
|
||||
{
|
||||
var traveler = user.GetComponent<TunnelTraveler>();
|
||||
if (traveler && !traveler.IsTraveling) traveler.StartTravel(this);
|
||||
// 내가 체인의 끝단(입구/출구)일 때만 작동
|
||||
if (neighborNode != null) return;
|
||||
|
||||
// 반대쪽 끝 노드를 찾아서 이동 요청
|
||||
TunnelNode endNode = FindUltimateEndNode();
|
||||
if (player.TryGetComponent<TunnelTraveler>(out var traveler))
|
||||
{
|
||||
traveler.StartTravel(endNode.transform.position, !endNode.isTop);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetInteractionText() => "터널 이용 [E]";
|
||||
private TunnelNode FindUltimateEndNode()
|
||||
{
|
||||
TunnelNode current = this;
|
||||
|
||||
// [연결 고리 추적] 파트너 -> 이웃 -> 파트너 -> 이웃...
|
||||
while (true)
|
||||
{
|
||||
// 1. 현재 노드의 프리팹 반대쪽(파트너)으로 이동
|
||||
TunnelNode partner = current.partnerNode;
|
||||
|
||||
// 2. 파트너와 연결된 다음 터널의 노드가 있는지 확인
|
||||
if (partner.neighborNode != null)
|
||||
{
|
||||
current = partner.neighborNode; // 다음 터널로 점프
|
||||
}
|
||||
else
|
||||
{
|
||||
return partner; // 더 이상 연결이 없으면 파트너가 최종 목적지
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 디버깅: 연결 상태를 씬 뷰에서 확인
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.color = isTop ? Color.cyan : Color.blue;
|
||||
Gizmos.DrawWireSphere(transform.position, 0.2f);
|
||||
|
||||
if (neighborNode != null)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(transform.position, neighborNode.transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user