如何实现点击 屏幕 绕过障碍物体到达目的地的自动导航?
step:
1:得到点击的目标位置
2:计算当前位置与目标位置的 方向
3:让游戏物体朝向目标位置
4:向前移动 并且在移动的过程当中不停的检测 是否碰撞都障碍物体 如果碰撞到了
调整游戏物体的移动方向
关键在第四步:
如何调整游戏物体的方向:
1:获得碰撞点的法线方向 hitInfo.normal
2:用游戏物体的方向 加上 法线方向 就得到了 新的方向transform.forward+hitInfo.normal
向量1 是物体的前方向 transform.forward 向量2是 发出射线碰撞后的法线方向 hitInfo.normal 向量3是叠加得到新的移动方向
注意游戏物体是在XZ 平面上移动的 不需要Y轴的方向
所以需要把 碰撞点的法线的Y 值设置为0
代码还是有点问题的 主要是 到达目的地后一直在原地打转 ??
talk is cheap show me the code!
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMove : MonoBehaviour { private Rigidbody rigid; public float moveSpeed = 5.0f; public GameObject sphere; private Vector3 targetPosiiton; // Use this for initialization void Start () { rigid = GetComponent<Rigidbody>(); targetPosiiton = transform.position; } // Update is called once per frame void Update () { RaycastHit hitInfo; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//发射线 得到目标位置 if (Input.GetMouseButtonDown(0)) { Debug.DrawLine(ray.origin,ray.direction*100.0f); if (Physics.Raycast(ray, out hitInfo, 1000.0f,1<<8)) { if (hitInfo.collider.tag == "Ground") { targetPosiiton = hitInfo.point; } } } Vector3 dir = targetPosiiton - transform.position; dir.y = 0.0f;
if (Vector3.Distance(transform.position,targetPosiiton)<1.0f) {//与目标的距离小于1时判断到达了终点 //rigid.e return; } dir.Normalize(); dir = GetNewDir(dir);//不断的发射线检测 物体的前方是否有障碍物 if (dir==Vector3.zero) { return; } Quaternion rot = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Slerp(transform.rotation,rot,5.0f*Time.deltaTime); transform.Translate(transform.forward*moveSpeed*Time.deltaTime,Space.World); } Vector3 GetNewDir(Vector3 dir) { Vector3 newDir=dir; RaycastHit hitInfo; if (Physics.Raycast(transform.position, transform.forward, out hitInfo, 100.0f, 1 << 9)) { if (hitInfo.collider != null) { Vector3 normal=hitInfo.normal; // Debug.Log("normal:"+normal); normal.y = 0.0f; newDir= normal+transform.forward; } } //当没有碰撞上的时候 就是目标的位置 减去当前的位置 然后单位化 return newDir; } }