[유니티][isometric 타일맵 좌표 이동 part.4] 캐릭터 이동 및 빌딩 생성 시 이동불가 처리

bamtoridotori·2021년 8월 29일
0

unity

목록 보기
4/5

캐릭터 이동 및 빌딩 장애물 처리

  • 추후 추가 필요 : 타일 위에 기존 빌딩 존재할 경우 건설 불가 처리 필요
코드를 입력using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
 
public class TestIsometric_4 : MonoBehaviour
{
    public Button moveBtn;
    public Button buildingBtn;
    public int colCount, rowCount;
    public Vector2 startPos;
 
    private GameObject mapTile;
    private Coroutine routine;
    private int tileWidth = 64;
    private int tileHeight = 32;
    private int col = 0; //행
    private int row = 0; //열
 
    private GameObject character;
    private GameObject building;
    private GameObject motherNode;
    private GameObject targetNode;
    private GameObject selectedTile;
 
    private Dictionary<Vector2, GameObject> dicFIndTile = new Dictionary<Vector2, GameObject>();
    private List<GameObject> closeList = new List<GameObject>();
    private List<GameObject> movePositionList = new List<GameObject>();
    
    void Start()
    {
        this.CreateCharacter();
        this.CreateMap();
        this.TileCheck();
 
        this.moveBtn.onClick.AddListener(() =>
        {
            this.FIndNextPos();
        });
        this.buildingBtn.onClick.AddListener(() =>
        {
            this.Createbuilding();
        });
    }
 
    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>().isBlock)
                {
                    this.ClearMap();
                    this.targetNode = hit.collider.gameObject;
                    hit.collider.GetComponent<SpriteRenderer>().color = Color.cyan;
                }
            }
            yield return null;
        }
    }
    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.gameObject.GetComponent<TestTile>().isBlock = true;
                    
                    building.transform.position = hit.collider.gameObject.transform.position;
                    break;
                }
            }
            yield return null;
        }
 
        this.TileCheck();
    }
 
    private void FIndNextPos()
    {
        if (this.routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.FindNextPosImpl());
    }
 
    private IEnumerator FindNextPosImpl()
    {
        while (true)
        {
            var dir = (this.motherNode.transform.position - this.character.transform.position).normalized;
            var nextNode = Vector2.Distance(this.character.transform.position, this.motherNode.transform.position);
            var distance = Vector2.Distance(this.character.transform.position, this.targetNode.transform.position);
 
            this.character.transform.position += dir * 2f * Time.deltaTime;
 
            if (nextNode <= 0.05f)
            {
                if (distance <= 0.05f)
                {
                    Debug.Log("도착");
 
                    this.TileCheck();
                    break;
                }
                
                this.FindNode();
                Debug.Log("다음");
            }
            yield return null;
        }
    }
 
    private void CharacterMovePoint()
    {
        var mother = this.motherNode.GetComponent<TestTile>().vec2;
        var data = this.character.GetComponent<TestTile>().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.character.GetComponent<Animator>().Play("hero_rightdown");
            //Debug.Log(data);
        }
        if (data.x == mother.x && data.y == maxY)
        {
            //Debug.Log("오른쪽위");
            this.character.GetComponent<Animator>().Play("hero_rightup");
            //Debug.Log(data);
        }
        if (data.x == maxX && data.y == mother.y)
        {
            //Debug.Log("왼쪽위");
            this.character.GetComponent<Animator>().Play("hero_leftup");
            //Debug.Log(data);
        }
        if (data.x == mother.x && data.y == motherY)
        {
            //Debug.Log("왼쪽아래");
            this.character.GetComponent<Animator>().Play("hero_leftdown");
            //Debug.Log(data);
        }
    }
 
    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;
 
        this.character.GetComponent<TestTile>().vec2 = mother;
 
        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.movePositionList.Add(tile);
                        }
                        if (data.y == motherY && data.x == mother.x || data.x == mother.x)
                        {
                            this.movePositionList.Add(tile);
                        }
                        
                        this.movePositionList.Remove(motherNode);
                        this.closeList.Add(motherNode);
                        if (!this.closeList.Contains(tile))
                        {
                            tile.GetComponent<SpriteRenderer>().color = Color.grey;
                            this.SetFGH();
                        }
                    }
                }
            }
        }
        this.NextNode();
        this.CharacterMovePoint();
    }
    
    private void NextNode()
    {
        IEnumerable<GameObject> sortNode = this.movePositionList.OrderBy(x => x.GetComponent<TestTile>().f);
        this.selectedTile = sortNode.FirstOrDefault<GameObject>();
        this.motherNode = this.selectedTile;
        this.motherNode.GetComponent<SpriteRenderer>().color = Color.blue;
    }
    
    private void ClearMap()
    {
        Debug.Log("타일초기화");
 
        for (int i = 0; i < colCount; i++)
        {
            for (int j = 0; j < rowCount; j++)
            {
                var tiles = new Vector2(j, i);
 
                var tile = dicFIndTile[tiles];
 
                Debug.LogFormat("{0}       {1}", tile.GetComponent<TestTile>().isBlock, tiles);
 
                tile.GetComponent<SpriteRenderer>().color = Color.white;
            }
        }
        this.closeList.Clear();
        this.targetNode = null;
        this.selectedTile = null;
 
        this.movePositionList.Clear();
    }
 
 
    #region FGH 활성화 비활성화
    private void SetActiveFGH(GameObject tile)
    {
        if (!this.movePositionList.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
    private void SetFGH()
    {
        foreach (var tile in this.movePositionList)
        {
            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;
        }
    }
 
    #region 맵, 타일 생성
    private void CreateCharacter()
    {
        if (this.character == null)
        {
            this.character = Instantiate(Resources.Load<GameObject>("Prefabs/hero"));
 
            this.CreatedCharacter(character, this.startPos.x, this.startPos.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;
                break;
            }
        }
    }
 
    private void CreatedCharacter(GameObject character, float x, float y)
    {
        var vec2 = new Vector2(x, y);
 
        if (character.GetComponentInChildren<TextMesh>())
        {
            character.GetComponentInChildren<TextMesh>().text = string.Format("({0},{1})", x, y);
            this.SetActiveFGH(character);
        }
 
        character.AddComponent<TestTile>();
        character.GetComponent<TestTile>().vec2 = vec2;
 
        var screen = this.MapToScreen(vec2);
 
        var screenPos = Camera.main.ScreenToWorldPoint(new Vector2(screen.x + 512, screen.y + 384 + 100));
 
        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);
 
        if (tileMap.GetComponentInChildren<TextMesh>())
        {
            tileMap.GetComponentInChildren<TextMesh>().text = string.Format("({0},{1})", x, y);
            this.SetActiveFGH(tileMap);
        }
 
        if (vec2 == this.character.GetComponent<TestTile>().vec2)
        {
            this.motherNode = tileMap;
        }
 
        tileMap.AddComponent<TestTile>();
        tileMap.GetComponent<TestTile>().vec2 = vec2;
 
        var screen = this.MapToScreen(vec2);
 
        var screenPos = Camera.main.ScreenToWorldPoint(new Vector2(screen.x + 512, screen.y + 384 + 100));
 
        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);
    }
    #endregion
}
 
하세요
profile
편하게 끄적이는 벨로그이자 개인적인 메모 공간

0개의 댓글