1. 이동시 Rigdoby와 Nav 충돌나는거 수정 2. 데이터 매니저에서 데이터 받아오는것에 대한 방식을 대폭 수정 3. 스폰 컨트롤러 방식 조금 수정 4. 벽과 플레이어 캐릭터 충돌시 미끄러지는 기능 추가(다른 오브젝트와는 테스트 안해 봄) - 캐릭터 컨트롤러에 스테이터스 하는거 손 봐야 함
337 lines
9.4 KiB
C#
337 lines
9.4 KiB
C#
using System;
|
|
using Animation;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using UnityEngine.InputSystem;
|
|
|
|
public partial class PlayerController : MonoBehaviour
|
|
{
|
|
private AnimatorManager<AnimatorParam> _mAnimator;
|
|
private NavMeshAgent _agent;
|
|
private Rigidbody _rigidbody;
|
|
|
|
private Status_Player _status;
|
|
private Vector2 _screenPos;
|
|
|
|
private Vector3 _currentVelocity;
|
|
private Vector3 _velocitySmoothDampRef;
|
|
|
|
private float _runTriggerRatio = 0.6f;
|
|
|
|
[SerializeField] private float _rotationSpeed = 10f;
|
|
|
|
// --- Enum 정의 ---
|
|
enum AnimatorParam
|
|
{
|
|
speed,
|
|
atk_speed,
|
|
attack,
|
|
run,
|
|
}
|
|
|
|
enum PlayerBehavior
|
|
{
|
|
Idle,
|
|
Move,
|
|
Attack,
|
|
Die
|
|
}
|
|
|
|
// rigidbody와 NavMeshAgent를 함께 사용할 때의 물리엔진 상 문제가 생겨서 그거를 구분하기 위한 부분
|
|
// NavMeshAgent가 뇌, rigidbody가 몸 역할을 하게 됨
|
|
public enum ControlMode
|
|
{
|
|
Player,
|
|
AI
|
|
}
|
|
|
|
private ControlMode _controlMode = ControlMode.Player;
|
|
|
|
private PlayerBehavior _behavior = PlayerBehavior.Idle;
|
|
private PlayerBehavior Behavior
|
|
{
|
|
get { return _behavior; }
|
|
set
|
|
{
|
|
_behavior = value;
|
|
switch (_behavior)
|
|
{
|
|
case PlayerBehavior.Die:
|
|
case PlayerBehavior.Idle:
|
|
_mAnimator.SetValue(AnimatorParam.speed, 0);
|
|
break;
|
|
case PlayerBehavior.Move:
|
|
_mAnimator.SetValue(AnimatorParam.attack, false);
|
|
break;
|
|
case PlayerBehavior.Attack:
|
|
_mAnimator.SetValue(AnimatorParam.attack, true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- 초기화 ---
|
|
private void Awake()
|
|
{
|
|
_mAnimator = new AnimatorManager<AnimatorParam>(GetComponent<Animator>());
|
|
_agent = gameObject.GetComponent<NavMeshAgent>();
|
|
_rigidbody = gameObject.GetComponent<Rigidbody>();
|
|
_status = gameObject.GetComponent<Status_Player>();
|
|
_currentVelocity = Vector3.zero;
|
|
|
|
if(_agent != null) _agent.updateRotation = false;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
|
|
Manager.Input.MoveAction -= OnMove;
|
|
Manager.Input.MoveAction += OnMove;
|
|
|
|
SetAnimator();
|
|
|
|
if (_agent != null)
|
|
{
|
|
_agent.updatePosition = false;
|
|
_agent.updateRotation = false;
|
|
}
|
|
|
|
}
|
|
|
|
void SetAnimator()
|
|
{
|
|
if (_status != null)
|
|
{
|
|
_mAnimator.SetValue(AnimatorParam.atk_speed, _status.AtkSpeed);
|
|
}
|
|
}
|
|
|
|
// --- 매 프레임 실행 ---
|
|
void Update()
|
|
{
|
|
if (_controlMode == ControlMode.AI)
|
|
{
|
|
if(_agent.pathPending || !_agent.hasPath) return;
|
|
_rigidbody.linearVelocity = Vector3.zero;
|
|
|
|
// 회전
|
|
if (_agent.desiredVelocity.sqrMagnitude > 0.1f)
|
|
{
|
|
Quaternion targetRotation = Quaternion.LookRotation(_agent.desiredVelocity.normalized);
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * _rotationSpeed);
|
|
}
|
|
|
|
if (_agent.remainingDistance <= _agent.stoppingDistance)
|
|
{
|
|
_rigidbody.linearVelocity = Vector3.zero;
|
|
SetControlMode(ControlMode.Player);
|
|
}
|
|
}
|
|
|
|
// if (_agent != null && _movement != null) _mAnimator.SetValue(AnimatorParam.speed, _movement.GetCurrentSpeed());
|
|
//
|
|
// if (_behavior == PlayerBehavior.Move)
|
|
// {
|
|
// if (!_movement.IsMoving()) Behavior = PlayerBehavior.Idle;
|
|
// else _mAnimator.SetValue(AnimatorParam.speed, _movement.GetCurrentSpeed());
|
|
// }
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if(_agent.enabled) _agent.nextPosition = _rigidbody.position;
|
|
}
|
|
|
|
public void SetControlMode(ControlMode mode)
|
|
{
|
|
_controlMode = mode;
|
|
if (_controlMode == ControlMode.Player) if(_agent != null && _agent.isOnNavMesh) _agent.isStopped = true;
|
|
}
|
|
|
|
void OnInput(Define.InputEvent evt)
|
|
{
|
|
switch (evt)
|
|
{
|
|
case Define.InputEvent.Click:
|
|
break;
|
|
case Define.InputEvent.Down:
|
|
break;
|
|
case Define.InputEvent.Up:
|
|
break;
|
|
case Define.InputEvent.Press:
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void NavigateTo(Vector3 target)
|
|
{
|
|
SetControlMode(ControlMode.AI);
|
|
if (_agent != null)
|
|
{
|
|
_agent.isStopped = false; // 목적지 설정 전 에이전트가 멈춰있지 않도록 합니다.
|
|
_agent.SetDestination(target);
|
|
_agent.speed = _status.MoveSpeed;
|
|
}
|
|
}
|
|
|
|
void OnMove(Vector2 direction)
|
|
{
|
|
SetControlMode(ControlMode.Player);
|
|
|
|
float magnitude = direction.magnitude;
|
|
bool isRun = direction.magnitude > _runTriggerRatio ? true : false;
|
|
float speed = 0f;
|
|
|
|
// 입력이 거의 없을 때
|
|
if (magnitude < 0.1f) speed = 0f;
|
|
// 걷기 구간일 때
|
|
else if (magnitude <= _runTriggerRatio) speed = Mathf.Lerp(0, _status.MoveSpeed, (magnitude/_runTriggerRatio));
|
|
// 달리기 구간일 때
|
|
else
|
|
{
|
|
float runPercentage = (magnitude - _runTriggerRatio) / (1.0f - _runTriggerRatio);
|
|
speed = Mathf.Lerp(_status.MoveSpeed, _status.MoveSpeed * 2.0f, runPercentage);
|
|
}
|
|
|
|
_agent.speed = speed;
|
|
_mAnimator.SetValue(AnimatorParam.run, isRun);
|
|
_mAnimator.SetValue(AnimatorParam.speed , speed);
|
|
|
|
if (magnitude < 0.1f)
|
|
{
|
|
_rigidbody.linearVelocity = Vector3.zero;
|
|
return;
|
|
}
|
|
|
|
// if (direction == Vector2.zero)
|
|
// {
|
|
// if (_agent != null)
|
|
// {
|
|
// _agent.velocity = _currentVelocity;
|
|
// _agent.isStopped = true;
|
|
// }
|
|
// return;
|
|
// }
|
|
|
|
Vector3 camForward = Camera.main.transform.forward;
|
|
Vector3 camRight = Camera.main.transform.right;
|
|
|
|
camForward.y = 0;
|
|
camRight.y = 0;
|
|
camForward.Normalize();
|
|
camRight.Normalize();
|
|
Vector3 moveDir = (camForward * direction.y + camRight * direction.x).normalized;
|
|
|
|
if (moveDir != Vector3.zero)
|
|
{
|
|
Quaternion targetRotation = Quaternion.LookRotation(moveDir);
|
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, _rotationSpeed * Time.deltaTime);
|
|
}
|
|
|
|
_rigidbody.linearVelocity = transform.forward * speed;
|
|
|
|
// if (_agent != null && _status != null)
|
|
// {
|
|
// _agent.isStopped = false;
|
|
// _agent.velocity = moveDir * speed;
|
|
// _agent.velocity = transform.forward * direction.magnitude * speed;
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
private void OnDestroy()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
// void MoveCharacter(Define.InputEvent evt)
|
|
// {
|
|
// if(Behavior == PlayerBehavior.Die) return;
|
|
//
|
|
// Vector3 destination = MeasureDestination();
|
|
//
|
|
// switch (evt)
|
|
// {
|
|
// case Define.InputEvent.Click:
|
|
// case Define.InputEvent.Down:
|
|
// _movement.SetDestination(destination);
|
|
// Behavior = PlayerBehavior.Move;
|
|
// break;
|
|
// case Define.InputEvent.Press:
|
|
// if (Behavior == PlayerBehavior.Move) _movement.SetDestination(destination);
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
// Vector3 MeasureDestination()
|
|
// {
|
|
// RaycastHit hit;
|
|
// Ray ray = Camera.main.ScreenPointToRay(_screenPos);
|
|
//
|
|
// int layerMask = LayerMask.GetMask("Ground");
|
|
// if (!Physics.Raycast(ray, out hit, 100.0f, layerMask))
|
|
// return Vector3.zero;
|
|
//
|
|
// return hit.point;
|
|
// }
|
|
//
|
|
// void OnPoint(Vector2 point)
|
|
// {
|
|
// _screenPos = point;
|
|
// }
|
|
|
|
//
|
|
// void OnMouseClicked(Define.MouseEvent evt)
|
|
// {
|
|
// if (Behavior == PlayerBehavior.Die) return;
|
|
//
|
|
// RaycastHit hit;
|
|
// Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
|
//
|
|
// int layerMask = LayerMask.GetMask("Ground");
|
|
// if (!Physics.Raycast(ray, out hit, 100.0f, layerMask))
|
|
// return;
|
|
//
|
|
// _destPos = hit.point;
|
|
//
|
|
// switch (evt)
|
|
// {
|
|
// case Define.MouseEvent.Click:
|
|
// case Define.MouseEvent.Down:
|
|
// _movement.SetDestination(_destPos);
|
|
// Behavior = PlayerBehavior.Move;
|
|
// break;
|
|
// case Define.MouseEvent.Press:
|
|
// if (Behavior == PlayerBehavior.Move) _movement.SetDestination(_destPos);
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
// void OnKeyboardInput()
|
|
// {
|
|
// // 키보드 입력이 필요할 경우 여기에 로직 구현
|
|
// }
|
|
}
|
|
|
|
// 애니메이션의 이벤트 함수 확인 부분 - 후에 따로 뺄 것
|
|
public partial class PlayerController {
|
|
public void Hit()
|
|
{
|
|
_mAnimator.SetValue(AnimatorParam.attack, false);
|
|
Debug.Log("Knight Hit!");
|
|
}
|
|
|
|
public void FootR()
|
|
{
|
|
|
|
}
|
|
|
|
public void FootL()
|
|
{
|
|
|
|
}
|
|
|
|
}
|