美文网首页
Unity 2D下的A星寻路算法

Unity 2D下的A星寻路算法

作者: 逗逼熊本熊 | 来源:发表于2017-08-07 00:54 被阅读0次
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityTileMap;

/// <summary>
/// 玩家行为,这里是A星算法的关键核心所在
/// </summary>
public class PlayerBehaviour : MonoBehaviour
{
    private TileMapBehaviour m_tileMap; //地图类     
    private LevelBehaviour m_levelBehaviour;  //地下城的每一层的层类
    private SceneFadeInOut m_sceneFadeInOut;    //Scene淡入淡出类
    private int m_x;      //地图width最大格子数
    private int m_y;      //地图height 最大格子数
    private bool m_walking;      //判断是否主角正在行走

    // Use this for initialization
    //初始化场景里面的各个对象和组件
    private void Start()
    {
        var tileMapGameObject = GameObject.Find("TileMap");      //找到TileMap这个GameObject;
        m_tileMap = tileMapGameObject.GetComponent<TileMapBehaviour>();    //获取Component
        if (m_tileMap == null)    
            Debug.LogError("TileMapBehaviour not found");
        m_levelBehaviour = tileMapGameObject.GetComponent<LevelBehaviour>(); 
        if (m_levelBehaviour == null)
            Debug.LogError("LevelBehaviour not found");
        m_sceneFadeInOut = GameObject.Find("SceneFader").GetComponent<SceneFadeInOut>();
        if (m_sceneFadeInOut == null)
            Debug.LogError("SceneFadeInOut not found");
    }

    // Update is called once per frame
   /// <summary>
   /// per frame check the input!
   /// </summary>
    private void Update()
    {
        ProcessInput();
    }

    private void ProcessInput()
    {
        //不能走到一半改变新的地点,必须等待当前走路完成,这一点需要修订
        if (m_walking)   
            return;

        if (Input.GetKeyDown(KeyCode.UpArrow))
            TryMoveTo(m_x, m_y + 1);
        if (Input.GetKeyDown(KeyCode.DownArrow))
            TryMoveTo(m_x, m_y - 1);
        if (Input.GetKeyDown(KeyCode.RightArrow))
            TryMoveTo(m_x + 1, m_y);
        if (Input.GetKeyDown(KeyCode.LeftArrow))
            TryMoveTo(m_x - 1, m_y);
        if (Input.GetMouseButtonDown(0))
        {
            // we can make this assumption since the TileMap is on position 0, 0
            // TODO create a world coordinate to tile coordinate lookup

            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            var clicked = new Vector2Int((int)ray.origin.x, (int)ray.origin.y);
            m_walking = true;
            StartCoroutine(WalkTo(clicked, .2f));
        }
    }

    // TODO refactor into a reusable "TileWalker" behaviour
    private IEnumerator WalkTo(Vector2Int destination, float stepIntervalSeconds)
    {
        if (m_levelBehaviour.IsWalkeable(destination.x, destination.y))
        {
            var astar = new AStar(m_levelBehaviour);
            var path = astar.Search(new Vector2Int(m_x, m_y), destination).ToList();
            if (path.Count == 0)
            {
                Debug.Log("No path found");
                m_walking = false;
                yield break;
            }

            foreach (var i in path)
            {
                SetTilePosition(i.x, i.y);
                yield return new WaitForSeconds(stepIntervalSeconds);
            }
        }
        m_walking = false;
    }

    private void TryMoveTo(int x, int y)
    {
        if (m_levelBehaviour.IsWalkeable(x, y))
            SetTilePosition(x, y);
    }

    public void SetTilePosition(int x, int y)
    {
        m_x = x;
        m_y = y;
        var tileBounds = m_tileMap.GetTileBoundsWorld(x, y);
        transform.position = new Vector3(tileBounds.xMin, tileBounds.yMin + 1, transform.position.z);

        // If we walk onto the stairs down...
        if (m_levelBehaviour.GetTile(m_x, m_y) == TileType.StairsDown)
            OnStairsDown();
    }

    private void OnStairsDown()
    {
        enabled = false;
        m_sceneFadeInOut.FadeOutThenIn(() =>
            {
                m_levelBehaviour.StartLevel();
                enabled = true;
            });
    }

    //  果然是A星算法
    //  TODO move this class to outer scope and refine logic specifically for grid
    private class AStarGrid : IAStar<Vector2Int>
    {
        public virtual int HeuristicCostEstimate(Vector2Int a, Vector2Int b)
        {
            return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
        }

        public virtual IEnumerable<Vector2Int> GetNeighbourNodes(Vector2Int node)
        {
            for (int y = -1; y <= 1; y++)
            {
                for (int x = -1; x <= 1; x++)
                    yield return new Vector2Int(node.x + x, node.y + y);
            }
        }
    }

    private class AStar : AStarGrid
    {
        private readonly LevelBehaviour m_levelBehaviour;

        public AStar(LevelBehaviour levelBehaviour)
        {
            m_levelBehaviour = levelBehaviour;
        }

        public override IEnumerable<Vector2Int> GetNeighbourNodes(Vector2Int node)
        {
            // only return neighbour tiles that are walkable
            return base.GetNeighbourNodes(node).Where(x => m_levelBehaviour.IsWalkeable(x.x, x.y));
        }
    }
}

相关文章

  • Unity 2D下的A星寻路算法

  • 游戏算法(1):实现AStar寻路算法

    本文从项目从2D项目寻路需求做介绍。实现了Astar的带权宽搜算法。 本文链接游戏算法(1):实现2D寻路算法[h...

  • A星算法

    A星的作用相当于导航用来寻路的,其次是A*算法适合用于2D类型的游戏 A*基本语言 用来不停的遍历身边的点 知...

  • Unity学习笔记——A*寻路算法的应用

    初步了解了一些寻路算法后,本以为dijstra是比较合适的寻路算法,今天仔细看了关于A星寻路算法的教程和视频后,我...

  • A星寻路算法

    1.简述 A星算法就是试图在地图中找到一条最短路径,但不保证一定存在。 任务小猫去找青蛙玩(好TM弱智啊~) 条件...

  • 2018-09-06

    准备面试,重温了一下之前做竞赛用到的一些算法,先来总结一下A星算法吧,这个算法应该是解决寻路问题中最常用的算法之一...

  • A星算法JavaScript实现

    A星算法 介绍 javascript实现A星寻路算法 在游戏中常有需要主角/敌人去移动到某个物品或者追寻敌人的时候...

  • OC实现A星寻路算法

    使用Object-C 实现 A*寻路算法:原理就不多介绍了:代码:https://github.com/hello...

  • Unity 2D Animation——1.骨骼绑定

    1. Unity 2D Animation 的安装 Unity 2D Animation是作为插件包安装到unit...

  • Unity笔记

    Unity3D 官方文档 2D游戏的起始2 2D物理 全局设置与刚体 Unity5.6 2D物理引擎Effecto...

网友评论

      本文标题:Unity 2D下的A星寻路算法

      本文链接:https://www.haomeiwen.com/subject/ntgkzttx.html