조준 시스템 개선
다른 블록에 의해 경로가 막힐 경우, 막은 블록을 하이라이트 + 조준과 공격 대상 선정 로직이 같아졌기 때문에 로직 통합
This commit is contained in:
@@ -34,6 +34,7 @@ public class PlayerNetworkController : NetworkBehaviour
|
|||||||
[SerializeField] private Sprite targetCrosshair;
|
[SerializeField] private Sprite targetCrosshair;
|
||||||
private RectTransform _crosshairRect;
|
private RectTransform _crosshairRect;
|
||||||
private MineableBlock _currentTargetBlock; // 현재 강조 중인 블록 저장
|
private MineableBlock _currentTargetBlock; // 현재 강조 중인 블록 저장
|
||||||
|
private MineableBlock _lastHighlightedBlock;
|
||||||
|
|
||||||
private CharacterController _controller;
|
private CharacterController _controller;
|
||||||
private PlayerInputActions _inputActions;
|
private PlayerInputActions _inputActions;
|
||||||
@@ -152,27 +153,11 @@ public class PlayerNetworkController : NetworkBehaviour
|
|||||||
{
|
{
|
||||||
if (!IsOwner) return;
|
if (!IsOwner) return;
|
||||||
|
|
||||||
// 1. 마우스가 가리키는 월드상의 위치를 먼저 찾습니다.
|
// 현재 하이라이트 중인 블록이 있다면 그 녀석이 바로 공격 대상입니다!
|
||||||
Ray mouseRay = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
if (_lastHighlightedBlock != null)
|
||||||
Vector3 worldAimPoint;
|
|
||||||
|
|
||||||
// 아주 멀리까지 레이를 쏴서 조준 방향을 결정합니다.
|
|
||||||
if (Physics.Raycast(mouseRay, out RaycastHit mouseHit, 1000f, ~ignoreDuringAim))
|
|
||||||
worldAimPoint = mouseHit.point;
|
|
||||||
else
|
|
||||||
worldAimPoint = mouseRay.GetPoint(100f);
|
|
||||||
|
|
||||||
// 2. 캐릭터 가슴 높이에서 조준점을 향하는 방향 계산
|
|
||||||
Vector3 origin = transform.position + Vector3.up * 1.2f;
|
|
||||||
Vector3 direction = (worldAimPoint - origin).normalized;
|
|
||||||
|
|
||||||
// 3. 캐릭터에서 해당 방향으로 SphereCast를 쏴서 가장 가까운 블록 하나를 찾습니다.
|
|
||||||
// SphereCast는 가장 먼저 닿는 오브젝트 하나만 hit에 담습니다.
|
|
||||||
if (Physics.SphereCast(origin, aimRadius, direction, out RaycastHit blockHit, attackRange, mineableLayer))
|
|
||||||
{
|
{
|
||||||
if (blockHit.collider.TryGetComponent<NetworkObject>(out var netObj))
|
if (_lastHighlightedBlock.TryGetComponent<NetworkObject>(out var netObj))
|
||||||
{
|
{
|
||||||
// 서버에 대미지 요청
|
|
||||||
ApplyMiningDamageServerRpc(netObj.NetworkObjectId);
|
ApplyMiningDamageServerRpc(netObj.NetworkObjectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,48 +271,52 @@ public class PlayerNetworkController : NetworkBehaviour
|
|||||||
{
|
{
|
||||||
if (!IsOwner || _crosshairRect == null) return;
|
if (!IsOwner || _crosshairRect == null) return;
|
||||||
|
|
||||||
// 1. [조준점 확보] 카메라 레이로 마우스가 가리키는 '실제 지점'을 찾습니다.
|
// 1. 카메라 레이로 조준점 계산 (플레이어 몸통 무시)
|
||||||
Ray cameraRay = Camera.main.ScreenPointToRay(_crosshairRect.position);
|
Ray aimRay = Camera.main.ScreenPointToRay(_crosshairRect.position);
|
||||||
RaycastHit cameraHit;
|
Vector3 worldAimPoint;
|
||||||
|
if (Physics.Raycast(aimRay, out RaycastHit mouseHit, 100f, ~ignoreDuringAim))
|
||||||
// 지형이나 블록을 모두 검사하여 조준점을 잡습니다.
|
worldAimPoint = mouseHit.point;
|
||||||
bool hitSomething = Physics.Raycast(cameraRay, out cameraHit, 150f, ~ignoreDuringAim);
|
|
||||||
Vector3 worldAimPoint = hitSomething ? cameraHit.point : cameraRay.GetPoint(100f);
|
|
||||||
|
|
||||||
// 2. [거리 및 방향 계산] 캐릭터 가슴에서 그 지점까지의 벡터를 구합니다.
|
|
||||||
Vector3 origin = transform.position + Vector3.up * 1.2f;
|
|
||||||
Vector3 toTarget = worldAimPoint - origin;
|
|
||||||
float distToTarget = toTarget.magnitude;
|
|
||||||
Vector3 direction = toTarget.normalized;
|
|
||||||
|
|
||||||
// 3. [대상 우선 판정]
|
|
||||||
// 만약 카메라 레이가 '채광 가능한 블록'을 직접 때렸고, 그게 사거리 이내라면? -> 바로 타겟팅!
|
|
||||||
bool isDirectHit = hitSomething && ((1 << cameraHit.collider.gameObject.layer) & mineableLayer) != 0;
|
|
||||||
|
|
||||||
RaycastHit finalHit;
|
|
||||||
bool hasValidTarget = false;
|
|
||||||
|
|
||||||
if (isDirectHit && distToTarget <= attackRange)
|
|
||||||
{
|
|
||||||
// 마우스가 직접 블록을 가리키고 사거리 내에 있는 경우
|
|
||||||
finalHit = cameraHit;
|
|
||||||
hasValidTarget = true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
worldAimPoint = aimRay.GetPoint(50f);
|
||||||
|
|
||||||
|
// 2. 캐릭터 가슴에서 조준점을 향하는 방향 계산
|
||||||
|
Vector3 origin = transform.position + Vector3.up * 1.2f;
|
||||||
|
Vector3 direction = (worldAimPoint - origin).normalized;
|
||||||
|
|
||||||
|
// 자기 자신 충돌 방지용 오프셋
|
||||||
|
Vector3 rayStart = origin + direction * 0.4f;
|
||||||
|
|
||||||
|
// 3. [중요] 실제 공격과 동일한 SphereCast 실행
|
||||||
|
RaycastHit blockHit;
|
||||||
|
bool hasTarget = Physics.SphereCast(rayStart, aimRadius, direction, out blockHit, attackRange - 0.4f, mineableLayer);
|
||||||
|
|
||||||
|
// 4. 하이라이트 대상 업데이트
|
||||||
|
MineableBlock currentTarget = null;
|
||||||
|
if (hasTarget)
|
||||||
{
|
{
|
||||||
// 마우스가 허공을 보거나 너무 먼 곳을 볼 때만 '범위 탐색(SphereCast)'을 수행합니다.
|
currentTarget = blockHit.collider.GetComponentInParent<MineableBlock>();
|
||||||
float searchDist = Mathf.Min(distToTarget, attackRange);
|
|
||||||
Vector3 rayStart = origin + direction * 0.4f;
|
|
||||||
hasValidTarget = Physics.SphereCast(rayStart, aimRadius, direction, out finalHit, searchDist - 0.4f, mineableLayer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 디버그 및 시각화 업데이트
|
// 대상이 바뀌었을 때만 아웃라인 갱신 (최적화)
|
||||||
_debugOrigin = origin;
|
if (_lastHighlightedBlock != currentTarget)
|
||||||
_debugDir = direction;
|
{
|
||||||
_debugHit = hasValidTarget;
|
if (_lastHighlightedBlock != null) _lastHighlightedBlock.SetHighlight(false);
|
||||||
_debugDist = hasValidTarget ? Vector3.Distance(origin, finalHit.point) : Mathf.Min(distToTarget, attackRange);
|
if (currentTarget != null) currentTarget.SetHighlight(true);
|
||||||
|
_lastHighlightedBlock = currentTarget;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateBlockVisuals(hasValidTarget, finalHit);
|
// 기즈모 디버그 데이터 동기화
|
||||||
|
_debugOrigin = rayStart;
|
||||||
|
_debugDir = direction;
|
||||||
|
_debugHit = hasTarget;
|
||||||
|
_debugDist = hasTarget ? blockHit.distance : (attackRange - 0.4f);
|
||||||
|
|
||||||
|
// 크로스헤어 이미지 교체
|
||||||
|
if (crosshairUI != null)
|
||||||
|
{
|
||||||
|
crosshairUI.sprite = hasTarget ? targetCrosshair : idleCrosshair;
|
||||||
|
crosshairUI.color = hasTarget ? Color.green : Color.white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateBlockVisuals(bool hasTarget, RaycastHit hit)
|
private void UpdateBlockVisuals(bool hasTarget, RaycastHit hit)
|
||||||
|
|||||||
Reference in New Issue
Block a user