using System;
using UnityEngine;
using UnityEngine.Serialization;
[ExecuteInEditMode]
public class ParticleSystemMeshRender : MonoBehaviour
{
[Header("BillBoard")]
public Vector3 startRotation;
public Vector3 rotationSpeed;//TODO曲线
public RenderAlignment renderAlignment;
public enum RenderAlignment
{
View, World, //Local
}
private Quaternion _origRotation;
private Vector3 _currentSpeedRotation;
[Header("Size")]
public float minSize = 0f;
public float maxSize = 0.5f;
public Vector3 origScale = Vector3.one;
public bool outCam;
public float viewWidthRatio;
public float viewHeightRatio;
public float viewRatio;
public float screenRadio;
public float afterPercentage;
public float sizeScale;
private Renderer rend;
private Camera cam;
private void Start()
{
cam = Camera.main;
rend = GetComponent<Renderer>();
origScale = transform.localScale;
}
private void Update()
{
#if UNITY_EDITOR
if (!Application.isPlaying)//编辑时一直能获取
{
if (rend == null)
rend = GetComponent<Renderer>();
if(cam == null)
cam = Camera.main;
}
#endif
if(rend == null || cam == null)
return;
_UpdateBillBoard();
_UpdateClampSize();
}
void _UpdateBillBoard()
{
//if (_origRotation != transform.rotation)
// _origRotation = transform.rotation;
_currentSpeedRotation += rotationSpeed * Time.deltaTime;
//if(renderAlignment == RenderAlignment.Local)
//{
// startRotation = transform.eulerAngles;
//}
var rotation = Quaternion.identity;
if (renderAlignment == RenderAlignment.View)
{
if (cam.transform != null)
transform.forward = -cam.transform.forward;
rotation = cam.transform.rotation;
}
else if(renderAlignment == RenderAlignment.World)
{
transform.forward = Vector3.forward;
}
//else if(renderAlignment == RenderAlignment.Local)
//{
// transform.rotation = Quaternion.Euler(startRotation);
//}
var offset = _currentSpeedRotation + startRotation;
transform.rotation = rotation * Quaternion.Euler(offset);
}
void _UpdateClampSize()
{
//还原大小
transform.localScale = origScale;
//获取bound位置
Bounds bounds = rend.bounds;
Vector3 viewPoint = cam.WorldToViewportPoint(bounds.center);
//检查视口坐标是否在屏幕之外
if (viewPoint.z < 0 || 1 < viewPoint.x || viewPoint.x < 0 || 1 < viewPoint.y || viewPoint.y < 0)
{
outCam = true;
return;
}
outCam = false;
var min = Vector3.Scale(bounds.min, transform.localScale);
var max = Vector3.Scale(bounds.max, transform.localScale);
//var min = transform.TransformPoint(bounds.min);
//var max = transform.TransformPoint(bounds.max);
Vector3 minPoint = cam.WorldToViewportPoint(new Vector3(min.x, min.y, min.z));
Vector3 maxPoint = cam.WorldToViewportPoint(new Vector3(max.x, max.y, max.z));
float width = viewRatio = viewWidthRatio = maxPoint.x - minPoint.x;
float height = viewHeightRatio = maxPoint.y - minPoint.y;
float modelArea = width * height;
float screenWidth = Screen.width;
float screenHeight = Screen.height;
float screenArea = screenWidth * screenHeight;
// 计算模型在屏幕上的占比
screenRadio = modelArea / screenArea;
if (outCam || screenRadio <= 0)//镜头之外就不管,0缩放不管
{
return;
}
var calcRatio = viewRatio;
// 如果模型的占比小于最小值,增大模型的大小
if (calcRatio < minSize)
{
sizeScale = minSize / calcRatio;
transform.localScale = origScale * (sizeScale);
}
// 如果模型的占比大于最大值,缩小模型的大小
else if (calcRatio > maxSize)
{
sizeScale = maxSize / calcRatio;
transform.localScale = origScale * sizeScale;
}
bounds = rend.bounds;
min = Vector3.Scale(bounds.min, transform.localScale);
max = Vector3.Scale(bounds.max, transform.localScale);
minPoint = cam.WorldToScreenPoint(new Vector3(min.x, min.y, min.z));
maxPoint = cam.WorldToScreenPoint(new Vector3(max.x, max.y, max.z));
width = maxPoint.x - minPoint.x;
height = maxPoint.y - minPoint.y;
modelArea = width * height;
afterPercentage = modelArea / screenArea;
}
private void OnDisable()
{
_currentSpeedRotation = Vector3.zero;
}
}
#if UNITY_EDITOR
#endif
unity看向并clamp size
最新推荐文章于 2024-10-16 15:24:54 发布