Unity模型編輯器實現仿爐石傳說攻擊箭頭
阿新 • • 發佈:2019-01-21
截圖展示
這裡所說的模仿,並沒有完全做成爐石傳說一摸一樣的攻擊箭頭,其實我在這裡做了一些簡化,所以並沒有爐石那麼好看,當然要實現也是可以的,只是要多一些模型資料的計算,加油。這裡主要說一下實現思路
拋物線實現曲線
- 忽略空氣阻力
- 已知兩點及之間的距離
- 已知通過兩點間的速度(設定的引數)
- 已知重力加速度(設定的引數)
- 已知最高點縱向速度為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
}