【Unity3D】自动寻路的跳跃

来源:互联网 发布:流畅的python epub 编辑:程序博客网 时间:2024/05/16 09:26

《【Unity3D】自动寻路》(点击打开链接)万般好,但锁死Y轴这点导致非常蛋疼的一个问题,我需要在自动寻路的过程允许游戏主角进行跳跃。毕竟玩家都说了,在3D游戏里面不让主角跳跃是一个很严重的问题,就像《阿玛拉王国》本来做得非常好,但就是不能跳,导致大打折扣。那么如果在Unity3D自动寻路的过程中进行跳跃呢?下面举一个例子说明这个问题:


如图所示,假设图中的小球就是我们的主角,我按左键可以让它自动寻路,按右键可以让它跳,同时到了边界还不会出现一堵无形的墙,小球能自然滑落的。

具体制作过程如下所示:

1、一如《【Unity3D】自动寻路》(点击打开链接)拖Plane,整些Cube作障碍体,Sphere做主角,同时设置一个光源,并给这些东西加上材质。然后保存场景,将Plane和Cube设置为Navigation Static,小球加上Nav Mesh Agent和Rigidbody,完成自动寻路的烘培。


2、给小球赋予GameScript.cs如下所示,则完成:

using UnityEngine;using System.Collections;public class GameScript : MonoBehaviour{    private NavMeshAgent navMeshAgent;    private bool is_jumping, out_of_bound;//用于设置小球是否跳跃和已经到达自动寻路边缘的flag    void Start()    {        navMeshAgent = gameObject.GetComponent<NavMeshAgent>();//初始化navMeshAgent          is_jumping = false;        out_of_bound = false;    }    void Update()    {        if (Input.GetMouseButtonDown(0) && !is_jumping && !out_of_bound)        {//如果不是在跳跃、不是到达自动寻路边缘,按下鼠标左键               //自动寻路            Ray mRay = Camera.main.ScreenPointToRay(Input.mousePosition);            RaycastHit mHit;            if (Physics.Raycast(mRay, out mHit))            {                if (mHit.collider.gameObject.name == "Plane")//如果点的是Plane上的一点                {                    this.rigidbody.velocity = new Vector3(0, 0, 0);//这里是考虑到跳跃落地之后,用户马上要自动寻路的情况                    navMeshAgent.SetDestination(mHit.point);                }            }        }        if (Input.GetMouseButtonDown(1) && !is_jumping && !out_of_bound)//按下鼠标右键的话        {            Ray mRay = Camera.main.ScreenPointToRay(Input.mousePosition);            RaycastHit mHit;            if (Physics.Raycast(mRay, out mHit))            {                if (mHit.collider.gameObject.name == "Plane")                {                    navMeshAgent.enabled = false;//取消自动寻路                    is_jumping = true;//让小球进行跳跃                    this.rigidbody.velocity = new Vector3(0, 0, 0);                    this.rigidbody.velocity = mHit.point + new Vector3(0, 5, 0);//基于一个点击位置方向加上y=5的向量速度                }            }        }        if ((this.transform.position.x > 4.6 && this.rigidbody.velocity.x > 0.01) ||            (this.transform.position.x < -4.6 && this.rigidbody.velocity.x < -0.01) ||            (this.transform.position.z > 4.6 && this.rigidbody.velocity.z > 0.01) ||            (this.transform.position.z < -4.6 && this.rigidbody.velocity.z < -0.01))        {//如果已经到了Plane的边缘            out_of_bound = true;            navMeshAgent.enabled = false;//关闭自动寻路        }        if (this.transform.position.y < -3)//如果小球已经掉得太下方        {            Application.LoadLevel("Navmesh_jump");//重新开始        }    }    //小球如果和Plane开始碰撞    void OnCollisionEnter(Collision collision)    {        if (collision.collider.gameObject.name == "Plane" && is_jumping)        {            is_jumping = false;            navMeshAgent.enabled = true;//重新打开自动寻路        }    }}
这里的难点就是因为自动寻路Nav Mesh Agent锁死了Y轴,导致和刚体Rigidbody想在3D世界中自由进行物理运动产生冲突,那么我们在小球需要跳跃的时候就不要这个自动寻路好了,同时自动寻路Nav Mesh Agent一旦小球到达了Plane的边界也会不知道为何会自动产生一股无形的墙,非要小球不能滑落,这里也和刚体Rigidbody产生冲突的,我们也是需要解除自动寻路Nav Mesh Agent,让小球得以滑落。

综上所述,其实来来去去是如果协调好自动寻路Nav Mesh Agent在何时开关的问题。这里在设置两个flag之后,在用户点击右键则让小球进行跳跃状态,执行《【Unity3D】用鼠标点击事件、AddForce完成跳跃与二段跳》(点击打开链接)对跳跃的处理,然后用到《【Unity3D】利用物体碰撞检测、键盘输入处理完成平衡球游戏》(点击打开链接)对碰撞检查的内容,设置进行跳跃状态的小球一旦与Plane碰撞,则重新回到自动寻路的状态。

原创粉丝点击