137 lines
3.9 KiB
C#
137 lines
3.9 KiB
C#
// Anchor 방식 리팩토링
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class WeaponController : MonoBehaviour, IObservable<GameObject>
|
|
{
|
|
[SerializeField] private Transform[] triggerAnchors;
|
|
[SerializeField] private float triggerRadius = 0.5f;
|
|
[SerializeField] private LayerMask targetLayerMask;
|
|
|
|
private List<IObserver<GameObject>> _observers = new List<IObserver<GameObject>>();
|
|
|
|
private int attackPower = 1;
|
|
private int _comboStep = 1;
|
|
public int AttackPower => _comboStep == 4 ? attackPower * 4 : attackPower;
|
|
|
|
private PlayerController _playerController;
|
|
private bool _isAttacking = false;
|
|
public bool IsAttacking => _isAttacking;
|
|
|
|
private Vector3[] _previousPositions;
|
|
private HashSet<Collider> _hitColliders;
|
|
private Ray _ray = new Ray();
|
|
private RaycastHit[] _hits = new RaycastHit[10];
|
|
|
|
private void Start()
|
|
{
|
|
if (triggerAnchors == null || triggerAnchors.Length == 0)
|
|
{
|
|
Debug.LogWarning("Trigger Anchors가 비어있습니다.");
|
|
return;
|
|
}
|
|
|
|
_playerController = GetComponent<PlayerController>();
|
|
if (_playerController == null)
|
|
{
|
|
var player = GameObject.FindGameObjectWithTag("Player");
|
|
if (player != null)
|
|
{
|
|
_playerController = player.GetComponent<PlayerController>();
|
|
}
|
|
}
|
|
|
|
_previousPositions = new Vector3[triggerAnchors.Length];
|
|
_hitColliders = new HashSet<Collider>();
|
|
}
|
|
|
|
public void AttackStart()
|
|
{
|
|
_isAttacking = true;
|
|
_hitColliders.Clear();
|
|
StopAllCoroutines();
|
|
StartCoroutine(AutoEndAttack());
|
|
|
|
for (int i = 0; i < triggerAnchors.Length; i++)
|
|
{
|
|
_previousPositions[i] = triggerAnchors[i].position;
|
|
}
|
|
}
|
|
|
|
private IEnumerator AutoEndAttack()
|
|
{
|
|
yield return new WaitForSeconds(0.6f);
|
|
if (_isAttacking) AttackEnd();
|
|
}
|
|
|
|
public void AttackEnd() => _isAttacking = false;
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (!_isAttacking) return;
|
|
|
|
for (int i = 0; i < triggerAnchors.Length; i++)
|
|
{
|
|
var current = triggerAnchors[i].position;
|
|
var direction = current - _previousPositions[i];
|
|
|
|
if (direction.magnitude < 0.01f) continue;
|
|
|
|
_ray.origin = _previousPositions[i];
|
|
_ray.direction = direction;
|
|
|
|
int hitCount = Physics.SphereCastNonAlloc(_ray, triggerRadius, _hits, direction.magnitude, targetLayerMask);
|
|
for (int j = 0; j < hitCount; j++)
|
|
{
|
|
var hit = _hits[j];
|
|
if (!_hitColliders.Contains(hit.collider))
|
|
{
|
|
_hitColliders.Add(hit.collider);
|
|
Notify(hit.collider.gameObject);
|
|
}
|
|
}
|
|
|
|
_previousPositions[i] = current;
|
|
}
|
|
}
|
|
|
|
public void Subscribe(IObserver<GameObject> observer)
|
|
{
|
|
if (!_observers.Contains(observer)) _observers.Add(observer);
|
|
}
|
|
|
|
public void Unsubscribe(IObserver<GameObject> observer) => _observers.Remove(observer);
|
|
|
|
public void Notify(GameObject value)
|
|
{
|
|
foreach (var o in _observers) o.OnNext(value);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
var copyObservers = new List<IObserver<GameObject>>(_observers);
|
|
foreach (var observer in copyObservers)
|
|
{
|
|
observer.OnCompleted();
|
|
}
|
|
_observers.Clear();
|
|
}
|
|
|
|
public void SetComboStep(int step) => _comboStep = step;
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnDrawGizmos()
|
|
{
|
|
if (triggerAnchors == null) return;
|
|
Gizmos.color = Color.green;
|
|
foreach (var anchor in triggerAnchors)
|
|
{
|
|
if (anchor != null)
|
|
Gizmos.DrawWireSphere(anchor.position, triggerRadius);
|
|
}
|
|
}
|
|
#endif
|
|
}
|