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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神码编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值