어제와 똑같은 에셋을 세팅한다.
그리고 새로운 프리팹을 만들고 P_Flag로 이름을 지정해준 뒤 태그를 Flag 라고 새로 만들고 지정합니다.
그리고 Flag에 스크립트를 넣어둡니다.
Flag.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Flag : MonoBehaviour
{
private MeshRenderer[] mrs = null;
private void Awake()
{
mrs = GetComponentsInChildren<MeshRenderer>();
}
private void SetColors(Color _color)
{
foreach(MeshRenderer mr in mrs)
{
mr.material.SetColor("_Main", _color);
}
}
public void SetSelectedColor()
{
SetColors(Color.yellow);
}
public void SetTouchedColor()
{
SetColors(Color.red);
}
public void ResetColor()
{
SetColors(Color.white);
}
public Vector3 GetPosition()
{
return transform.position;
}
}
이런식으로 각 플래그가 갈수있는곳을 지정해주는 기능을 만드려고한다.
빈 오브젝트를 만들고 FlagPathManager 을 만들어 둡니다. 당연히 동일이름의 스크립트를 만들고 컴포넌트를 넣어줍니다.
그리고 임의로 아무데에나 Flag 프리팹을 만들어둔다
그리고 프리팹 설정 3DObject -> Text Mesh 를 만들면 깃발에 숫자를 구현할수 있다.
짠.
그리고 기존 치킨 프리팹을 가져와서 PathFinder이라는 이름으로 지정하고 스크립트를 만들어줍니다.
Ui-> Text Mesh Pro를 넣어주면 UI를 만들수 있습니다.
과제 : 최단거리,경로로 목표깃발을 찾아가는 알고리즘을 구현
FlagPathManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.Texture2D;
public class FlagPathManager : MonoBehaviour
{
[SerializeField] public PathFinder pathFinder = null;
[SerializeField] private GUIPathList guiPathList = null;
[SerializeField] public Flag startFlag = null;
[SerializeField] public Flag tempFlag = null;
[SerializeField] public Flag endFlag = null;
[SerializeField] private Flag flag = null;
private int i = 0;
private void Awake()
{
/* startFlag = flag.nextFlags[i].transform.name;*/
}
public Flag[] PathFinding()
{
if(startFlag == null || endFlag == null)
{
return null;
}
//startFlag 부터 endFlag 까지 경로 탐색
pathFinder.RaycastProcess(ref pathFinder.destination);
return null;
}
private void Update()
{
}
}
Flag.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using TMPro;
using UnityEditor;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.UI;
using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics;
using static UnityEditor.PlayerSettings;
public class Flag : MonoBehaviour
{
[SerializeField] private int number = 0;
[SerializeField] public Flag[] nextFlags = null;
[SerializeField] public Flag[] flagName = null;
[SerializeField] private bool onDebugMode = true;
[SerializeField] private Color debugLineColor = Color.black;
[SerializeField] private FlagPathManager flagPathManager = null;
[SerializeField] private PathFinder pathFinder = null;
private MeshRenderer[] mrs = null;
private TextMeshPro numberText = null;
private GameObject nowTransform = null;
private MeshRenderer gos = null;
private float[] dist = new float[100];
private static float lastDist = 110;
private string[] flagname = new string[1000];
public bool stopMoving = false;
private void Awake()
{
mrs = GetComponentsInChildren<MeshRenderer>();
numberText = GetComponentInChildren<TextMeshPro>();
gos = GetComponentInChildren<MeshRenderer>();
for (int i = 0; i < 100; i++)
{
dist[i] = 0;
Debug.Log(dist[i]);
}
/* for (int i = 0; i < nextFlags.Length; i++)
{
Flag flag = nextFlags[i];
flagname[i] = transform.name;
startDist[i] = Vector3.Distance(transform.position, flag.transform.position);
Debug.Log(" Next Flag Name " + flag);
}*/
}
private void Start()
{
numberText.text = number.ToString();
/*
for(int i = 0; i < nextFlags.Length; i++)
{
Debug.Log("Flagname : " + flagname[i] + " StadtDist : " + startDist[i]);
}
*/
}
public int GetNumber()
{
return number;
}
private void SetColors(Color _color)
{
foreach(MeshRenderer mr in mrs)
{
mr.material.SetColor("_Main", _color);
}
}
public void SetSelectedColor()
{
SetColors(Color.yellow);
}
public void SetTouchedColor()
{
SetColors(Color.red);
}
public void ResetColor()
{
SetColors(Color.white);
}
public Vector3 GetPosition()
{
return transform.position;
}
private void Update()
{
if (!onDebugMode) return;
foreach (Flag flag in nextFlags)
{
Debug.DrawLine(transform.position, flag.GetPosition(), debugLineColor);
}
/* if (!pathFinder.isMoving)
{
if (flagPathManager.startFlag != null && flagPathManager.endFlag != null)
{
if (flagPathManager.startFlag != flagPathManager.endFlag)
{
for (int i = 0; i < pathFinder.colliders.Length; i++)
{
if (flagPathManager.startFlag.transform.name == pathFinder.colliders[i].transform.name)
{
//Debug.Log("검출 : " + flagPathManager.tempFlag.name);
for (int j = 0; j < nextFlags.Length; j++)
{
if (pathFinder.colliders[i].transform.name == nextFlags[j].transform.name)
{
Moving();
//nextFlag 가 있으면 TempFlag에 저장하고 TempFlag 의 nextFlag가 endFlag와 같으면 동작.
}
else
{
Debug.Log("검출 : " + pathFinder.colliders[i].transform.name);
}
}
}
}
}
}
}*/
if (!pathFinder.isMoving && flagPathManager.startFlag != null && flagPathManager.endFlag != null && flagPathManager.startFlag != flagPathManager.endFlag)
{
for (int i = 0; i < pathFinder.colliders.Length; i++)
{
if (flagPathManager.startFlag.transform.name == pathFinder.colliders[i].transform.name)
{
for (int j = 0; j < nextFlags.Length; j++)
{
if (pathFinder.colliders[i].transform.name == nextFlags[j].transform.name)
{
flagPathManager.tempFlag = transform.gameObject.GetComponent<Flag>();
for (int k = 0; k < nextFlags.Length; k++)
{
shortPath(k);
}
Debug.Log("LastDist검출 : " + lastDist);
Moving();
}
}
}
}
}
}
private void OnTriggerEnter(Collider other)
{
if (gos != null)
{
gos = GetComponentInChildren<MeshRenderer>();
MeshRenderer mr = gos.GetComponentInChildren<MeshRenderer>();
mr.material.SetColor("_Color", Color.white);
}
}
private bool Cal()
{
return true;
}
private void Moving()
{
if (Vector3.Distance(pathFinder.transform.position, flagPathManager.startFlag.transform.position) > 1f && stopMoving == false)
{
pathFinder.MovingToPoint(flagPathManager.startFlag.transform.position);
}
else
{
stopMoving = true;
if (flagPathManager.endFlag.transform.gameObject.name == transform.name && stopMoving == true)
{
if (Vector3.Distance(pathFinder.transform.position, flagPathManager.endFlag.transform.position) > 1f)
{
pathFinder.MovingToPoint(flagPathManager.endFlag.transform.position);
}
}
}
}
private float shortPath(int k)
{
dist[k] = Vector3.Distance(pathFinder.transform.position, flagPathManager.tempFlag.transform.position) + Vector3.Distance(flagPathManager.tempFlag.transform.position, flagPathManager.endFlag.transform.position);
if (dist[k] < lastDist)
{
lastDist = dist[k];
}
else if (dist[k] == lastDist)
{
Debug.Log("LastDist검출 : " + lastDist + "컴포넌트 : " + transform.name);
pathFinder.MovingToPoint(transform.position);
//pathFinder.MovingToPoint(flagPathManager.tempFlag.transform.position);
}
return lastDist;
}
}
PathFinder.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
using static UnityEditor.Experimental.GraphView.GraphView;
using static UnityEditor.PlayerSettings;
using static UnityEngine.Texture2D;
public class PathFinder : MonoBehaviour
{
[SerializeField] private float moveSpeed = 10f;
[SerializeField] private float rotateSpeed = 10.0f;
[SerializeField] private GameObject[] objs = null;
[SerializeField] private Flag flags = null;
[SerializeField] private FlagPathManager flagPathManager = null;
private Flag[] pathList = null;
private Camera mainCam = null;
private Transform pointTr = null;
private GameObject go = null;
private Vector3 pointPos = Vector3.zero;
private LayerMask layer;
private int mask = (1 << 9);
private int i = 0;
public Collider[] colliders = null;
public Collider flag;
public Vector3 destination = Vector3.zero;
public const float stopDistance = 1f;
public bool isMoving = false;
public float radius = 0;
private void Update()
{
Serch();
RaycastProcess(ref destination);
Flag go = PickingProcessC();
if (!isMoving & Input.GetMouseButton(0))
{
if (go != null)
{
flagPathManager.startFlag = PickingProcessC();
transform.position = flagPathManager.startFlag.transform.position;
SetColorAtGO(go, Color.green);
}
}
if (!isMoving & Input.GetMouseButton(1))
{
if (go != null)
{
SetColorAtGO(go,Color.red);
flagPathManager.endFlag = PickingProcessC();
}
}
}
private void Serch()
{
if (flagPathManager.startFlag != null && flagPathManager.endFlag != null)
{
if (flagPathManager.startFlag != flagPathManager.endFlag)
{
colliders = Physics.OverlapSphere(transform.position, radius, mask);
radius = (radius + 150);
}
}
}
public bool RaycastProcess(ref Vector3 _point)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f, mask))
{
Debug.DrawRay(ray.origin, ray.direction * 100f, Color.blue);
_point = hit.point;
return true;
}
return false;
}
public Flag PickingProcessC()
{
mainCam = Camera.main;
Vector3 mousePos = Input.mousePosition;
mousePos.z = mainCam.nearClipPlane;
Vector3 toWorld = mainCam.ScreenToWorldPoint(mousePos);
Vector3 dir = (toWorld - mainCam.transform.position).normalized;
RaycastHit hit;
if (Physics.Raycast(mainCam.transform.position, dir, out hit, 100f, mask))
{
Flag flag = hit.transform.GetComponent<Flag>();
if (flag != null)
{
return flag;
}
}
Debug.DrawRay(mainCam.transform.position, dir, Color.red);
return null;
}
public void MovingToPoint(Vector3 _point)
{
_point.y = transform.position.y;
Vector3 dir = _point - transform.position;
dir.Normalize();
transform.position = transform.position + (dir * moveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, _point) < stopDistance)
{
flagPathManager.startFlag = flagPathManager.tempFlag;
isMoving = false;
}
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * rotateSpeed);
}
private void StartMove(Flag[] _pathList)
{
if (pathList == null || pathList.Length == 0) { return; }
pathList = _pathList;
}
public void SetColorAtGO(Flag _go, Color color)
{
MeshRenderer[] meshRenderers = _go.GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer mr in meshRenderers)
{
foreach (Material mat in mr.materials)
{
mat.SetColor("_Color", color);
}
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, radius);
}
}