using UnityEngine; using UnityEngine.Rendering; public class Entity { private readonly int entityNum; private GameObject gameObject; private MeshFilter meshFilter; private MeshRenderer meshRenderer; private SkinnedMeshRenderer skinnedMeshRenderer; private AliasModel aliasModel; private GameObject brushModel; private GameObject worldModel; public Entity(int entityNum) { this.entityNum = entityNum; CreateGameObject(); } private void CreateGameObject() { gameObject = new GameObject($"Entity_{entityNum}"); } public void Destroy() { Object.Destroy(gameObject); } public void ClearModel() { aliasModel = null; brushModel = null; worldModel = null; Object.Destroy(meshFilter); Object.Destroy(meshRenderer); Object.Destroy(skinnedMeshRenderer); // TODO: not sure if this is the right way to unlink world sub-models gameObject.transform.DetachChildren(); } public void SetAliasModel(AliasModel model) { ClearModel(); aliasModel = model; AssignMeshRenderer(); // Set a default pose based on the first animation frame UpdateAnimation(0); if (model.AutoAnimate) { // TODO: do something with syncbase value to push similar animations out of phase var animator = gameObject.AddComponent(); animator.aliasModel = model; } } public void SetBrushModel(GameObject brushModelGO) { ClearModel(); brushModel = brushModelGO; brushModel.transform.SetParent(gameObject.transform); } public void SetWorldModel(GameObject worldModelGO) { ClearModel(); worldModel = worldModelGO; worldModel.transform.SetParent(gameObject.transform); } public void UpdateAnimation(float frameNum) { if (aliasModel != null) { aliasModel.Animate(frameNum, out Mesh mesh, out float blendWeight); if (skinnedMeshRenderer != null) { skinnedMeshRenderer.sharedMesh = mesh; if (mesh != null && mesh.blendShapeCount > 0) skinnedMeshRenderer.SetBlendShapeWeight(0, blendWeight); } else if (meshFilter != null) { meshFilter.sharedMesh = mesh; } } if (worldModel != null) { // TODO: update texture animation } } public void SetTransform(Vector3 position, Quaternion rotation) { gameObject.transform.position = position; gameObject.transform.rotation = rotation; } private void AssignMeshRenderer() { // DEBUG - we'll want to instantiate a prefab and assign materials from a preset collection var material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); if (aliasModel.IsAnimated) { skinnedMeshRenderer = gameObject.AddComponent(); skinnedMeshRenderer.material = material; skinnedMeshRenderer.shadowCastingMode = ShadowCastingMode.Off; skinnedMeshRenderer.receiveShadows = false; skinnedMeshRenderer.lightProbeUsage = LightProbeUsage.Off; skinnedMeshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off; } else { meshFilter = gameObject.AddComponent(); meshRenderer = gameObject.AddComponent(); meshRenderer.material = material; meshRenderer.shadowCastingMode = ShadowCastingMode.Off; meshRenderer.receiveShadows = false; meshRenderer.lightProbeUsage = LightProbeUsage.Off; meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off; } } }