Notifications
Article
[原创] Unity简单地图循环长箭头实现
Published 6 months ago
487
10
--- 转自玄猫大人发表于Unity中国论坛
最近在做大地图,行军导航过程中会试用到导向箭头,这里整理下实现的过程。
思路分解
  1. 地图上会有很多这种指向的箭头,同时长度是不固定的,需要根据不同的起始点和终点进行计算角度和方向
  2. 长度在Unity中可以通过scale进行控制
  3. 需要重复的箭头,要实现图片平铺的效果,这里就有一个Tiling的概念
  4. 如果需要移动,可以使用材质的Offset属性
  5. 选择角度计算过程中,需要考虑到四个象限的不同情况
  6. 箭头显示要在最上层,不能被地表的物体遮挡
看到这些思路你们能实现的出来吗?不卖官司,接着往下看。
具体实现
原料:
Plane一只,做2D的时候用Sprite原理也是一样的;
箭头图片一张;
Shader文件一个;
材质球一枚;
CS文件一个;
操作步骤:
1.先处理材质球,新建一个Shader,命名为TransparentOverlay,具体代码如下:
Shader"Custom/TransparentOverlay" { Properties { _MainTex ("MainTex(RGBA)",2D) = "white" {} } SubShader { LOD 100 Cull Off Lighting Off ZWrite Off ZTestAlways Blend SrcAlpha OneMinusSrcAlpha Tags { "Queue" ="Overlay" "IgnoreProjector" ="True" "RenderType" ="Transparent" } Pass { SetTexture[_MainTex] } } }
2.利用该Shader创建一个材质球,将箭头图片赋给材质球
3.在场景中新建一个Plane,将材质球赋个Plane,调整Plane到你需要的尺寸,做成预制件
4.新建一个C#脚本,代码有点长,直接看注释咯,需要额外说的是,计算长度和角度公式大致如下,在其他地方使用的时候还是要根据当前场景的相机,地图大小等等进行相应的微调。
usingUnityEngine; ///<summary> /// 行军路线 ///</summary> public classMapLine : 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 = newVector2(1, lineLong); transform.Translate(0,0,lineLong / 4,Space.Self); 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; } }
5.将脚本附加到预制件中,通过设置SetLine方法设置起点和终点就可以在地图上画箭头了。
PS:写代码还是要学好数学呀,不做都不知道象限是个啥,顺路复习初中数学
Tags:
Jason like
Designer
12
Comments
h
hua.guo+1@unity3d.com
Staff
4 months ago
花花hello
京津冀
0
Jason like
Staff
4 months ago
花花hello
hello
0
花花
Staff
4 months ago
testhua
是的
2
Jason like
Staff
4 months ago
528
2
花花
Staff
4 months ago
testhua
hello
2