Unity实战 RTS3D即时战略游戏开发(五):Navigation Mesh 自动寻路

发表于2017-06-02
评论0 1.9k浏览

这是RTS3D即时战略游戏开发系列的第五篇文章,为单位添加寻路功能。为了能让单位在地图上移动,我们需要知道在哪里点击了鼠标右键,首先要创建新的交互方式,在Interactions文件夹下创建一个RightClickNavigation脚本,暂时不添加方法,我们打开RtsManager脚本,为了能检测到在哪里点击了鼠标右键,首先我们需要知道地形的碰撞体,在RTSManager中添加如下:

public TerrainCollider MapCollider;  

接下来我们还需要一个方法来确定点击了地图哪里,或者哪里都没有点
public Vector3? ScreenPointToMapPosition(Vector2 point)  //带有? 表明它是可空类型,如果没有点击地面则返回Null  
    {  
        var ray = Camera.main.ScreenPointToRay (point);  
        RaycastHit hit;  
        if (!MapCollider.Raycast (ray, out hit, Mathf.Infinity))  
            return null;  
        return hit.point;  
    }  

接下来,我们来修改一下RTSManager的Start方法,选中并操控敌军单位没有任何意义,但是可以选择查看他们的信息,确保不控制的有AI的单位没有Navigation脚本, 修改后如下:
// Use this for initialization  
    void Start () {  
        Current = this;  
        foreach (var p in Players) {  
            foreach (var u in p.StartingUnits)  
            {  
                var go = (GameObject)GameObject.Instantiate(u, p.Location.position, p.Location.rotation);  
                if (!p.IsAi)  
                {  
                    go.AddComponent();  
                }  
            }  
        }  
    }  

 返回到 场景中的Manager中,发现RTSManager脚本中多出了一个叫MapCollider的新字段,将地形信息赋给它,如图:


这样就能够在地图哪里点击右键了,接下来我们要使主角移动了,选择预设DrontUint,为其添加Nav Mesh Agent组件,这个组件可以通过导航网格寻路并移动,添加完后,我们把它的初始值设置一下如图:



然后开始编辑RightClickNavigation脚本,如下:

using UnityEngine;  
using System.Collections;  
public class RightClickNavigation : Interaction {  
    ///   
    /// 在距目的地多远时准备停止移动,  
    /// 使用它的原因是当我们派遣多个单位到统一位置时,他们都会争取到达准确的位置,这不是我们想要,我们需要一个安全距离  
    ///   
    public float RelaxDistance = 5;    
    private NavMeshAgent agent;  
    private Vector3 target = Vector3.zero;//目的地的位置  
    private bool selected = false;//当玩家点击右键事是否要执行选中操作  
    private bool isActive = false; //NavMesh是否启用并控制单位移动  
    public override void Deselect ()  
    {  
        selected = false;  
    }  
    public override void Select ()  
    {  
        selected = true;  
    }  
    ///   
    /// 向目的地导航的方法  
    ///   
    public void SendToTarget()  
    {  
        agent.SetDestination (target);  
        agent.Resume ();  //如果代理定下来了,设置的目的地也不会有作用,所以需要代理恢复移动  
        isActive = true;  
    }  
    // Use this for initialization  
    void Start () {  
        agent = GetComponent ();  //获取当前的NavMeshAgent脚本  
    }  
    // Update is called once per frame  
    void Update () {  
        if (selected && Input.GetMouseButtonDown (1))  //点击右键并被选中  
        {  
            var tempTarget = RtsManager.Current.ScreenPointToMapPosition(Input.mousePosition);  
            if (tempTarget.HasValue)   //我们可能再次点击选中的物体,并且选中的物体也可能为Null  
            {  
                target = tempTarget.Value;  
                SendToTarget();  
            }  
        }  
        if (isActive && Vector3.Distance (target, transform.position) < RelaxDistance)  
        {  
            agent.Stop ();  
            isActive = false;  
        }  
    }  
}  
好了,返回到Unity中,运行就可以发现选中后的单位可以自动寻路了

  Unity实战RTS3D即时战略游戏开发系列:

  Unity实战 RTS3D即时战略游戏开发(一):场景

  Unity实战 RTS3D即时战略游戏开发(二):玩家状态显示

  Unity实战 RTS3D即时战略游戏开发(三):单位选中处理

  Unity实战 RTS3D即时战略游戏开发(四):鼠标管理器

  Unity实战 RTS3D即时战略游戏开发(六):信息显示

  Unity实战 RTS3D即时战略游戏开发(七):HUD的使用小地图显示

  Unity实战 RTS3D即时战略游戏开发(八):HUD的使用单位信息显示

  Unity实战 RTS3D即时战略游戏开发(九):行为管理器Action的使用

  Unity实战 RTS3D即时战略游戏开发(十):可建造地点标示

  Unity实战 RTS3D即时战略游戏开发(十一)AiController

  Unity实战 RTS3D即时战略游戏开发(十二):建造AI、生产AI

  Unity实战 RTS3D即时战略游戏开发(十三):战斗AI的控制

  Unity实战 RTS3D即时战略游戏开发(十四)伤害更新信息显示、销毁单位、爆炸效果

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引