플레이어의 inputVec을 기준으로 사용하다 보니 너무나 많은 경우가 발생한다. 따라서 더 이상 재배치 로직에 플레이어 입력은 제외한다.
이제부터는 두 오브젝트의 위치 차이를 활용한 로직으로 변경, 이제 입력에 상관없이 두 오브젝트의 위치 관계로만 재배치에 적용시켰다.
case "Ground": //collsion의 태그가 ground일 경우
float diffX = playerPos.x - myPos.x; //x축 좌표 차이
float diffY = playerPos.y - myPos.y; //y축 좌표 차이
float dirX = diffX < 0 ? -1 : 1; //player의 inputVec의 x가 음수이다? 진행방이 왼쪽(-1), 아닐경우 오른쪽(1)
float dirY = diffY < 0 ? -1 : 1; //player의 inputVec의 y가 음수이다? 진행방이 아래쪽(-1), 아닐경우 위쪽(1)
diffX = Mathf.Abs(diffX);
diffY = Mathf.Abs(diffY);
if (diffX > diffY) //두 오브젝트의 거리 차이에서 X축이 Y축보다 크면 맵을 수평이동
{
//Translate 지정된 값 만큼 현재 위치에서 이동
transform.Translate(Vector3.right * dirX * 40); //오른쪽 단위 벡터(1, 0, 0) * 방향(왼쪽 -1 , 오른쪽 1) * 크기(40)
//크기가 40인 이유는 타일맵을 4개를 사용해서 2*2로 설정했기 때문
}
else if (diffX < diffY) //두 오브젝트의 거리 차이에서 Y축이 X축보다 크면 맵을 수평이동
{
//Translate 지정된 값 만큼 현재 위치에서 이동
transform.Translate(Vector3.up * dirY * 40);
}
else
{
transform.Translate(dirX * 40, dirY * 40, 0);
}
break;
기존에 diffX, diffY, inputVec을 구하는 코드를 모두 삭제 후 Ground 안에서 따로 계산하도록 변경한다.
이제 더 이상 플레이어의 방향을 구하지 않기 때문에 몬스터 또한 플레이어의 방향이 아닌 로직을 사용해 재배치 시켜주어야한다.
이때 몬스터를 플레이어와 멀어진다면 해당 거리만큼 2배 순간이동해서 배치하면 반대쪽에 배치된다. 이 때 플레이어의 앞쪽에 배치되는데 좀 랜덤하게 배치되도록 ran 벡터를 하나 만들어 벡터에 더해준다.
case "Enemy": //collsion의 태그가 Enemy일 경우
if (coll.enabled) // 콜라이더가 활성화 되어있는지 조건 먼저 작성 - 몬스터가 죽었으면 비활성화 되어있음 => 재배치 필요가 없음
{
Vector3 dist = playerPos - myPos; // 몹 -> 플레이어 벡터가 만들어짐 (이 벡터만큼 몹을 옮기면 플레이어위치, 2배 옮기면 플레이어의 앞쪽에 배치)
Vector3 ran = new Vector3(Random.Range(-3, 3), Random.Range(-3, 3), 0); // 랜덤 벡터를 더하여 퍼져있는 몬스터 재배치 구현
transform.Translate(ran + dist * 2); //
}
break;
근접무기의 관통은 -1로 초기화해줬었는데 원거리가 계속 per가 줄면서 -1이 되버리면 죽지 않고 살아있는 경우가 간혹 발생한다.
따라서 근접무기의 관통을 -100으로 재설정한다.
//Bullet의 Bullet 스크립트의 init 함수로 데미지 관통 초기화
bullet.GetComponent<Bullet>().Init(damage, -100, Vector2.zero); // -1 is Infinity Per. (근접공격은 무한 관통)
EnemyCleanr의 Bullet의 per 값도 -100으로 설정
public void Init(float damage, int per, Vector3 dir)
{
this.damage = damage; //Bullet의 데미지를 매개변수 데미지로 초기화
this.per = per; //Bullet의 관통을 매개변수 관통으로 초기화
if(per >= 0)
{
rigid.velocity = dir * 15f; //속도는 15로 사용
}
}
void OnTriggerEnter2D(Collider2D collision)
{
// 몬스터와 만난게 아니거나, 관통이 무한일 경우 return
if (!collision.CompareTag("Enemy") || per == -100)
return;
per--;
if(per < 0) //per 수치만큼 몬스터를 만나서 0보다 작아지면 삭제
{
rigid.velocity = Vector2.zero;//비활성화 이전에 재사용을 위해 미리 물리 속도 초기화
gameObject.SetActive(false); //비활성화
}
}
투사체가 Area 밖으로 나가면 삭제하도록 OnTriggerExit2D 이벤트를 활용해서 쉽게 비활성화할 수 있다.
void OnTriggerExit2D(Collider2D collision)
{
if (!collision.CompareTag("Area") || per == -100)
return;
gameObject.SetActive(false);
}
기존 레벨을 10초 마다 레벨업 해주는 것을 Spawner 스크립트에 소환 레벨 구간을 결정하는 변수를 선언해주어 기존 하드 코딩 방식을 개선시킨다.
최대 시간에 몬스터 데이터 크기로 나누어 자동으로 구간 시간을 계산하고 해당 구간 시간을 level 업데이트에 적용 시킨다.
public float levelTime;
void Awake()
{
// 배열로 여러개를 가져올 것이기 때문에 Component's'를 써야함
spawnPoint = GetComponentsInChildren<Transform>();
levelTime = GameManager.Instance.maxGameTime / spawnData.Length;
}
void Update()
{
~~(생략)~~
//gameTime을 levelTime으로 나누어서 내림(Floor) 한 후 정수형으로 레벨 지정
level = Mathf.Min(Mathf.FloorToInt(GameManager.Instance.gameTime / levelTime), spawnData.Length - 1);
~~(생략)~~
}
이제 게임매니저의 nextExp로 선언해놨던 경험치로 인스펙터에서 Next Exp를 다시 초기화 시켜준다. 또한 maxGameTime도 5분(300초)로 설정한다.
추후 직접 플레이 해보고 무기 데미지를 조정해 난이도를 조절한다.