기존에 R&D 해놨던 오브젝트 풀링으로 적 생성 구현한 것을 토대로 본 프로젝트에서 구현해보자
using System.Collections;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public List<Transform> points = new List<Transform>();
public List<GameObject> enemyPool = new List<GameObject>();
public GameObject enemyPrefab;
public int maxEnemys = 3;
public float createTime = 3.0f;
private bool IsFirst = true;
void Start()
{
this.CreateEnemyPool();
Transform spawnPointGroup = GameObject.Find("SpawnPointGroup")?.transform;
foreach (Transform point in spawnPointGroup)
{
this.points.Add(point);
}
InvokeRepeating("CreateEnemy", 2.0f, this.createTime);
}
private void CreateEnemy()
{
//처음에 한꺼번에 세개 생성될 때
if (IsFirst == true)
{
for (int idx = 0; idx < points.Count; idx++)
{
GameObject enemyGo = GetEnemyInPool();
enemyGo?.transform.SetPositionAndRotation(points[idx].position, points[idx].rotation);
enemyGo?.SetActive(true);
IsFirst = false;
Debug.Log("처음");
}
}
//한개씩 생성
else
{
GameObject enemyGo = GetEnemyInPool();
if (enemyGo != null)
{
var enemyRbody = enemyGo.GetComponent<Rigidbody>();
var enemyColl = enemyGo.GetComponent<SphereCollider>();
enemyRbody.useGravity = false;
enemyColl.enabled = true;
enemyGo.transform.SetPositionAndRotation(enemyGo.transform.position, enemyGo.transform.rotation);
enemyGo.SetActive(true);
}
}
}
private void CreateEnemyPool()
{
for (int i = 0; i < this.maxEnemys; i++)
{
var enemyGo = Instantiate<GameObject>(enemyPrefab);
enemyGo.SetActive(false);
enemyPool.Add(enemyGo);
}
}
public GameObject GetEnemyInPool()
{
foreach (var enemy in enemyPool)
{
if (enemy.activeSelf == false)
{
return enemy;
}
}
return null;
}
}
결과
몇가지 문제점이 발생했다.
1. 적을 공격하는 도중에 이미 죽은 적이 생성되면 그 적도 공격하고 돌아온다.
2. 적이 모두 생성되지 않은 상태에서 다시 공격하면 정해진 순서대로 적이 생성되기 때문에 마지막 순서의 적은 생성이 되질 않는다.(모두 unactive인 상태에서 ,공격 받은 순서대로 active되지 않고 풀에 저장된 순서대로 active된다.)
첫번째 문제점의 경우에는 적이 생성되고-> 앞으로 다가오는데, 적이 생성되는 위치는 공격 사거리를 벗어나기 때문에 해결 가능할 것 같다.
두번째 문제점의 경우는 오브젝트 풀링으로 구현해서
이미 맞고 죽은 애를 다시 살리니, 여러 문제들이 발생했다, collider에 부딪혀서 죽으니 새로 생성되고 그 영향으로 떨린다던가 등.. => 그냥 instantiate해서 새로 생성하기로 결정했다.
수정된 코드
using System.Collections;
using System.Collections.Generic;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject enemyPrefab;
private GameObject[] enemyGo;
[SerializeField]
private Transform[] points;
void Start()
{
}
private void Update()
{
this.enemyGo=GameObject.FindGameObjectsWithTag("Enemy");
this.CreateEnemy();
}
private void CreateEnemy()
{
if (this.enemyGo.Length==0 )
{
//적 생성
for (int i = 0; i < 3; i++)
{
Debug.Log("적 생성해라");
Instantiate(this.enemyPrefab, this.points[i].position,Quaternion.identity);
}
}
}
}
using Palmmedia.ReportGenerator.Core.Reporting.Builders;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
public class AerialEnemy : MonoBehaviour
{
private Rigidbody rBody;
private SphereCollider parentCollider;
[SerializeField]
private SphereCollider childCollider;
private Coroutine coroutine;
private void Start()
{
this.rBody = this.gameObject.GetComponent<Rigidbody>();
this.parentCollider = this.gameObject.GetComponent<SphereCollider>();
this.rBody.useGravity = false;
this.Move();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Shield"))
{
Destroy(this.gameObject, 2f);
this.rBody.useGravity = true; //바닥으로 떨어지게
this.parentCollider.enabled = false;
this.childCollider.enabled = true;
}
}
public void Move()
{
if (this.coroutine != null) StopCoroutine(this.coroutine);
this.coroutine = this.StartCoroutine(this.CoMove());
}
public IEnumerator CoMove()
{
var position = this.transform.position+ new Vector3(Random.Range(-0.8f, 0.8f), Random.Range(-0.5f, 1.0f), Random.Range(-10f, -3.5f));
Debug.LogFormat("<color=red>position:{0}</color>", position);
while (true)
{
this.transform.LookAt(position);
this.transform.Translate(Vector3.forward * 4f * Time.deltaTime);
var dis = Vector3.Distance(position, this.transform.position);
if (dis < 0.2f)
break;
yield return null;
}
}
}
코드도 훨씬 줄어들었다.
3마리-> 3마리 -> 2마리 생성 후 더이상 생성되지 않기
private void CreateEnemy()
{
if (this.enemyGo.Length == 0)
{
if (enemyNum < 6)
{
//적 3마리 생성
for (int i = 0; i < 3; i++)
{
Debug.Log("적 생성해라");
Instantiate(this.aerialEnemyPrefab, this.points[i].position, Quaternion.identity);
enemyNum++;
}
}
else if (enemyNum >= 6 && enemyNum < 8)
{
//2마리 생성
for (int i = 0; i < 2; i++)
{
Instantiate(this.aerialEnemyPrefab, this.points[i].position, Quaternion.identity);
enemyNum++;
}
}
else
{
//더이상 생성하지 X
//인디케이터 생성
return;
}
}
}
코드가 넘나 더럽긴 하지만 되긴 됨...
'마블 VR 프로젝트 제작' 카테고리의 다른 글
[마블 VR] 방패 던지기 다듬기 (1) | 2023.12.21 |
---|---|
[마블 VR] 공중 적 이동/공격/피격 (1) | 2023.12.20 |
[마블 VR] Oculus 씬전환 fadein, fade out (1) | 2023.12.18 |
[마블 VR] 방패 던지기 회전 구현 (0) | 2023.12.13 |
[마블 VR] 공중적 레이저 발사/방패 막기 버그 수정 (0) | 2023.12.12 |