228 lines
5.7 KiB
C#
228 lines
5.7 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public enum ESceneObjectType
|
|
{
|
|
None = 0,
|
|
Tree = 1, //树
|
|
Buildings = 2, //建筑物
|
|
Stuff = 3,//其他
|
|
}
|
|
|
|
/// <summary>
|
|
/// 场景中对象,可以方便地执行一些渲染上的效果,如半透,面片渲染等
|
|
/// </summary>
|
|
public class SceneObject : MonoBehaviour
|
|
{
|
|
#region Fields
|
|
|
|
[SerializeField]
|
|
private bool _transparent;
|
|
|
|
[SerializeField]
|
|
private bool _useSurface;
|
|
|
|
[SerializeField]
|
|
public SceneObjectRenderInfo renderInfo;
|
|
|
|
[SerializeField]
|
|
public ESceneObjectType sceneObjectType;
|
|
|
|
private bool Valid => renderInfo != null;
|
|
|
|
private SceneSurfaceData _surfaceData;
|
|
|
|
public SceneSurfaceData SurfaceData
|
|
{
|
|
get
|
|
{
|
|
if (_surfaceData == null || !_surfaceData.valid)
|
|
{
|
|
NLDSceneManager sceneManager;
|
|
if (Application.isPlaying)
|
|
{
|
|
sceneManager = NLDSceneManager.Instance;
|
|
}
|
|
else
|
|
{
|
|
sceneManager = FindObjectOfType<NLDSceneManager>();
|
|
}
|
|
|
|
if (sceneManager is not null)
|
|
{
|
|
sceneManager.Refresh();
|
|
_surfaceData = sceneManager.GetSurfaceData(renderInfo);
|
|
}
|
|
}
|
|
|
|
return _surfaceData;
|
|
}
|
|
}
|
|
|
|
public bool SupportSurface => SurfaceData != null && SurfaceData.IsGameObjectValid(gameObject);
|
|
|
|
private Vector3 _originMeshScale;
|
|
private Vector3 _originMeshPosition;
|
|
private Quaternion _originMeshRotation;
|
|
|
|
#endregion
|
|
|
|
#region API
|
|
|
|
public bool Transparent
|
|
{
|
|
get => _transparent;
|
|
set
|
|
{
|
|
if (_transparent != value && Valid)
|
|
{
|
|
_transparent = value;
|
|
RefreshTransparent();
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool UseSurface
|
|
{
|
|
get => _useSurface;
|
|
set
|
|
{
|
|
if (_useSurface != value)
|
|
{
|
|
if (value && !SupportSurface)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_useSurface = value;
|
|
RefreshSurface();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MainLife
|
|
|
|
private void Start()
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void SaveSurfaceTransformValues(Transform meshTrans)
|
|
{
|
|
_originMeshScale = meshTrans.localScale;
|
|
_originMeshPosition = meshTrans.position;
|
|
_originMeshRotation = meshTrans.rotation;
|
|
}
|
|
|
|
private void RevertSurfaceTransformValues(Transform surfaceTrans)
|
|
{
|
|
surfaceTrans.localScale = _originMeshScale;
|
|
surfaceTrans.position = _originMeshPosition;
|
|
surfaceTrans.rotation = _originMeshRotation;
|
|
}
|
|
|
|
private void RefreshAllMaterials(List<Material> mats)
|
|
{
|
|
if (mats == null || mats.Count == 0)
|
|
return;
|
|
var meshrenderers = GetComponentsInChildren<MeshRenderer>();
|
|
int matIndex = 0;
|
|
List<Material> matsToSet = new();
|
|
foreach (var meshrenderer in meshrenderers)
|
|
{
|
|
matsToSet.Clear();
|
|
var msf = meshrenderer.GetComponent<MeshFilter>();
|
|
var mesh = msf.sharedMesh;
|
|
for (int i = 0; i < mesh.subMeshCount; i++)
|
|
{
|
|
Material matToSet = matIndex >= mats.Count ? null : mats[matIndex];
|
|
|
|
matsToSet.Add(matToSet);
|
|
matIndex++;
|
|
}
|
|
|
|
meshrenderer.SetSharedMaterials(matsToSet);
|
|
}
|
|
}
|
|
|
|
private void RefreshAllMeshes(List<Mesh> meshes)
|
|
{
|
|
if (meshes == null || meshes.Count == 0)
|
|
return;
|
|
var msfs = GetComponentsInChildren<MeshFilter>();
|
|
int meshIndex = 0;
|
|
foreach (var msf in msfs)
|
|
{
|
|
Mesh mesh = null;
|
|
if (meshIndex < meshes.Count)
|
|
mesh = meshes[meshIndex];
|
|
msf.sharedMesh = mesh;
|
|
meshIndex++;
|
|
}
|
|
}
|
|
|
|
private void RefreshTransparent()
|
|
{
|
|
if (!_useSurface)
|
|
{
|
|
RefreshAllMaterials(_transparent ? renderInfo.transparentMaterial : renderInfo.opaqueMaterial);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
private void RefreshSurface()
|
|
{
|
|
if (_useSurface)
|
|
{
|
|
ChangeGameObjectToSurface();
|
|
}
|
|
else
|
|
{
|
|
ChangeGameObjectToReal();
|
|
}
|
|
}
|
|
|
|
private async void ChangeGameObjectToSurface()
|
|
{
|
|
var mat = await SurfaceData.GetMaterial();
|
|
if (mat is null)
|
|
{
|
|
_useSurface = false;
|
|
return;
|
|
}
|
|
|
|
var msr = gameObject.GetComponentInChildren<MeshRenderer>();
|
|
var msf = msr.GetComponent<MeshFilter>();
|
|
if (msr is null)
|
|
return;
|
|
|
|
var meshTrans = msr.transform;
|
|
SaveSurfaceTransformValues(meshTrans);
|
|
msf.sharedMesh = await SceneSurfaceData.GetSurfaceMesh();
|
|
RefreshAllMaterials(new List<Material>() { mat });
|
|
//必须是统一缩放
|
|
var rootScale = transform.localScale.x;
|
|
meshTrans.position += SurfaceData.cachedOffset * rootScale;
|
|
if (meshTrans == transform)
|
|
meshTrans.localScale = SurfaceData.cachedScale * rootScale;
|
|
else
|
|
meshTrans.localScale = SurfaceData.cachedScale;
|
|
meshTrans.eulerAngles = SurfaceData.cachedRotation;
|
|
}
|
|
|
|
private void ChangeGameObjectToReal()
|
|
{
|
|
var msr = gameObject.GetComponentInChildren<MeshRenderer>();
|
|
if (msr is null)
|
|
return;
|
|
var meshTrans = msr.transform;
|
|
RefreshAllMeshes(renderInfo.meshes);
|
|
RefreshTransparent();
|
|
RevertSurfaceTransformValues(meshTrans);
|
|
}
|
|
} |