using System.Collections.Generic; using UnityEngine; public enum ESceneObjectType { None = 0, Tree = 1, //树 Buildings = 2, //建筑物 Stuff = 3,//其他 } /// /// 场景中对象,可以方便地执行一些渲染上的效果,如半透,面片渲染等 /// 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(); } if (sceneManager != 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 mats) { if (mats == null || mats.Count == 0) return; var meshrenderers = GetComponentsInChildren(); int matIndex = 0; List matsToSet = new(); foreach (var meshrenderer in meshrenderers) { matsToSet.Clear(); var msf = meshrenderer.GetComponent(); 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 meshes) { if (meshes == null || meshes.Count == 0) return; var msfs = GetComponentsInChildren(); 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 == null) { _useSurface = false; return; } var msr = gameObject.GetComponentInChildren(); var msf = msr.GetComponent(); if (msr == null) return; var meshTrans = msr.transform; SaveSurfaceTransformValues(meshTrans); msf.sharedMesh = await SceneSurfaceData.GetSurfaceMesh(); RefreshAllMaterials(new List() { 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(); if (msr == null) return; var meshTrans = msr.transform; RefreshAllMeshes(renderInfo.meshes); RefreshTransparent(); RevertSurfaceTransformValues(meshTrans); } }