일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 유니티 GUI
- 유니티 Json 데이터 연동
- Photon Fusion
- meta xr
- Oculus
- 모작
- 개발
- 팀 프로젝트
- HAPTIC
- 멀티플레이
- 포트폴리오
- 오큘러스
- VR
- 오브젝트 풀링
- OVR
- ChatGPT
- 앱 배포
- 연습
- CGV
- meta
- 드래곤 플라이트
- 개발일지
- 유니티
- 유니티 UI
- XR
- 드래곤 플라이트 모작
- input system
- 팀프로젝트
- 길건너 친구들
- 가상현실
Archives
- Today
- Total
EasyCastleUNITY
HeroShooter 개발일지1 본문
https://easycastleunity.tistory.com/135
위에 포스트에 이어서 개발을 해보고자 한다.
위 포스트에서 정리해 두었던 미흡한 점들이다.
1. 몬스터 움직임
몬스터가 따라오는 기능은 Stage3 부터 나오는 기본적인 기능이다.
이 기능은 기본적인 부분은 완성되었고, 벽에 막히는 부분이 문제이기에 이 문제를 먼저 해결하고자 한다.
1.몬스터 움직임
방해물이 있으면 돌아서 접근해야 되는데, 그대로 다가와서 장애물에 부딫친다.
이 문제점을 해결해 볼 생각이다.
MonsterController - 따라오지만 여전히 문제가 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MonsterController : MonoBehaviour
{
//몬스터 애니메이션 enum
private enum eMonsterState
{
Idle,Hit,Die
}
[SerializeField] private int hp = 5; //몬스터 hp
public System.Action onDie; //죽으면 알려주는 대리자
[SerializeField] private GameObject indicator; //선택된 거 표시
[SerializeField] private Transform target; // 플레이어
private Animator anim;
private NavMeshAgent agent;
[SerializeField]
private float speed = 1.0f;
[SerializeField]
private float damping = 10.0f;
private Queue<Vector3> points = new Queue<Vector3>(); //코너 지점을 저장하는 큐
private bool isMoving; //이동중인지 확인
private System.Action onMoveComplete; //이동 완료한지 확인
private int count = 0;
private void Awake()
{
this.anim = this.GetComponent<Animator>();
this.agent = GetComponent<NavMeshAgent>();
if(this.agent !=null) this.agent.updateRotation = false;
}
private void Start()
{
this.onMoveComplete = () => {
if(this.points.Count ==0) //저장된 정보 없음 == 이동이 완료되었다
{
Debug.Log("<color=yellow>MOVE COMPLETE!!!!</color>");
this.CalculatePathToTarget();
}
else //이동 완료가 아니라면
{
Debug.Log("<color=yellow>Move Next!</color>");
//다시 다음 경로 계산
Vector3 pos = this.GetNextPoint();
Vector3 dir = pos - this.transform.position;
DrawArrow.ForDebug(this.transform.position, dir, 10f, Color.red, ArrowType.Solid);
this.StartCoroutine(this.CoMove(pos, dir.normalized));
}
};
//this.Move();
}
private void FixedUpdate()
{
this.Move();
}
private void Move()
{
if(this.count==0) this.CalculatePathToTarget(); //최초 한번만 Move에서 검색
if (this.isMoving == false) //이동중이 아니라면
{
this.isMoving = true;
Vector3 pos = this.GetNextPoint(); // 다음 코너에 대한 위치 정보
Vector3 dir = pos - this.transform.position; //다음 코너까지의 방향
DrawArrow.ForDebug(this.transform.position, dir.normalized, 10f, Color.red, ArrowType.Solid);
this.StartCoroutine(this.CoMove(pos, dir.normalized));
}
this.count = 1;
}
IEnumerator CoMove(Vector3 pos, Vector3 dir)
{
while (true)
{
Quaternion rot = Quaternion.LookRotation(dir.normalized);
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, rot, Time.deltaTime * damping);
this.agent.velocity = dir * this.speed;
float distance = Vector3.Distance(pos, this.transform.position);
if(distance <= this.agent.stoppingDistance)
{
break;
}
yield return null;
}
Debug.Log("move complete");
this.agent.velocity = Vector3.zero;
this.isMoving = false;
this.onMoveComplete(); //대리자 호출
}
private Vector3 GetNextPoint() //저장한 정보 받아오기
{
return this.points.Dequeue();
}
private void CalculatePathToTarget() //타겟 까지의 경로 계산
{
NavMeshPath path = new NavMeshPath(); //길 동적 생성
this.points.Clear(); // 다음 정보들을 위해 클리어
//타갯 까지의 경로를 찾고, 찾은 경로를 path에 저장,
//path를 찾았다면 true를 반환
if (this.agent.CalculatePath(target.position, path))
{
Vector3[] waypoints = path.corners; // 경로의 각 경유지 지점을 배열로 얻음
// waypoints 배열에 있는 지점들을 순회하면서 처리할 수 있음
foreach (Vector3 waypoint in waypoints)
{
Debug.Log("Waypoint: " + waypoint);
this.points.Enqueue(waypoint); //정보 저장
}
this.points.Dequeue(); // 정보 호출, 선입선출
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Bullet"))
{
this.hp--;
this.anim.SetInteger("MonsterState", 1); //hit //아직 미흡
if(this.hp <= 0)
{
this.Die();
}
}
}
public void Die()
{
StartCoroutine(this.CoDie());
//Destroy(this.gameObject);
}
private IEnumerator CoDie()
{
this.anim.SetInteger("MonsterState", 2); //die
yield return new WaitForSeconds(2.0f);
this.onDie();
}
public void HideIndicator()
{
//Debug.Log("선택 마크 숨기기!");
this.indicator.SetActive(false);
}
public void ShowIndicator()
{
//Debug.Log("선택 마크 보여주기!");
this.indicator.SetActive(true);
}
}
이 방법은 SetDestination을 대체하기 위해 만든 방법인데, 한번만 추적하는 것은 그럴듯하게 되지만,
계속 플레이어를 추적하는 것은 도중에 이상한 버그가 생기고 있다.
파악한 바로는, 큐에 저장을 하고 있는 정보가 계속 바뀌면서 생기는 문제가 아닐까 한다.
그래서 큐를 갱신하는 시점을 바꾸었다.
원래는 큐를 갱신하는 시점은 update 마다 계속 갱신되었는데,
처음 한번만 큐를 Move에서 갱신하고 다음부터는, 문제가 일어나는 타이밍이 줄어들었다.
하지만 여전히 같은 문제가 발생하고 있다. 또한 queue의 데이터가 없어지는 문제가 추가로 발견되었다.
따라서 추적 알고리즘은 이와 같은 방법이 아닌, SetDestination 방법을 쓰는 것이 좋다고 생각된다.
'유니티 심화' 카테고리의 다른 글
Hero Shooter 새로운 Input System 활용한 조이스틱 이동 (0) | 2023.09.01 |
---|---|
Hero Shooter new Input System Test (0) | 2023.08.31 |
HeroShooter 중간과정 정리 (0) | 2023.08.29 |
SpaceShooter2D 오브젝트 풀링 응용 (0) | 2023.08.28 |
오브젝트 풀링 연습 (0) | 2023.08.28 |