截图展示
这里所说的模仿,并没有完全做成炉石传说一摸一样的攻击箭头,其实我在这里做了一些简化,所以并没有炉石那么好看,当然要实现也是可以的,只是要多一些模型数据的计算,加油。这里主要说一下实现思路
抛物线实现曲线
- 忽略空气阻力
- 已知两点及之间的距离
- 已知通过两点间的速度(设置的参数)
- 已知重力加速度(设置的参数)
- 已知最高点纵向速度为0
- 可求两点之间经过的时间(t=s/v)
- 可求初始速度(v0=-gt)
本来想详解一下抛物线,根据以上条件就能轻松算出曲线任意点的位置。我也不知道是否解释清楚,下面是具体的实现代码:
_fTime += Time.fixedDeltaTime;
//s=v0*t-0.5f*g*t*t
transform.position = _StartPos+( _StartSpeed * _fTime - 0.5f * G * _fTime * _fTime);
求垂直向量绘制面片
因为我是用在UGUI上,通过两点,我可以得出它的垂直向量,然后通过垂直向量扩展面片。绘制模型在前面的博客都有写,都一样。然后移动uv做出简单的动画效果
#region 获取箭头的垂直向量
Vector3 GetDir(Vector3 _start,Vector3 _end)
{
Vector3 _dirValue = (_end - _start).normalized;
//因为不需要考虑z轴的向量,加一个条件,即可得出唯一垂直向量
Vector2 _dir=new Vector2(Mathf.Abs(_dirValue.y),-1.0f*Mathf.Sign(_dirValue.x* _dirValue.y)*Mathf.Abs(_dirValue.x));
if (_dirValue.y < 0)
_dir *= -1.0f;
return _dir;
}
#endregion
完整代码
这篇博客主要做个截图展示,最后还是给个完整代码,
/// ========================================================
/// file:ArrowMesh.cs
/// brief:
/// author: coding2233
/// date:
/// version:v1.0
/// ========================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowMesh : MonoBehaviour {
// 重力加速度
[SerializeField]
private Vector3 G = new Vector3(0.0f, 0.0f, 9.8f);
//间隔时间
[SerializeField]
private float _FixedTime = 0.05f;
// 速度 保证速度均匀,路径越长时间越长
[SerializeField]
private float _Speed = 10;
public float Speed
{
set
{
_Speed = value;
}
get
{
return _Speed;
}
}
//箭头的宽度
[SerializeField]
private float _ArrowWidth = 2.0f;
private MeshFilter _MeshFilter;
// private Vector3 _StartPos;
#if UNITY_EDITOR
private void OnValidate()
{
}
#endif
private void Start()
{
_MeshFilter = GetComponent<MeshFilter>();
}
public void UpdatePosition(Vector3 _endPos)
{
if(!_MeshFilter)
_MeshFilter = GetComponent<MeshFilter>();
List<Vector3> _pos = GetRadianPos(Vector3.zero, _endPos);
CreateMesh(_MeshFilter, _pos);
}
#region 创建模型
void CreateMesh(MeshFilter _meshFilter,List<Vector3> _pos)
{
int _num = _pos.Count -1;
if (_num < 1)
return;
float _halfWidth = _ArrowWidth * 0.5f;
Vector3 _dir = GetDir(_pos[0], _pos[_num]);
//Vector3[] _vertices = new Vector3[_num*4+8];
//Vector2[] _uv = new Vector2[_num * 4 + 8];
//int[] _triangle = new int[_num * 6 + 12];
Vector3[] _vertices = new Vector3[_num * 4];
Vector2[] _uv = new Vector2[_num * 4];
int[] _triangle = new int[_num * 6];
for (int i = 0; i < _num; i++)
{
//计算顶点位置
_vertices[i * 4 + 0] = _pos[i] +_dir* _halfWidth;
_vertices[i * 4 + 1] = _pos[i + 1] - _dir * _halfWidth ;
_vertices[i * 4 + 2] = _pos[i + 1] + _dir * _halfWidth ;
_vertices[i * 4 + 3] = _pos[i] - _dir * _halfWidth;
//计算uv位置
_uv[i * 4 + 0] = new Vector2(0.0f, 0.0f);
_uv[i * 4 + 1] = new Vector2(1.0f, 1.0f);
_uv[i * 4 + 2] = new Vector2(1.0f, 0.0f);
_uv[i * 4 + 3] = new Vector2(0.0f, 1.0f);
}
int _verticeIndex = 0;
for (int i = 0; i < _num; i++)
{
// 第一个三角形
_triangle[_verticeIndex++] = i * 4 + 0;
_triangle[_verticeIndex++] = i * 4 + 1;
_triangle[_verticeIndex++] = i * 4 + 2;
// 第二个三角形
_triangle[_verticeIndex++] = i * 4 + 1;
_triangle[_verticeIndex++] = i * 4 + 0;
_triangle[_verticeIndex++] = i * 4 + 3;
}
Mesh _newMesh = new Mesh();
_newMesh.vertices = _vertices;
_newMesh.uv = _uv;
_newMesh.triangles = _triangle;
#if UNITY_EDITOR
_meshFilter.sharedMesh = _newMesh;
#else
_meshFilter.mesh = _newMesh;
#endif
}
#endregion
#region 获取箭头的垂直向量
Vector3 GetDir(Vector3 _start,Vector3 _end)
{
Vector3 _dirValue = (_end - _start).normalized;
//因为不需要考虑z轴的向量,加一个条件,即可得出唯一垂直向量
Vector2 _dir=new Vector2(Mathf.Abs(_dirValue.y),-1.0f*Mathf.Sign(_dirValue.x* _dirValue.y)*Mathf.Abs(_dirValue.x));
if (_dirValue.y < 0)
_dir *= -1.0f;
return _dir;
}
#endregion
#region 获取两点之间的点
List<Vector3> GetRadianPos(Vector3 _startPos, Vector3 _endPos)
{
List<Vector3> _pos = new List<Vector3>();
float _LifeTime = Vector3.Distance(_startPos, _endPos) / _Speed;
// 朝上移动:v=v0-gt; v0=v+gt; v0=0;
Vector3 _startSpeed=(_endPos-_startPos)/_LifeTime+ G * (_LifeTime * 0.5f);
for (float _moveTime = 0.0f; _moveTime <= _LifeTime; _moveTime+= _FixedTime)
{
if (_moveTime > _LifeTime)
_moveTime = _LifeTime;
Vector3 _tmpPos = _startPos + (_startSpeed * _moveTime - 0.5f * G * _moveTime * _moveTime);
_pos.Add(_tmpPos);
}
return _pos;
}
#endregion
}