public void Initialize() { if (_noteAssetLoader.SelectedNote != 0) { CustomNote activeNote = _noteAssetLoader.CustomNoteObjects[_noteAssetLoader.SelectedNote]; if (activeNote.NoteBomb != null) { MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteBomb); } if (_gameplayCoreSceneSetupData.gameplayModifiers.ghostNotes) { _submission?.DisableScoreSubmission("Custom Notes", "Ghost Notes"); } if (_gameplayCoreSceneSetupData.gameplayModifiers.disappearingArrows) { _submission?.DisableScoreSubmission("Custom Notes", "Disappearing Arrows"); } if (_gameplayCoreSceneSetupData.gameplayModifiers.smallCubes) { _submission?.DisableScoreSubmission("Custom Notes", "Small Notes"); } if (Utils.IsNoodleMap(_level)) { _submission?.DisableScoreSubmission("Custom Notes", "Noodle Extensions"); } } }
public void OnGameSceneLoaded() { CustomNote activeNote = NoteAssetLoader.CustomNoteObjects[NoteAssetLoader.SelectedNote]; if (activeNote.FileName != "DefaultNotes") { MaterialSwapper.GetMaterials(); MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteLeft); MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteRight); if (activeNote.NoteDotLeft != null) { MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteDotLeft); } if (activeNote.NoteDotRight != null) { MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteDotRight); } if (activeNote.NoteBomb != null) { MaterialSwapper.ReplaceMaterialsForGameObject(activeNote.NoteBomb); } CheckCustomNotesScoreDisable(); } else if (ScoreUtility.ScoreIsBlocked) { ScoreUtility.EnableScoreSubmission("ModifiersEnabled"); } }
public void Construct(NoteAssetLoader _noteAssetLoader, DiContainer Container, GameplayCoreSceneSetupData sceneSetupData) { CanSetup = !(sceneSetupData.gameplayModifiers.ghostNotes || sceneSetupData.gameplayModifiers.disappearingArrows) || !Container.HasBinding <MultiplayerLevelSceneSetupData>(); if (_noteAssetLoader.SelectedNote != 0) { var note = _noteAssetLoader.CustomNoteObjects[_noteAssetLoader.SelectedNote]; MaterialSwapper.GetMaterials(); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteLeft); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteRight); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteDotLeft); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteDotRight); Utils.AddMaterialPropertyBlockController(note.NoteLeft); Utils.AddMaterialPropertyBlockController(note.NoteRight); Utils.AddMaterialPropertyBlockController(note.NoteDotLeft); Utils.AddMaterialPropertyBlockController(note.NoteDotRight); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId("cn.left.arrow").WithInitialSize(25).FromComponentInNewPrefab(NotePrefabContainer(note.NoteLeft)); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId("cn.right.arrow").WithInitialSize(25).FromComponentInNewPrefab(NotePrefabContainer(note.NoteRight)); if (note.NoteDotLeft != null) { Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId("cn.left.dot").WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteDotLeft)); } if (note.NoteDotRight != null) { Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId("cn.right.dot").WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteDotRight)); } } }
/// <summary> /// Start this instance. If environment is Android, instantiate the location tracker, and send it /// an instance of the LocationUpdateListener, attached to the primary sphere object. /// </summary> void Start() { #if UNITY_ANDROID AndroidJavaObject javaObj = new AndroidJavaObject("edu.temple.gamemanager.LocationTracker"); MaterialSwapper listener = new MaterialSwapper(GameObject.Find("Sphere")); javaObj.Call("SetLocationUpdateListener", listener); #else Debug.Log("LocationUpdateListener placeholder for Play Mode (not running on Android device)"); #endif }
public void Construct(NoteAssetLoader _noteAssetLoader, DiContainer Container, GameplayCoreSceneSetupData sceneSetupData) { CanSetup = !(sceneSetupData.gameplayModifiers.ghostNotes || sceneSetupData.gameplayModifiers.disappearingArrows) || !Container.HasBinding <MultiplayerLevelSceneSetupData>(); if (_noteAssetLoader.SelectedNote != 0 && CanSetup) { var note = _noteAssetLoader.CustomNoteObjects[_noteAssetLoader.SelectedNote]; MaterialSwapper.GetMaterials(); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteBomb); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId("cn.bomb").WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteBomb)); } }
/// <summary> /// This function is called when on Able to Move is invoked from XRPOIGazeMovement. /// Gets material swapper component from gazed target, /// and uses it to set highlight material on target. /// </summary> /// <param name="target"></param> private void CanMove(Transform target) { if (target != null) { matSwap = target.GetComponent <MaterialSwapper>(); if (matSwap != null) { matSwap.SetHighLightMaterial(); } } }
public override void InstallBindings() { bool autoDisable = _pluginConfig.AutoDisable && (_gameplayCoreSceneSetupData.gameplayModifiers.ghostNotes || _gameplayCoreSceneSetupData.gameplayModifiers.disappearingArrows || _gameplayCoreSceneSetupData.gameplayModifiers.smallCubes || Utils.IsNoodleMap(_gameplayCoreSceneSetupData.difficultyBeatmap)); _shouldSetup = !autoDisable && (!(_gameplayCoreSceneSetupData.gameplayModifiers.ghostNotes || _gameplayCoreSceneSetupData.gameplayModifiers.disappearingArrows) || !Container.HasBinding <MultiplayerLevelSceneSetupData>()); if (_pluginConfig.Enabled && _noteAssetLoader.SelectedNote != 0 && _shouldSetup) { Container.BindInterfacesAndSelfTo <GameCameraManager>().AsSingle(); Container.Bind <IInitializable>().To <CustomNoteManager>().AsSingle(); CustomNote note = _noteAssetLoader.CustomNoteObjects[_noteAssetLoader.SelectedNote]; #region Note Setup Container.RegisterRedecorator(new BasicNoteRegistration(DecorateNote, DECORATION_PRIORITY)); MaterialSwapper.GetMaterials(); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteLeft); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteRight); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteDotLeft); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteDotRight); Utils.AddMaterialPropertyBlockController(note.NoteLeft); Utils.AddMaterialPropertyBlockController(note.NoteRight); Utils.AddMaterialPropertyBlockController(note.NoteDotLeft); Utils.AddMaterialPropertyBlockController(note.NoteDotRight); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId(Protocol.LeftArrowPool).WithInitialSize(25).FromComponentInNewPrefab(NotePrefabContainer(note.NoteLeft)); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId(Protocol.RightArrowPool).WithInitialSize(25).FromComponentInNewPrefab(NotePrefabContainer(note.NoteRight)); if (note.NoteDotLeft != null) { Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId(Protocol.LeftDotPool).WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteDotLeft)); } if (note.NoteDotRight != null) { Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId(Protocol.RightDotPool).WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteDotRight)); } #endregion #region Bomb Setup if (note.NoteBomb != null) { MaterialSwapper.GetMaterials(); MaterialSwapper.ReplaceMaterialsForGameObject(note.NoteBomb); Container.BindMemoryPool <SiraPrefabContainer, SiraPrefabContainer.Pool>().WithId(Protocol.BombPool).WithInitialSize(10).FromComponentInNewPrefab(NotePrefabContainer(note.NoteBomb)); Container.RegisterRedecorator(new BombNoteRegistration(DecorateBombs, DECORATION_PRIORITY)); } #endregion } }
/// <summary> /// This function is called, /// when on Not Able to Move is invoked from XRPOIGazeMovement. /// if material swapper is not null, /// sets the normal material of that material swapper, /// and nulls the material swapper. /// if target is not null, /// sets material swapper to match target material swapper, /// and sets it material to normal material. /// </summary> /// <param name="target"></param> private void CantMove(Transform target) { if (matSwap != null) { matSwap.SetNormalMaterial(); matSwap = null; } if (target != null) { matSwap = target.GetComponent <MaterialSwapper>(); if (matSwap != null) { matSwap.SetNormalMaterial(); } } }
public void AddComponentsToSceneObject(AreaSceneObjectData jsonData, GameObject so) { if (jsonData.soData.Count > 0) { SceneObjectDataGeneric data = jsonData.soData [0]; SceneObjectData sceneObjectData = so.GetComponent <SceneObjectData> (); Bumper bumper = so.GetComponent <Bumper> (); if (data.bumperForce > 0) { if (bumper == null) { bumper = so.gameObject.AddComponent <Bumper> (); } bumper.force = data.bumperForce; } if (data.size != Vector3.zero) { if (sceneObjectData == null) { sceneObjectData = so.gameObject.AddComponent <SceneObjectData> (); } sceneObjectData.size = data.size; } if (data.random_pos_x != 0) { if (sceneObjectData == null) { sceneObjectData = so.gameObject.AddComponent <SceneObjectData> (); } sceneObjectData.random_pos_x = data.random_pos_x; } if (data.minPayers != 0) { if (sceneObjectData == null) { sceneObjectData = so.gameObject.AddComponent <SceneObjectData> (); } sceneObjectData.minPayers = data.minPayers; } } MaterialSwapper mat = so.GetComponent <MaterialSwapper>(); if (mat != null && jsonData.mat.Count > 0) { MaterialChanger data = jsonData.mat[0]; //if (mat == null) // mat = so.gameObject.AddComponent<MaterialSwapper>(); mat.Init(data.name); } FullRotation fullRotation = so.GetComponent <FullRotation> (); if (jsonData.fullRotationData.Count > 0) { FullRotationData data = jsonData.fullRotationData [0]; if (fullRotation == null) { fullRotation = so.gameObject.AddComponent <FullRotation> (); } fullRotation.rotateX = data.rotateX; fullRotation.rotateY = data.rotateY; fullRotation.rotateZ = data.rotateZ; fullRotation.speed = data.speed; fullRotation.randomRotation = data.random; } else if (fullRotation != null) { fullRotation.OnComponentDisposed(); } TimelineAnimation timelineAnimation = so.GetComponent <TimelineAnimation> (); if (jsonData.timelineAnimation.Count > 0) { TimelineAnimationData data = jsonData.timelineAnimation [0]; if (timelineAnimation == null) { timelineAnimation = so.gameObject.AddComponent <TimelineAnimation> (); } timelineAnimation.timeLineData = data.timeLineData; } else if (timelineAnimation != null) { timelineAnimation.OnComponentDisposed(); } if (jsonData.bossSettings.Count > 0) { BossSettingsData data = jsonData.bossSettings [0]; BossSettings newcomponent = so.GetComponent <BossSettings> (); if (newcomponent == null) { newcomponent = so.gameObject.AddComponent <BossSettings> (); } newcomponent.bossModule = data.bossModule; newcomponent.time_to_init_enemies = data.time_to_init_enemies; newcomponent.asset = data.asset; newcomponent.time_to_kill = data.time_to_kill; newcomponent.distance_from_avatars = data.distance_from_avatars; newcomponent.bundle = data.bundle; } if (jsonData.moveForward.Count > 0) { MoveForwardData data = jsonData.moveForward [0]; MoveForward newcomponent = so.GetComponent <MoveForward> (); if (newcomponent == null) { newcomponent = so.gameObject.AddComponent <MoveForward> (); } newcomponent.speed = data.speed; newcomponent.randomSpeedDiff = data.randomSpeedDiff; newcomponent.moveBackIn = data.moveBackIn; } }
public void AddComponentsToJson(AreaSceneObjectData newSOdata, GameObject go) { FullRotation fullRotation = go.GetComponent <FullRotation> (); MaterialSwapper mat = go.GetComponent <MaterialSwapper>(); TimelineAnimation timelineAnimation = go.GetComponent <TimelineAnimation> (); BossSettings bossSettings = go.GetComponent <BossSettings> (); MoveForward moveForward = go.GetComponent <MoveForward> (); Bumper bumper = go.GetComponent <Bumper> (); SceneObjectData soData = go.GetComponent <SceneObjectData> (); if (newSOdata.name == "wallSmall") { newSOdata.mat = new List <MaterialChanger>(); MaterialChanger mc = new MaterialChanger(); mc.name = go.GetComponent <MeshRenderer>().sharedMaterial.ToString().Split(" "[0])[0]; newSOdata.mat.Add(mc); } if (soData != null) { newSOdata.soData = new List <SceneObjectDataGeneric> (); SceneObjectDataGeneric data = new SceneObjectDataGeneric(); data.size = soData.size; data.random_pos_x = soData.random_pos_x; data.minPayers = soData.minPayers; data.minPayers = soData.minPayers; newSOdata.soData.Add(data); } if (bumper != null) { newSOdata.soData = new List <SceneObjectDataGeneric> (); SceneObjectDataGeneric data = new SceneObjectDataGeneric(); data.bumperForce = bumper.force; newSOdata.soData.Add(data); } if (fullRotation != null) { newSOdata.fullRotationData = new List <FullRotationData> (); FullRotationData data = new FullRotationData(); data.rotateX = fullRotation.rotateX; data.rotateY = fullRotation.rotateY; data.rotateZ = fullRotation.rotateZ; data.speed = fullRotation.speed; data.random = fullRotation.randomRotation; newSOdata.fullRotationData.Add(data); } if (timelineAnimation != null) { newSOdata.timelineAnimation = new List <TimelineAnimationData> (); TimelineAnimationData data = new TimelineAnimationData(); data.timeLineData = timelineAnimation.timeLineData; newSOdata.timelineAnimation.Add(data); } if (bossSettings != null) { newSOdata.bossSettings = new List <BossSettingsData> (); BossSettingsData data = new BossSettingsData(); data.bossModule = bossSettings.bossModule; data.asset = bossSettings.asset; data.time_to_init_enemies = bossSettings.time_to_init_enemies; data.time_to_kill = bossSettings.time_to_kill; data.distance_from_avatars = bossSettings.distance_from_avatars; data.bundle = bossSettings.bundle; newSOdata.bossSettings.Add(data); } if (moveForward != null) { newSOdata.moveForward = new List <MoveForwardData> (); MoveForwardData data = new MoveForwardData(); data.speed = moveForward.speed; data.randomSpeedDiff = moveForward.randomSpeedDiff; data.moveBackIn = moveForward.moveBackIn; newSOdata.moveForward.Add(data); } }
private void RecursivelyAddSubObject(TankBlock block, ModContents mod, Transform targetTransform, JObject jData, Material defaultMaterial, bool isNewSubObject) { Debug.Log("[Nuterra] Called RecursivelyAddSubObject"); // Material - Used in the next step Material mat = null; bool hasMaterial = TryGetStringMultipleKeys(jData, out string materialName, "MaterialName", "MeshMaterialName"); bool hasAlbedo = TryGetStringMultipleKeys(jData, out string albedoName, "MeshTextureName", "TextureName"); bool hasGloss = TryGetStringMultipleKeys(jData, out string glossName, "MetallicTextureName", "GlossTextureName", "MeshGlossTextureName"); bool hasEmissive = TryGetStringMultipleKeys(jData, out string emissiveName, "EmissionTextureName", "MeshEmissionTextureName"); bool hasAnyOverrides = hasAlbedo || hasGloss || hasEmissive; // Calculate a unique string that defines this material string compoundMaterialName = ""; if (hasMaterial) { compoundMaterialName = $"{compoundMaterialName}M:{materialName};"; } if (hasAlbedo) { compoundMaterialName = $"{compoundMaterialName}A:{albedoName};"; } if (hasGloss) { compoundMaterialName = $"{compoundMaterialName}G:{glossName};"; } if (hasEmissive) { compoundMaterialName = $"{compoundMaterialName}E:{emissiveName};"; } if (hasAnyOverrides) { if (sMaterialCache.TryGetValue(compoundMaterialName, out Material existingMat)) { mat = existingMat; } else { // Default to missing texture, then see if we have a base texture reference mat = defaultMaterial; if (hasMaterial) { string matName = materialName.Replace("Venture_", "VEN_").Replace("GeoCorp_", "GC_"); mat = TTReferences.FindMaterial(matName); } Texture2D albedo = hasAlbedo ? TTReferences.Find <Texture2D>(albedoName, mod) : null; Texture2D gloss = hasGloss ? TTReferences.Find <Texture2D>(glossName, mod) : null; Texture2D emissive = hasEmissive ? TTReferences.Find <Texture2D>(emissiveName, mod) : null; mat = Util.CreateMaterial(mat, true, albedo, gloss, emissive); // Cache our newly created material in case it comes up again sMaterialCache.Add(compoundMaterialName, mat); } } else { // Actually, if we make no references, we can keep official modded block behaviour mat = defaultMaterial; } // Physics Material - Used in the next step PhysicMaterial physMat = new PhysicMaterial(); if (jData.TryGetValue("Friction", out JToken jFriction)) { physMat.dynamicFriction = jFriction.ToObject <float>(); } if (jData.TryGetValue("StaticFriction", out JToken jStaticFriction)) { physMat.staticFriction = jStaticFriction.ToObject <float>(); } if (jData.TryGetValue("Bounciness", out JToken jBounce)) { physMat.bounciness = jBounce.ToObject <float>(); } // MeshName & ColliderMeshName Override Mesh mesh = null; Mesh colliderMesh = null; bool supressBoxColliderFallback = TryParse(jData, "SupressBoxColliderFallback", TryParse(jData, "NoBoxCollider", false)); if (TryGetStringMultipleKeys(jData, out string meshName, "MeshName", "ModelName")) { foreach (UnityEngine.Object obj in mod.FindAllAssets(meshName)) { if (obj != null) { if (obj is Mesh) { mesh = (Mesh)obj; } else if (obj is GameObject) { mesh = ((GameObject)obj).GetComponentInChildren <MeshFilter>().sharedMesh; } } } Debug.Assert(mesh != null, $"[Nuterra] Failed to find mesh with name {meshName}"); } if (TryGetStringMultipleKeys(jData, out string meshColliderName, "ColliderMeshName", "MeshColliderName")) { foreach (UnityEngine.Object obj in mod.FindAllAssets(meshColliderName)) { if (obj is Mesh) { colliderMesh = (Mesh)obj; } else if (obj is GameObject) { colliderMesh = ((GameObject)obj).GetComponentInChildren <MeshFilter>().sharedMesh; } } Debug.Assert(colliderMesh != null, $"[Nuterra] Failed to find collider mesh with name {meshColliderName}"); } // This is the only bit where the root object majorly differs from subobjects if (targetTransform == block.transform) { // Generally speaking, the root of a TT block does not have meshes, so needs to add a child // Add mesh / collider mesh sub GameObject if we have either if (mesh != null || colliderMesh != null) { GameObject meshObj = CreateMeshGameObject(targetTransform, mesh, mat, colliderMesh, physMat, supressBoxColliderFallback); } } else // However, if we are poking around in a subobject, we may want to swap out existing renderers { // If we provided a new mesh, do a full swap if (mesh != null) { targetTransform.gameObject.EnsureComponent <MeshFilter>().sharedMesh = mesh; targetTransform.gameObject.EnsureComponent <MeshRenderer>().sharedMaterial = mat; } else // If we don't want to swap out the mesh we may still want to swap out the properties of existing renderers { bool forceEmissive = TryParse(jData, "ForceEmission", false); foreach (Renderer renderer in targetTransform.GetComponents <Renderer>()) { renderer.sharedMaterial = mat; if (renderer is ParticleSystemRenderer psrenderer) { psrenderer.trailMaterial = mat; } if (forceEmissive) { MaterialSwapper.SetMaterialPropertiesOnRenderer(renderer, ManTechMaterialSwap.MaterialColour.Normal, 1f, 0); } } } // If we provided a collider mesh, do a full swap if (colliderMesh != null) { MeshCollider mc = targetTransform.gameObject.EnsureComponent <MeshCollider>(); mc.convex = true; mc.sharedMesh = colliderMesh; mc.sharedMaterial = physMat; } // If we want a box collider, try to make one from our mesh bool makeBoxCollider = GetBoolMultipleKeys(jData, false, "MakeBoxCollider", "GenerateBoxCollider"); if (makeBoxCollider) { BoxCollider bc = targetTransform.gameObject.EnsureComponent <BoxCollider>(); bc.sharedMaterial = physMat; if (mesh != null) { mesh.RecalculateBounds(); bc.size = mesh.bounds.size - Vector3.one * 0.2f; bc.center = mesh.bounds.center; } else { bc.size = Vector3.one; bc.center = Vector3.zero; } } // Weird option from TTQMM that has a fixed size sphere bool makeSphereCollider = TryParse(jData, "MakeSphereCollider", false); if (makeSphereCollider) { SphereCollider sc = targetTransform.gameObject.EnsureComponent <SphereCollider>(); sc.radius = 0.5f; sc.center = Vector3.zero; sc.sharedMaterial = physMat; } } // ------------------------------------------------------ #region Deserializers if (TryGetTokenMultipleKeys(jData, out JToken jDeserialObj, "Deserializer", "JSONBLOCK") && jDeserialObj.Type == JTokenType.Object) { JObject jDeserializer = (JObject)jDeserialObj; // TTQMM Ref: GameObjectJSON.CreateGameObject(jBlock.Deserializer, blockbuilder.Prefab); NuterraDeserializer.DeserializeIntoGameObject(jDeserializer, block.gameObject); } #endregion // ------------------------------------------------------ // ------------------------------------------------------ #region Sub objects if (jData.TryGetValue("SubObjects", out JToken jSubObjectList) && jSubObjectList.Type == JTokenType.Array) { foreach (JToken token in (JArray)jSubObjectList) { if (token.Type == JTokenType.Object) { JObject jSubObject = (JObject)token; if (TryGetStringMultipleKeys(jSubObject, out string subObjName, "SubOverrideName", "OverrideName", "ObjectName")) { GameObject subObject = (targetTransform.RecursiveFindWithProperties(subObjName) as Component)?.gameObject; bool creatingNew = subObject == null; if (subObject != null) { if (TryGetTokenMultipleKeys(jSubObject, out JToken jLayer, "Layer", "PhysicsLayer") && jLayer.Type == JTokenType.Integer) { subObject.layer = jLayer.ToObject <int>(); } } else // Reference was not matched, so we want to add a new subobject { if (subObjName.NullOrEmpty()) { subObjName = $"SubObject_{targetTransform.childCount + 1}"; } subObject = new GameObject(subObjName); subObject.transform.parent = targetTransform; subObject.transform.localPosition = Vector3.zero; subObject.transform.localRotation = Quaternion.identity; if (TryGetTokenMultipleKeys(jSubObject, out JToken jLayer, "Layer", "PhysicsLayer") && jLayer.Type == JTokenType.Integer) { subObject.layer = jLayer.ToObject <int>(); } else { subObject.layer = 8; // Globals.inst.layerTank; } } // Target acquired, lets tweak a few things bool destroyColliders = GetBoolMultipleKeys(jSubObject, false, "DestroyExistingColliders", "DestroyColliders"); if (destroyColliders) { foreach (Collider col in subObject.GetComponents <Collider>()) { UnityEngine.Object.DestroyImmediate(col); } UnityEngine.Object.DestroyImmediate(subObject.GetComponentInParents <ColliderSwapper>()); } bool destroyRenderers = GetBoolMultipleKeys(jSubObject, false, "DestroyExistingRenderer", "DestroyExistingRenderers", "DestroyRenderers"); if (destroyRenderers) { foreach (Renderer renderer in subObject.GetComponents <Renderer>()) { UnityEngine.Object.DestroyImmediate(renderer); } foreach (MeshFilter mf in subObject.GetComponents <MeshFilter>()) { UnityEngine.Object.DestroyImmediate(mf); } } // If there is already a material set on this sub object ref, use it Material matForSubObject = mat; if (!creatingNew && !destroyRenderers) { Renderer ren = subObject.GetComponent <Renderer>(); if (ren) { matForSubObject = ren.sharedMaterial; } } // Optional resize settings if (TryGetTokenMultipleKeys(jSubObject, out JToken jPos, "SubPosition", "Position") && jPos.Type == JTokenType.Object) { subObject.transform.localPosition = GetVector3(jPos); } if (TryGetTokenMultipleKeys(jSubObject, out JToken jEuler, "SubRotation", "Rotation") && jEuler.Type == JTokenType.Object) { subObject.transform.localEulerAngles = GetVector3(jEuler); } if (TryGetTokenMultipleKeys(jSubObject, out JToken jScale, "SubScale", "Scale") && jScale.Type == JTokenType.Object) { subObject.transform.localScale = GetVector3(jScale); } RecursivelyAddSubObject(block, mod, subObject.transform, jSubObject, matForSubObject, creatingNew); } else { Debug.LogError($"[Nuterra] Failed to find SubOverrideName tag in sub object JSON"); } }