代码很简单没有难度,自己看一下应该就能明白。
OK 老规矩,直接上代码:
射线测距
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 网格变形器输入 & GL 距离绘制
///
/// </summary>
public class MeshDeformerInput_ZH : MonoBehaviour
{
//GL 起始 结束点
private Vector3 _Target, _End;
//距离
private float _Distance = 0;
//距离文字
private string _DistanceStr = "";
//点击计数
private int _Number = 1;
[Header("GUI 线段")]
public Color _ColorGUI;
[Header ("GUI 文字")]
public Color _ColorStr;
void Update()
{
if (Input.GetMouseButtonDown(1))
{
_Number++;
Ray _GLRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit _GLHit;
if (Physics.Raycast(_GLRay, out _GLHit))
{
if (_GLHit.transform.tag == "Crash")
{
_Target = _GLHit.point;
if (_Number == 2)
{
Ray _DistanceRay = Camera.main.ScreenPointToRay(Input.mousePosition);
///射线碰到了物体,hit为鼠标碰到的物体,hit1是从该物体发出的射线碰撞到的物体
RaycastHit _Hit1;
if (Physics.Raycast(_DistanceRay, out _Hit1))
{
_End = _Hit1.point;
Debug.DrawLine(_Target, _End);
_Number = 0;
}
}
}
}
//防止越界
if (_Number > 2)
{
_Number = 1;
}
print(_Number);
}
}
/// <summary>
/// GL 绘制
/// </summary>
private void GLDrawLine(Vector3 _Target, Vector3 _End)
{
//返回这个向量的长度(只读)
_Distance = (_End - _Target).magnitude;
//如果距离不等于0
if (_Distance != 0.0)
{
//显示位置
_DistanceStr = _Distance.ToString("f2") + "M";
//GL 绘制类型 (线段)
GL.Begin(GL.LINE_STRIP);
//线段颜色
GL.Color(_ColorGUI);
//开始位置
GL.Vertex3(_Target.x, _Target.y, _Target.z);
//结束位置
GL.Vertex3(_End.x, _End.y, _End.z);
//绘制结束
GL.End();
}
}
public float _SizeVector2;
/// <summary>
/// GUI 文字显示
/// </summary>
private void GUIStr(string _DistanceStr)
{
//如果距离文字不为空
if (_DistanceStr != "")
{
//世界空间位置
Vector3 _WorldPosition = new Vector3(((_Target + _End) / 2).x, ((_Target + _End) / 2).y, ((_Target + _End) / 2).z);
//从世界空间转换到屏幕空间的位置
Vector3 _Position = Camera.main.WorldToScreenPoint(_WorldPosition);
//生成位置 在起始点到终点 的一半
_Position = new Vector2(_Position.x, Screen.height - _Position.y);
//GUI 颜色
GUI.color = _ColorStr;
//文字大小
Vector2 _StrSize = GUI.skin.label.CalcSize(new GUIContent(_DistanceStr));
//在屏幕上创建一个文本或纹理标签
GUI.Label(new Rect(_Position.x - (_StrSize.x / 2), _Position.y - _StrSize.y, _StrSize.x +_SizeVector2, _StrSize.y +_SizeVector2), _DistanceStr);
}
}
private void OnGUI()
{
if (_Number==1)
{
GUIStr(_DistanceStr);
}
}
private void OnPostRender()
{
if (_Number == 1)
{
GLDrawLine(_Target, _End);
}
}
}
网格变形
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 网格变形器
/// </summary>
[RequireComponent(typeof(MeshFilter))]
public class MeshDeformer_ZH : MonoBehaviour
{
[Header("弹力")]
public float _SpringForce = 20f;
[Header("衰减值")]
public float _Damping = 5f;
[Header("初始附加力")]
public float _Force = 10f;
[Header("初始衰减力")]
public float _ForceOffset = 0.1f;
//变形网格
private Mesh DeformingMesh;
//原始顶点数组 移动的顶点数组
private Vector3[] _OriginalVertices, _DisplacedVertices;
//顶点速度数组
private Vector3[] _VertexVelocities;
//等分标尺
private float _UniformScale = 1f;
void Start()
{
//变形网格获取
DeformingMesh = GetComponent<MeshFilter>().mesh;
//获取变形网格顶点数据
_OriginalVertices = DeformingMesh.vertices;
//变形顶点网格数据数组填充
_DisplacedVertices = new Vector3[_OriginalVertices.Length];
for (int i = 0; i < _OriginalVertices.Length; i++)
{
_DisplacedVertices[i] = _OriginalVertices[i];
}
//顶点速度网格速度数组长度填充
_VertexVelocities = new Vector3[_OriginalVertices.Length];
}
void Update()
{
if (Input.GetMouseButton(0))
{
HandleInput();
}
//等分标尺 赋值
_UniformScale = transform.localScale.x;
//实时更新变形网格数据
for (int i = 0; i < _DisplacedVertices.Length; i++)
{
UpdateVertex(i);
}
//返回顶点位置的副本或分配一个新的顶点位置数组
DeformingMesh.vertices = _DisplacedVertices;
//从三角形和顶点重新计算网格的法线。
DeformingMesh.RecalculateNormals();
}
/// <summary>
/// 点击输入
/// </summary>
void HandleInput()
{
Ray _InputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit _Hit;
if (Physics.Raycast(_InputRay, out _Hit))
{
//获取变形网格
MeshDeformer_ZH _Deformer = _Hit.collider.GetComponent<MeshDeformer_ZH>();
if (_Deformer)
{
Vector3 _HitPoint = _Hit.point;
_HitPoint += _Hit.normal * _ForceOffset;
_Deformer.AddDeformingForce(_HitPoint, _Force);
}
}
}
/// <summary>
/// 更新顶点 复位
/// </summary>
/// <param name="i"></param>
void UpdateVertex(int i)
{
Vector3 _Velocity = _VertexVelocities[i];
//位移数据 变形顶点数据 减去 原始顶点数组
Vector3 _Displacement = _DisplacedVertices[i] - _OriginalVertices[i];
//位移数据 赋值
_Displacement *= _UniformScale;
//速度矢量 减等于 位移数据 * 弹力 * 缓动时间
_Velocity -= _Displacement * _SpringForce * Time.deltaTime;
//速度矢量 * 等于 1 减去衰减值 * 缓动时间
_Velocity *= 1f - _Damping * Time.deltaTime;
//顶点速度数组 缓动时间
_VertexVelocities[i] = _Velocity;
//移动顶点数据数组 加等于 速度矢量 * (缓动时间 除以 等分标尺)
_DisplacedVertices[i] += _Velocity * (Time.deltaTime / _UniformScale);
}
/// <summary>
/// 添加变形力
/// </summary>
/// <param 位置="_HitPoint"></param>
/// <param 力度="_Force"></param>
public void AddDeformingForce(Vector3 _HitPoint, float _Force)
{
//从世界空间到局部空间的位置转换
_HitPoint = transform.InverseTransformPoint(_HitPoint);
//循环编辑 变形顶点网格数据
for (int i = 0; i < _DisplacedVertices.Length; i++)
{
AddForceToVertex(i, _HitPoint, _Force);
}
}
/// <summary>
/// 顶点附加力
/// </summary>
/// <param 当前顶点="i"></param>
/// <param 位置="_HitPoint"></param>
/// <param 力度="_Force"></param>
void AddForceToVertex(int i, Vector3 _HitPoint, float _Force)
{
// 偏移顶点位置 当前变形顶点网格数据 减去传递值
Vector3 _PointToVertex = _DisplacedVertices[i] - _HitPoint;
//偏移顶点位置 乘 等分标尺
_PointToVertex *= _UniformScale;
//返回这个向量的平方长度(只读)
//衰减力 等于 力度值除以 顶点偏移位置的平方长度
float _AttenuatedForce = _Force / (1f + _PointToVertex.sqrMagnitude);
//渐变速度
float _Velocity = _AttenuatedForce * Time.deltaTime;
//原始顶点偏移 加等 变形网格数据顶点的法线方向 乘 渐变速度
_VertexVelocities[i] += _PointToVertex.normalized * _Velocity;
}
}
组件搭载:
最终效果:
射线测距
网格变形
暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路长远兮,与君共勉。