1. 程式人生 > >Unity模型編輯器實現仿爐石傳說攻擊箭頭

Unity模型編輯器實現仿爐石傳說攻擊箭頭

截圖展示

這裡寫圖片描述
這裡寫圖片描述
這裡所說的模仿,並沒有完全做成爐石傳說一摸一樣的攻擊箭頭,其實我在這裡做了一些簡化,所以並沒有爐石那麼好看,當然要實現也是可以的,只是要多一些模型資料的計算,加油。這裡主要說一下實現思路

拋物線實現曲線

  • 忽略空氣阻力
  • 已知兩點及之間的距離
  • 已知通過兩點間的速度(設定的引數)
  • 已知重力加速度(設定的引數)
  • 已知最高點縱向速度為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 }