[VR] GroundZero 개발
[4Idle - Gazzlers] GameScene 맵 수정
meltingmelvin
2023. 12. 26. 17:45
-현재 GameScene은 동적으로 맵을 생성하는데, 미완성이라 나무만 무작위로 생겨나고 있었다.
- 이를 수정하여
건물들과 램프 등이 생성되도록 수정하려한다.
https://made-myblog.tistory.com/70
-팀원분이 수정해주신 맵을 토대로 GameScene을 수정할 것이다.
-CurvedWorld를 사용하여 지면도 휘어지도록 처리하였다.
- 관련된 오브젝트들의 material이 수정되어야한다.
-빈오브젝트를 생성하고 curvedworld Controller를 부착한다.
-BendType 을 ClassicRunner(Z positive)로 설정하고 Bend Settings 의 Vertical을 -2로 해준다.
-Pivod Point의 Transform에 PlayerCar를 할당한다.
-수정된 structure스크립트를 달아주고 프리팹들마다 type을 다르게 변경해준다.
-Structure Pool Manager에 새로운 프리팹들을 할당해준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
public class EnemyMove : MonoBehaviour
{
public enum eEnemyType
{
Enemy1, Enemy2, Enemy3
}
public eEnemyType enemyType;
public KeyValuePair<int, Transform> target;
protected bool isReady;
public float moveSpeed = 5.5f;
public float rotSpeed = 8f;
public float changeTargetTime = 5f;
public float trackingTargetTime = 2f;
private float elapsedTime = 3f;
public float offset = 0.5f;
public float length = 3.5f;
public int depth = 3;
public Action<int> onChangeTarget;
protected Rigidbody rBody;
private List<Tuple<Ray, bool>> listRays = new List<Tuple<Ray, bool>>();
private Vector3 dir;
private bool isDetected;
private void FixedUpdate()
{
if (!this.isReady) return;
this.Detect();
this.DecideDir();
this.Move();
}
private void Start()
{
this.rBody = this.GetComponent<Rigidbody>();
}
virtual public void Init(Vector3 pos)
{
//..Enemy 위치 지정 후
this.transform.position = pos;
//..활성화(보여주기)
this.gameObject.SetActive(true);
}
virtual public void Detect()
{
this.listRays.Clear();
this.isDetected = false;
Vector3[] pos = new Vector3[] { this.transform.right, -this.transform.right, this.transform.forward };
for (int i = 0; i < pos.Length; i++)
{
Ray ray = new Ray(this.transform.position + Vector3.up * this.offset, pos[i]);
DrawAndHitRay(ray);
}
for (int i = 0; i < 2; i++)
{
this.RecurDrawAndHitRay(pos[i], pos[2], 0);
}
}
virtual public void Move()
{
float curSpeed = this.moveSpeed;
float posZ = this.transform.position.z;
float targetPosZ = this.target.Value.position.z;
if (posZ > targetPosZ + 15)
{
curSpeed = this.moveSpeed * 1.5f;
}
else if (posZ > targetPosZ + 7)
{
curSpeed = this.moveSpeed;
}
else if (posZ > targetPosZ + 3)
{
curSpeed = this.moveSpeed * 0.9f;
}
if (this.isDetected) curSpeed *= 0.8f;
//float velocityY = this.rBody.velocity.y;
//this.rBody.velocity = this.transform.forward * curSpeed;
//this.rBody.velocity += Vector3.up * velocityY;
this.rBody.MovePosition(this.rBody.position + this.transform.forward * curSpeed * Time.fixedDeltaTime);
//Debug.LogFormat("<color=green>curspeed: {0}</color>", curSpeed);
}
virtual public void DecideDir()
{
List<List<Ray>> listNotHitRays = new List<List<Ray>>();
List<Tuple<Ray, bool>> newListRays = listRays.OrderBy(x => Vector3.Distance(x.Item1.direction, this.transform.right)).ToList();
for (int i = 0; i < newListRays.Count; i++)
{
Tuple<Ray, bool> tupleRay = newListRays[i];
if (!tupleRay.Item2)
{
if (listNotHitRays.Count == 0)
{
listNotHitRays.Add(new List<Ray>());
}
listNotHitRays[listNotHitRays.Count - 1].Add(tupleRay.Item1);
if (i < newListRays.Count - 1 && newListRays[i + 1].Item2)
{
listNotHitRays.Add(new List<Ray>());
}
}
}
if (this.isDetected)
{
this.elapsedTime = 0f;
int maxCount = 0;
int maxCountIndex = 0;
for (int i = 0; i < listNotHitRays.Count; i++)
{
if (listNotHitRays[i].Count > maxCount)
{
maxCount = listNotHitRays[i].Count;
maxCountIndex = i;
}
}
this.dir = Vector3.zero;
for (int i = 0; i < listNotHitRays[maxCountIndex].Count; i++)
{
this.dir += listNotHitRays[maxCountIndex][i].direction;
}
this.dir /= maxCount;
this.transform.rotation = Quaternion.Lerp(this.transform.localRotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime);
}
else
{
this.elapsedTime += Time.deltaTime;
if (this.elapsedTime > this.trackingTargetTime)
{
this.dir = this.target.Value.position - this.transform.position;
//Debug.LogFormat("<color=red>{0}</color>", Quaternion.LookRotation(this.dir));
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime * 0.6f);
}
else
this.transform.rotation = Quaternion.Lerp(this.transform.localRotation, Quaternion.LookRotation(this.dir), this.rotSpeed * Time.deltaTime);
}
}
virtual public void RecurDrawAndHitRay(Vector3 pos1, Vector3 pos2, int depth)
{
Ray ray = new Ray(this.transform.position + Vector3.up * this.offset, (pos1 + pos2).normalized);
this.DrawAndHitRay(ray);
if (depth < this.depth)
{
this.RecurDrawAndHitRay(pos1, (pos1 + pos2).normalized, depth + 1);
this.RecurDrawAndHitRay(pos2, (pos1 + pos2).normalized, depth + 1);
}
}
virtual public void DrawAndHitRay(Ray ray)
{
int layerMask = 1 << 3 | 1 << 6 | 1 << 7;
RaycastHit hit;
if (Physics.Raycast(ray, out hit, this.length, layerMask))
{
this.isDetected = true;
Debug.DrawRay(ray.origin, ray.direction.normalized * this.length, Color.red);
this.listRays.Add(new Tuple<Ray, bool>(ray, true));
// Debug.LogFormat("<color=blue>hit</color>: {0}", hit.collider.gameObject);
}
else
{
Debug.DrawRay(ray.origin, ray.direction.normalized * this.length, Color.green);
this.listRays.Add(new Tuple<Ray, bool>(ray, false));
}
}
virtual public void UpdateTargetPos(int idx, Transform targetTrans)
{
this.target = new KeyValuePair<int, Transform>(idx, targetTrans);
if (!isReady)
{
isReady = true;
this.StartCoroutine(this.CoChangeTarget());
}
}
virtual public IEnumerator CoChangeTarget()
{
while (true)
{
yield return new WaitForSeconds(this.changeTargetTime);
this.onChangeTarget(this.target.Key);
}
}
virtual public void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(this.transform.position, 2f);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class EnemyPoolManager : MonoBehaviour
{
public static EnemyPoolManager instance;
//[SerializeField] private GameObject enemyPrefab;
[SerializeField] private GameObject[] arrEnemyPrefabs;
// private List<Enemy1Move> enemyPool = new List<Enemy1Move>();
private List<List<GameObject>> enemyPool = new List<List<GameObject>>();
void Awake()
{
instance = this;
}
private void Start()
{
this.GenerateEnemy();
}
private void GenerateEnemy()
{
// for (int i = 0; i < 2; i++)
for(int i=0;i<this.arrEnemyPrefabs.Length; i++)
{
List<GameObject> list = new List<GameObject>();
for (int j = 0; j < 2; j++)
{
GameObject go = Instantiate(arrEnemyPrefabs[i], this.transform);
go.SetActive(false);
list.Add(go);
//GameObject go = Instantiate(enemyPrefab, this.transform);
//go.SetActive(false);
//enemyPool.Add(go.GetComponent<Enemy1Move>());
}
this.enemyPool.Add(list);
}
}
public GameObject EnableEnemy(int idx)
{
GameObject result = null;
for (int i = 0; i < enemyPool[idx].Count; i++)
{
// Debug.Log(enemyPool[idx][i]);
if (enemyPool[idx][i].activeSelf == false)
{
result = enemyPool[idx][i];
//result.gameObject.SetActive(true);
result.transform.SetParent(null);
break;
}
}
if (result == null)
{
result = Instantiate(arrEnemyPrefabs[idx]);
enemyPool[idx].Add(result);
}
return result;
}
public void DisableEnemy(GameObject enemy)
{
enemy.SetActive(false);
enemy.transform.SetParent(this.transform);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StructureManager : MonoBehaviour
{
private Queue<List<Structure>> qStructures = new Queue<List<Structure>>();
private bool install;
private bool uninstall;
public void InstallStructure(Rail rail)
{
if (!(this.install ^= true)) return;
List<Structure> list = new List<Structure>();
int type = Random.Range((int)Structure.eType.ARCHITECTURE1, (int)Structure.eType.ARCHITECTURE3 + 1);
GameObject go = StructurePoolManager.Instance.EnableStructure(type);
go.transform.position = rail.transform.position;
list.Add(go.GetComponent<Structure>());
int rand = Random.Range(0, 2);
GameObject pole;
if (rand % 2 == 0)
{
pole = StructurePoolManager.Instance.EnableStructure((int)Structure.eType.LAMP);
}
else
{
pole = StructurePoolManager.Instance.EnableStructure(((int)Structure.eType.CLOCK));
}
float[] dirx = new float[] { -1, 1 };
pole.transform.position = rail.transform.position + Vector3.left * dirx[Random.Range(0, dirx.Length)] * Random.Range(5f, 7f) + Vector3.back * Random.Range(1f, 15f);
list.Add(pole.GetComponent<Structure>());
qStructures.Enqueue(list);
}
public void UninstallStructure()
{
if (!(this.uninstall ^= true) || qStructures.Count == 0) return;
List<Structure> list = qStructures.Dequeue();
for (int i = 0; i < list.Count; i++)
{
StructurePoolManager.Instance.DisableStructure(list[i].gameObject);
}
}
}