导航中的路径指示(图片文字不被物体遮挡)
在场景中,新建一个 GameObject,命名为 LineRenderer,并在上面添加一个LineRenderer组件
导入一个箭头的 图片,并修改成精灵图,拖到场景中,调整好合适的精灵图比例,在拖到工程中,作为预制体
选中场景中的 Capsule,添加脚本 ArrowFindPath,赋值 LineRenderer 和 箭头预制体
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ArrowFindPath : MonoBehaviour {
private NavMeshAgent _navPlayer;
private NavMeshPath _navPath;
public float tileSpacing = 0.5f;
public LineRenderer LineGameObject;
public GameObject directionPrefab;
private List<GameObject> arrowList = new List<GameObject>();
void Start () {
_navPlayer = transform.GetComponent<NavMeshAgent>();
_navPath = new NavMeshPath();
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray,out hit,Mathf.Infinity))
{
//print("hit:" + hit.point);
_navPlayer.SetDestination(hit.point);
NavMesh.CalculatePath(transform.position, hit.point, NavMesh.AllAreas, _navPath);
DrawPath(_navPath);
}
}
}
private void DrawPath(NavMeshPath navPath)
{
List<GameObject> arrows = arrowList;
StartCoroutine(ClearArrows(arrows));
arrowList.Clear();
Debug.Log(navPath.corners.Length);
if (navPath.corners.Length<2)
{
print("navPath.corner,Lenth<2");
return;
}
LineGameObject.positionCount = navPath.corners.Length;
Quaternion planerot = Quaternion.identity;
for (int i = 0; i < navPath.corners.Length; i++)
{
LineGameObject.SetPosition(i, navPath.corners[i]);
float distance = 0;
Vector3 offsetVector = Vector3.zero;
if (i<navPath.corners.Length-1)
{
offsetVector = navPath.corners[i + 1] - navPath.corners[i];
planerot = Quaternion.LookRotation(offsetVector);
distance = Vector3.Distance(navPath.corners[i + 1], navPath.corners[i]);
if (distance<tileSpacing)
{
continue;
}
planerot = Quaternion.Euler(90, planerot.eulerAngles.y, planerot.eulerAngles.z);
float newSpacing = 0;
for (int j = 0; j < distance/tileSpacing; j++)
{
newSpacing += tileSpacing;
var normalizedVector = offsetVector.normalized;
var position = navPath.corners[i] + newSpacing * normalizedVector;
GameObject go = Instantiate(directionPrefab, position + Vector3.up, planerot);
arrowList.Add(go);
}
}
else
{
GameObject go = Instantiate(directionPrefab, navPath.corners[i] + Vector3.up, planerot);
arrowList.Add(go);
}
}
}
private IEnumerator ClearArrows(List<GameObject> arrows)
{
if (arrowList.Count==0)
{
yield break;
}
foreach (var arrow in arrows)
{
Destroy(arrow);
}
}
}
文字不被遮挡图片不被遮挡
链接: https://pan.baidu.com/s/1Dk0BdvzFa8FyMu02op-OQw 提取码: k8m3 复制这段内容后打开百度网盘手机App,操作更方便哦
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MapLine : MonoBehaviour
{
private Vector3 startPos = Vector3.one;
private Vector3 endPos = Vector3.one;
private Vector3 rotation = Vector3.zero;
private Material material;
private bool isMove;
private Vector2 moveDir;
private Vector2 resetOffset;
void Awake()
{
isMove = false;
moveDir = new Vector2(0, 0.01f);
resetOffset = new Vector2(0, 100);
material = GetComponent<Renderer>().material;
}
/// <summary>
/// 设置材质的Offset的属性,让箭头移动起来
/// </summary>
private void Update()
{
if (isMove)
{
if (material.mainTextureOffset == resetOffset)
material.mainTextureOffset = moveDir;
material.mainTextureOffset += -moveDir;
}
}
public void SetLine(Vector3 startPos, Vector3 endPos)
{
this.startPos = startPos;
this.endPos = endPos;
transform.localScale = Vector3.one * 0.05f;
transform.position = startPos;
transform.eulerAngles = Vector3.zero;
var scale = transform.localScale;
var lineLong = CalLineLong() * 2;
scale.z = scale.z * lineLong;
transform.localScale = scale;
rotation.y = CalLineAngle();
transform.eulerAngles = rotation;
material.mainTextureScale = new Vector2(1, lineLong);
transform.Translate(0, 0, lineLong / 4, Space.Self);
//因为贴图箭头的方向不对,这里角度纠正,刚刚好 Y + 180
transform.eulerAngles += new Vector3(0, 180, 0);
isMove = true;
}
/// <summary>
/// 计算行军路线长度
/// </summary>
private float CalLineLong()
{
return Mathf.Sqrt(Mathf.Pow(startPos.x - endPos.x, 2) + Mathf.Pow(startPos.z - endPos.z, 2));
}
/// <summary>
/// 计算行军路线角度
/// </summary>
private float CalLineAngle()
{
//斜边长度
float length = Mathf.Sqrt(Mathf.Pow((startPos.x - endPos.x), 2) + Mathf.Pow((startPos.z - endPos.z), 2));
//对边比斜边 sin
float hudu = Mathf.Asin(Mathf.Abs(startPos.z - endPos.z) / length);
float ag = hudu * 180 / Mathf.PI;
//第一象限
if ((endPos.x - startPos.x) >= 0 && (endPos.z - startPos.z >= 0))
ag = -ag + 90;
//第二象限
else if ((endPos.x - startPos.x) <= 0 && (endPos.z - startPos.z >= 0))
ag = ag - 90;
//第三象限
else if ((endPos.x - startPos.x) <= 0 && (endPos.z - startPos.z) <= 0)
ag = -ag + 270;
//第四象限
else if ((endPos.x - startPos.x) >= 0 && (endPos.z - startPos.z) <= 0)
ag = ag + 90;
return ag;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class PlayerArrow : MonoBehaviour {
private NavMeshAgent _navPlayer;
public MapLine Arrow;
void Start () {
_navPlayer = transform.GetComponent<NavMeshAgent>();
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
_navPlayer.SetDestination(hit.point);
Arrow.SetLine(transform.position, hit.point);
}
}
}
}
Shader"Custom/TransparentOverlay"
{
Properties
{
_MainTex("MainTex(RGBA)",2D) = "white" {}
}
SubShader
{
LOD 100
Cull Off Lighting Off ZWrite Off ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"Queue" = "Overlay"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
SetTexture[_MainTex]
}
}
}