您的位置:首页 > 移动开发 > Unity3D

Unity模型编辑器实现仿炉石传说攻击箭头

2017-07-08 14:27 357 查看

截图展示





这里所说的模仿,并没有完全做成炉石传说一摸一样的攻击箭头,其实我在这里做了一些简化,所以并没有炉石那么好看,当然要实现也是可以的,只是要多一些模型数据的计算,加油。这里主要说一下实现思路

抛物线实现曲线

忽略空气阻力

已知两点及之间的距离

已知通过两点间的速度(设置的参数)

已知重力加速度(设置的参数)

已知最高点纵向速度为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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: