건물 생성 시 가까운 NPC 이동
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class TestProtoType : MonoBehaviour
{
public int colCount, rowCount;
public Vector2[] blockPos;
public Vector2[] characterPos;
public GameObject uiPopup;
public Button buildingBtn;
public Button chracterMoveBtn;
public Button testBtn;
private int tileWidth = 64;
private int tileHeight = 32;
private int col = 0; //행
private int row = 0; //열
private Coroutine routine;
private GameObject mapTile;
private GameObject motherNode;
private GameObject targetNode;
private GameObject selectedTile;
private GameObject selectedBuilding;
private GameObject nearCharacter;
//private TestUIPopup uiPopup;
private Dictionary<Vector2, GameObject> dicFIndTile = new Dictionary<Vector2, GameObject>();
private List<GameObject> openList = new List<GameObject>();
private List<GameObject> closeList = new List<GameObject>();
private List<GameObject> characterList = new List<GameObject>();
private List<GameObject> randomMoveList = new List<GameObject>();
private void Start()
{
this.CreateCharacter();
this.CreateMap();
this.TileCheck();
this.buildingBtn.onClick.AddListener(() =>
{
this.uiPopup.GetComponent<TestUIPopup>().CreateUI();
});
this.chracterMoveBtn.onClick.AddListener(() =>
{
//this.FindNode();
this.FindeTargetNode();
});
this.testBtn.onClick.AddListener(() =>
{
this.FIndNextPos();
});
}
private void FindeTargetNode()
{
if (targetNode != null)
{
while (true)
{
if (targetNode == motherNode)
{
Debug.Log("찾음");
break;
}
this.FindNode();
}
}
else
{
Debug.Log("어디로 가");
}
}
private void FIndNextPos()
{
if (this.routine != null)
{
StopCoroutine(this.routine);
}
this.routine = StartCoroutine(this.FindNextPosImpl());
}
private IEnumerator FindNextPosImpl()
{
for (int i = 1; i < this.closeList.Count; i++)
{
this.nearCharacter.GetComponent<TestCharacter>().vec2 = this.closeList[i - 1].GetComponent<TestTile>().vec2;
this.CharacterMovePoint(this.closeList[i]);
while (true)
{
var dir = (this.closeList[i].transform.position - this.nearCharacter.transform.position).normalized;
var nextNode = Vector2.Distance(this.nearCharacter.transform.position, this.closeList[i].transform.position);
this.nearCharacter.transform.position += dir * 2f * Time.deltaTime;
//Debug.Log(nextNode);
if (nextNode <= 0.03f)
{
//Debug.Log("다음");
break;
}
yield return null;
}
var distance = Vector2.Distance(this.nearCharacter.transform.position, this.targetNode.transform.position);
//Debug.Log(distance);
if (distance <= 0.04f)
{
this.nearCharacter.GetComponent<TestCharacter>().vec2 = this.targetNode.GetComponent<TestTile>().vec2;
Debug.Log("도착");
this.nearCharacter.gameObject.SetActive(false);
this.ClearMap();
yield return new WaitForSeconds(4);
this.nearCharacter.gameObject.SetActive(true);
this.nearCharacter.GetComponent<Animator>().Play("hero_idle2");
this.nearCharacter = null;
break;
}
}
}
private void CharacterMovePoint(GameObject tile)
{
var mother = tile.GetComponent<TestTile>().vec2;
var data = this.nearCharacter.GetComponent<TestCharacter>().vec2;
var motherX = mother.x - 1;
var motherY = mother.y - 1;
var maxX = mother.x + 1;
var maxY = mother.y + 1;
if (data.x == motherX && data.y == mother.y)
{
//Debug.Log("오아");
this.nearCharacter.GetComponent<Animator>().Play("hero_rightdown");
}
if (data.x == mother.x && data.y == maxY)
{
//Debug.Log("오위");
this.nearCharacter.GetComponent<Animator>().Play("hero_rightup");
}
if (data.x == maxX && data.y == mother.y)
{
//Debug.Log("왼위");
this.nearCharacter.GetComponent<Animator>().Play("hero_leftup");
}
if (data.x == mother.x && data.y == motherY)
{
//Debug.Log("왼아");
this.nearCharacter.GetComponent<Animator>().Play("hero_leftdown");
}
}
private void FindNode()
{
var mother = this.motherNode.GetComponent<TestTile>().vec2;
var motherX = mother.x - 1;
var motherY = mother.y - 1;
var maxX = mother.x + 1;
var maxY = mother.y + 1;
if (motherX < 0)
{
motherX = 0;
}
if (motherY < 0)
{
motherY = 0;
}
for (int x = (int)motherX; x <= maxX; x++)
{
for (int y = (int)motherY; y <= maxY; y++)
{
if (x < this.colCount && y < this.rowCount)
{
var data = new Vector2(x, y);
var tile = this.dicFIndTile[data];
if (tile.GetComponent<TestTile>().isBlock != true && !this.closeList.Contains(tile))
{
if (data.x == motherX && data.y == mother.y || data.y == mother.y)
{
this.openList.Add(tile);
this.SetFGH(tile);
}
if (data.y == motherY && data.x == mother.x || data.x == mother.x)
{
this.openList.Add(tile);
this.SetFGH(tile);
}
this.openList.Remove(motherNode);
this.closeList.Add(motherNode);
if (!this.closeList.Contains(tile))
{
tile.GetComponent<SpriteRenderer>().color = Color.grey;
this.SetActiveFGH(tile);
}
}
}
}
}
foreach (var datas in openList)
{
datas.GetComponent<SpriteRenderer>().color = Color.grey;
}
this.NextNode();
this.closeList.Add(motherNode);
}
private void SetFGH(GameObject tile)
{
var tileScript = tile.GetComponent<TestTile>();
var getG = tile.GetComponent<TestTile>().g;
var getH = tile.GetComponent<TestTile>().h;
getG = Mathf.Round(Vector2.Distance(tile.GetComponent<TestTile>().vec2, this.motherNode.GetComponent<TestTile>().vec2) * 10);
var dx = Mathf.Abs(tile.GetComponent<TestTile>().vec2.x - this.targetNode.GetComponent<TestTile>().vec2.x);
var dy = Mathf.Abs(tile.GetComponent<TestTile>().vec2.y - this.targetNode.GetComponent<TestTile>().vec2.y);
getH = (dx + dy) * 10;
tile.GetComponent<TestTile>().f = getG + getH;
tileScript.G.text = getG.ToString();
tileScript.H.text = getH.ToString();
tileScript.F.text = tile.GetComponent<TestTile>().f.ToString();
}
private void NextNode()
{
this.motherNode.GetComponent<SpriteRenderer>().color = Color.blue;
if (this.targetNode != this.motherNode)
{
IEnumerable<GameObject> sortNode = this.openList.OrderBy(x => x.GetComponent<TestTile>().f);
this.selectedTile = sortNode.FirstOrDefault<GameObject>();
this.motherNode = this.selectedTile;
}
else
{
Debug.Log("찾았다");
}
}
#region 타일초기화
private void ClearMap()
{
Debug.Log("타일초기화");
this.openList.Clear();
this.closeList.Clear();
this.targetNode = null;
this.selectedTile = null;
//this.nearCharacter = null;
this.motherNode = null;
for (int i = 0; i < colCount; i++)
{
for (int j = 0; j < rowCount; j++)
{
var tiles = new Vector2(j, i);
var tile = dicFIndTile[tiles];
if (!tile.GetComponent<TestTile>().isBlock)
{
tile.GetComponent<TestTile>().isBlock = false;
this.SetActiveFGH(tile);
tile.GetComponent<SpriteRenderer>().color = Color.white;
}
//Debug.LogFormat("{0}{1}", tile.GetComponent<TestTile>().isBlock, tile.GetComponent<TestTile>().vec2);
}
}
}
#endregion
void TileCheck()
{
if (this.routine != null)
{
StopCoroutine(this.routine);
}
this.routine = StartCoroutine(this.TileCheckImpl());
}
IEnumerator TileCheckImpl()
{
while (true)
{
if (Input.GetMouseButtonDown(0))
{
Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPos, Vector2.zero);
if (hit.collider != null && hit.collider.GetComponent<TestTile>().isBuilding)
{
Debug.Log("??");
//hit.collider.gameObject.GetComponentInChildren<Button>().onClick.AddListener(() =>
//{
// //var buildingPopupMenu = Instantiate(Resources.Load("Prefabs/BuildingPopup") as GameObject);
//});
}
}
yield return null;
}
}
#region 마우스 클릭 시 빌딩생성
public void CreateBuilding()
{
if (routine != null)
{
StopCoroutine(this.routine);
}
this.routine = StartCoroutine(this.CreatebuildingImpl());
}
private IEnumerator CreatebuildingImpl()
{
var building = Instantiate(Resources.Load<GameObject>("Prefabs/isoTile"));
while (true)
{
Vector2 ray = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero);
building.transform.position = ray;
if (Input.GetMouseButtonDown(0))
{
if (hit.collider == null || hit.collider.GetComponent<TestTile>().isBlock || hit.collider.GetComponent<TestTile>().isBuilding == true)
{
Debug.Log("응 안돼~");
}
else
{
this.selectedBuilding = hit.collider.gameObject;
this.targetNode = hit.collider.gameObject;
hit.collider.gameObject.GetComponent<TestTile>().isBuilding = true;
this.FindNearCharacterNode();
building.transform.position = hit.collider.gameObject.transform.position;
break;
}
}
yield return null;
}
}
#endregion
#region 주변캐릭터 탐색
private void FindNearCharacterNode()
{
foreach (var characters in this.characterList)
{
var character = characters.GetComponent<TestCharacter>().vec2;
//Debug.Log(character);
var characterX = character.x - 1;
var characterY = character.y - 1;
var maxX = character.x + 1;
var maxY = character.y + 1;
if (characterX < 0)
{
characterX = 0;
}
if (characterY < 0)
{
characterY = 0;
}
for (int x = (int)characterX; x <= maxX; x++)
{
for (int y = (int)characterY; y <= maxY; y++)
{
if (x < this.colCount && y < this.rowCount)
{
var data = new Vector2(x, y);
var nearNode = this.dicFIndTile[data];
var getG = characters.GetComponent<TestCharacter>().g;
var getH = characters.GetComponent<TestCharacter>().h;
//다음 타일까지의 이동비용
getG = Mathf.Round(Vector2.Distance(characters.GetComponent<TestCharacter>().vec2, nearNode.GetComponent<TestTile>().vec2) * 10);
//최종목적지점까지의 예상이동비용
var dx = Mathf.Abs(characters.GetComponent<TestCharacter>().vec2.x - this.selectedBuilding.GetComponent<TestTile>().vec2.x);
var dy = Mathf.Abs(characters.GetComponent<TestCharacter>().vec2.y - this.selectedBuilding.GetComponent<TestTile>().vec2.y);
getH = (dx + dy) * 10;
characters.GetComponent<TestCharacter>().f = getG + getH;
}
}
}
}
//F값이 제일 적은 캐릭터
var sortCharacterF = this.characterList.OrderBy(x => x.GetComponent<TestCharacter>().f);
this.nearCharacter = sortCharacterF.FirstOrDefault<GameObject>();
//캐릭터의 키값으로 타일 찾고 마더로
this.motherNode = this.dicFIndTile[nearCharacter.GetComponent<TestCharacter>().vec2];
}
#endregion
#region FGH 활성화 비활성화
private void SetActiveFGH(GameObject tile)
{
if (!this.openList.Contains(tile))
{
tile.GetComponent<TestTile>().G.gameObject.SetActive(false);
tile.GetComponent<TestTile>().F.gameObject.SetActive(false);
tile.GetComponent<TestTile>().H.gameObject.SetActive(false);
}
else
{
tile.GetComponent<TestTile>().G.gameObject.SetActive(true);
tile.GetComponent<TestTile>().F.gameObject.SetActive(true);
tile.GetComponent<TestTile>().H.gameObject.SetActive(true);
}
}
#endregion
#region 맵, 타일, 캐릭터 생성
//캐릭터 생성입력
private void CreateCharacter()
{
var character = Instantiate(Resources.Load<GameObject>("Prefabs/hero"));
var character1 = Instantiate(Resources.Load<GameObject>("Prefabs/hero"));
var character2 = Instantiate(Resources.Load<GameObject>("Prefabs/hero"));
this.CreatedCharacter(character, this.characterPos[0].x, this.characterPos[0].y);
this.CreatedCharacter(character1, this.characterPos[1].x, this.characterPos[1].y);
this.CreatedCharacter(character2, this.characterPos[2].x, this.characterPos[2].y);
}
//맵생성입력
private void CreateMap()
{
while (true)
{
this.mapTile = Instantiate(Resources.Load<GameObject>("Prefabs/tile"));
this.mapTile.tag = "Tile";
this.mapTile.transform.SetParent(this.transform);
this.CreatedMap(this.mapTile, this.col, row);
this.dicFIndTile.Add(new Vector2(col, row), mapTile);
this.col++;
if (this.col >= this.colCount)
{
this.col = 0;
this.row++;
}
if (this.row >= this.rowCount)
{
row = 0;
this.WorldToCenterCamera();
break;
}
}
}
//캐릭터생성
private void CreatedCharacter(GameObject character, float x, float y)
{
var vec2 = new Vector2(x, y);
character.AddComponent<TestCharacter>();
character.GetComponent<TestCharacter>().vec2 = vec2;
this.characterList.Add(character);
var screen = this.MapToScreen(vec2);
var screenPos = Camera.main.ScreenToWorldPoint(new Vector2(screen.x, screen.y));
character.transform.position = new Vector3(screenPos.x, screenPos.y, 0);
}
//맵생성
private void CreatedMap(GameObject tileMap, float x, float y)
{
var vec2 = new Vector2(x, y);
tileMap.AddComponent<TestTile>();
tileMap.GetComponent<TestTile>().vec2 = vec2;
if (tileMap.GetComponentInChildren<TextMesh>())
{
tileMap.GetComponentInChildren<TextMesh>().text = string.Format("({0},{1})", x, y);
this.SetActiveFGH(tileMap);
}
foreach (var chracter in this.characterList)
{
if (chracter.GetComponent<TestCharacter>().vec2 == tileMap.GetComponent<TestTile>().vec2)
{
this.motherNode = tileMap;
}
}
for (int a = 0; a < this.blockPos.Length; a++)
{
if (vec2 == this.blockPos[a])
{
tileMap.name = "block";
tileMap.GetComponent<SpriteRenderer>().color = Color.red;
tileMap.GetComponent<TestTile>().isBlock = true;
}
}
var screen = this.MapToScreen(vec2);
var screenPos = Camera.main.ScreenToWorldPoint(new Vector2(screen.x, screen.y));
tileMap.transform.position = new Vector3(screenPos.x, screenPos.y, 0);
}
//맵포지를 스크린포지로
public Vector2 MapToScreen(Vector2 mapPos)
{
var screenX = mapPos.x * this.tileWidth - (mapPos.y * this.tileWidth);
var screenY = mapPos.y * -tileHeight - (mapPos.x * tileHeight);
return new Vector2(screenX, screenY);
}
//카메라를 타일의 센터로
private void WorldToCenterCamera()
{
var pos = new Vector2(this.colCount / 2 - 1, this.rowCount / 2 - 1);
var posX = this.dicFIndTile[pos].transform.position.x;
var posY = this.dicFIndTile[pos].transform.position.y;
Camera.main.transform.localPosition = new Vector3(posX, posY, -100);
Camera.main.orthographicSize = this.rowCount / 2;
}
#endregion
}