For a school project we got scripts from our teacher however for me it gives errors (my teacher or classmates don't). Can anyone see what is wrong? Do I have to change settings in unity?
error message:
UnityException: Internal_CreateGameObject is not allowed to be called during serialization, call it from Awake or Start instead. Called from MonoBehaviour 'SceneMgr' on game object 'SceneMgr'.
See "Script Serialization" page in the Unity Manual for further details.
Building..ctor () (at Assets/Scripts/Building.cs:33)
and I get this warning:
Serialization depth limit 10 exceeded at 'Building.myObject'. There may be an object composition cycle in one or more of your serialized classes.
Serialization hierarchy:
11: Building.myObject
10: Building.floors
9: Building.floors
8: Building.floors
7: Building.floors
6: Building.floors
5: Building.floors
4: Building.floors
3: Building.floors
2: Building.floors
1: Building.floors
0: SceneMgr.selectedBuilding
Scripts 1 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization;
using System;
using System.Xml.Serialization;
// Remark: all custom building textures must be place in the Assets/Resources/BuildingTextures folder to work
[Serializable]
public struct customMaterial
{
public bool textureIsCustom;
public string textureName;
public float tilingX, tilingY;
public float offsetX, offsetY;
}
[Serializable]
public class Building
{
[XmlAttribute]
public string buildingType;
[XmlIgnoreAttribute]
GameObject myObject;
public customMaterial customMaterial;
public List floors;
public Building()
{
GameObject = new GameObject();
buildingType = "none";
customMaterial.textureName = null;
customMaterial.tilingX = 1;
customMaterial.tilingY = 1;
floors = new List();
}
public string Type
{
get { return buildingType; }
set { buildingType = value; }
}
[XmlIgnoreAttribute]
public GameObject GameObject
{
get { return myObject; }
set { myObject = value; }
}
public Vector3 Position
{
get { return myObject.transform.position; }
set
{
myObject.transform.position = value;
for (int i = 0; i < floors.Count; i++)
{
floors[i].Position = new Vector3(myObject.transform.position.x,
myObject.transform.position.y + (i + 1) * 3,
myObject.transform.position.z);
}
}
}
public Quaternion Rotation
{
get { return myObject.transform.rotation; }
set { myObject.transform.rotation = value; }
}
public Vector3 Scale
{
get { return myObject.transform.localScale; }
set { myObject.transform.localScale = value; }
}
public void SetMaterialTiling(float x, float y)
{
customMaterial.textureIsCustom = true;
customMaterial.tilingX = x;
customMaterial.tilingY = y;
}
public void SetMaterialOffset(float x, float y)
{
customMaterial.textureIsCustom = true;
customMaterial.offsetX = x;
customMaterial.offsetY = y;
}
public void SetTextureName(string texName)
{
customMaterial.textureIsCustom = true;
customMaterial.textureName = texName;
}
public void UpdateMaterial()
{
Material m = new Material(myObject.GetComponent().material);
if (customMaterial.textureIsCustom)
{
Texture t = Resources.Load("BuildingTextures/" + customMaterial.textureName);
m.mainTexture = t;
m.mainTextureScale = new Vector2(customMaterial.tilingX, customMaterial.tilingY);
m.mainTextureOffset = new Vector2(customMaterial.offsetX, customMaterial.offsetY);
}
myObject.GetComponent().material = m;
}
public void AddFloor(Building newFloor)
{
floors.Add(newFloor);
}
public int NumFloors()
{
return floors.Count + 1;
}
public void DestroyFloors()
{
while (floors.Count > 0)
{
//delete gameObjects
GameObject.Destroy(floors[floors.Count - 1].GameObject);
//remove from list
floors.RemoveAt(floors.Count - 1);
}
}
}
script 2:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
using UnityEngine.UI;
//todo add tag maincamera to all cameras
//todo fill in all public variables in unity
//todo for custom buiding textures => place them in Assets/Resources/BuildingTextures folder
//todo create prefabs that have their base on the ground instead of in the middle of the object
//example objects: https://free3d.com/3d-model/array-house-example-3033.html
public enum SceneMode
{
cityMode,
buildingMode
}
public class SceneMgr : MonoBehaviour
{
public static List myBuildings;
public string[] buildingTypes;//number must match number of prefabs
public UnityEngine.Object[] buildingPrefabs;//number must match number of buildingtype strings
public Material defaultBuildingMaterial;
public SceneMode sceneMode = SceneMode.cityMode;
public GameObject buildingPropertiesUI;
public Building selectedBuilding;
// Start is called before the first frame update
void Start()
{
myBuildings = new List();
}
// Update is called once per frame
void Update()
{
//switch between modes, activate correct Canvasses
/* if (sceneMode == SceneMode.cityMode )
{
buildingPropertiesUI.SetActive(false);
}
else if (sceneMode == SceneMode.buildingMode && !buildingPropertiesUI.activeSelf)
{
buildingPropertiesUI.SetActive(true);
}*/
//handle object properties in UI
/* if (sceneMode == SceneMode.buildingMode)
{
if (selectedBuilding != null )
{
//get the text gameobject that should hold the posx in text
InputField posxText = GameObject.FindGameObjectWithTag("PosX").GetComponent();
posxText.text = selectedBuilding.Position.x.ToString();
Slider rotator = GameObject.FindGameObjectWithTag("Rotation").GetComponent();
rotator.value = selectedBuilding.Rotation.eulerAngles.y;
}
}
else
{
}*/
HandleTerrainClicks();
if (Input.GetKeyDown(KeyCode.Alpha1) && sceneMode == SceneMode.cityMode)
{
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[0]);
Building myBuilding = new Building();
myBuilding.Type = buildingTypes[0];//block
myBuilding.GameObject = newGameObject;
myBuilding.Position = new Vector3(-30, 2.5f, 0);
myBuilding.Rotation = Quaternion.identity; //this means no rotation
myBuilding.Scale = new Vector3(4, 10, 4); //scale is set to 1 on all ocasions
//create and set custom material
myBuilding.SetMaterialTiling(2, 2);
myBuilding.SetMaterialOffset(.5f, .5f);
myBuilding.SetTextureName("appartment");
myBuilding.UpdateMaterial();
myBuildings.Add(myBuilding);
}
if (Input.GetKeyDown(KeyCode.Alpha2) && sceneMode == SceneMode.cityMode)
{
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[1]);
Building myBuilding = new Building();
myBuilding.Type = buildingTypes[1];//cylinder
myBuilding.GameObject = newGameObject;
myBuilding.Position = new Vector3(-30, 2.5f, 10);
myBuilding.Rotation = Quaternion.Euler(-90, 30, 0); //rotate because default mesh is rotated
myBuilding.Scale = 30 * Vector3.one; //scale is set to 1 on all ocasions
//keep original material
myBuildings.Add(myBuilding);
}
if (Input.GetKeyDown(KeyCode.Alpha3) && sceneMode == SceneMode.cityMode)
{
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[2]);
Building myBuilding = new Building();
myBuilding.Type = buildingTypes[2];//sphere
myBuilding.GameObject = newGameObject;
myBuilding.Position = new Vector3(-30, 2.5f, 20);
myBuilding.Rotation = Quaternion.Euler(-90, 0, 0); //rotate because default mesh is rotated
myBuilding.Scale = 30 * Vector3.one; //scale is set to 1 on all ocasions
//keep original material
myBuildings.Add(myBuilding);
}
if (Input.GetKeyDown(KeyCode.F))
{
AddFloorToSelectedBuilding("TEST");
}
if (Input.GetKeyDown(KeyCode.C))//clear buildings
{
ClearBuildings();
}
if (Input.GetKeyDown(KeyCode.S))//save buildings to file
{
if (WriteToFile("buildings.xml"))
{
Debug.Log("Successfully written to buildings.xml");
}
}
if (Input.GetKeyDown(KeyCode.L))//load buildings to file
{
if (ReadFromFile("buildings.xml"))
{
Debug.Log("Successfully created buildings from buildings.xml");
}
}
GameObject obsolete = GameObject.Find("New Game Object");
if (obsolete != null)
{
GameObject.Destroy(obsolete);
}
}
public bool WriteToFile(string filename)
{
bool succeeded = false;
StreamWriter writer = null;
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List));
writer = new StreamWriter(filename);
serializer.Serialize(writer, myBuildings);
succeeded = true;
}
catch (Exception e)
{
Debug.Log("Exception writing XML: " + e.Message);
succeeded = false;
}
finally
{
if (writer != null)
{
writer.Close();
}
}
return succeeded;
}
public bool ReadFromFile(string filename)
{
ClearBuildings();
bool succeeded = false;
myBuildings = new List();
StreamReader reader = null;
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List));
reader = new StreamReader(filename);
myBuildings = (List)serializer.Deserialize(reader);
for (int i = 0; i < myBuildings.Count; i++)
{
int prefabID = GetPrefabIndexFromTypeName(myBuildings[i].Type);
if (prefabID >= 0 && prefabID < myBuildings.Count)
{
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[prefabID]);
newGameObject.transform.position = myBuildings[i].Position;
newGameObject.transform.rotation = myBuildings[i].Rotation; //this means no rotation
newGameObject.transform.localScale = myBuildings[i].Scale; //scale is set to 1 on all ocasions
myBuildings[i].GameObject = newGameObject;
myBuildings[i].UpdateMaterial();
int numFloors = myBuildings[i].floors.Count;
for (int f = 0; f < numFloors; f++)
{
int prefabNum = GetPrefabIndexFromTypeName(myBuildings[i].floors[f].Type);
GameObject newFloorObject = (GameObject)GameObject.Instantiate(buildingPrefabs[prefabNum]);
Building myFloor = new Building();
myFloor.Type = myBuildings[i].floors[f].Type;//block
myFloor.GameObject = newFloorObject;
myFloor.Position = myBuildings[i].floors[f].Position;
myFloor.Rotation = myBuildings[i].floors[f].Rotation;
myFloor.Scale = myBuildings[i].floors[f].Scale;
myBuildings[i].AddFloor(myFloor);
}
succeeded = true;
}
else
{
Debug.Log("Could not create building, wrong type/prefab id num?");
succeeded = false;
}
}
}
catch (Exception e)
{
Debug.Log("Exception reading XML: " + e.Message);
succeeded = false;
}
finally
{
if (reader != null)
{
reader.Close();
}
}
return succeeded;
}
public void ClearBuildings()
{
Debug.Log("removing " + myBuildings.Count + " buildings");
while (myBuildings.Count > 0)
{
//delete gameObjects
myBuildings[myBuildings.Count - 1].DestroyFloors();
GameObject.Destroy(myBuildings[myBuildings.Count - 1].GameObject);
//remove from list
myBuildings.RemoveAt(myBuildings.Count - 1);
}
Debug.Log("All buildings removed");
sceneMode = SceneMode.cityMode;
}
public static Building GetBuildingFromObject(GameObject objectToFind)
{
foreach (Building b in myBuildings)
{
if (objectToFind == b.GameObject)
{
return b;
}
}
//if not found
return null;
}
public int GetPrefabIndexFromTypeName(string buildingTypeName)
{
return Array.IndexOf(buildingTypes, buildingTypeName);
}
void HandleTerrainClicks()
{
//check if ground plane is clicked
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
if (hit.collider.gameObject.tag == "Ground")
{
//switch to city mode
sceneMode = SceneMode.cityMode;
transform.position = hit.point;
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[0]);
Building myBuilding = new Building();
myBuilding.Type = buildingTypes[0];//block
myBuilding.GameObject = newGameObject;
//myBuilding.Position = hit.point; //where the terrain was hit
myBuilding.Position = new Vector3(Mathf.Round(hit.point.x), Mathf.Round(hit.point.y), Mathf.Round(hit.point.z));
myBuilding.Rotation = Quaternion.identity; //this means no rotation
myBuilding.Scale = new Vector3(4, 10, 4); //scale is set to 1 on all ocasions
myBuilding.SetMaterialTiling(2, 2);
myBuilding.SetTextureName("appartment");
myBuilding.UpdateMaterial();
myBuildings.Add(myBuilding);
}
else
{
}
}
}
}
public void MoveBuildingPlusX()
{
selectedBuilding.Position = new Vector3(selectedBuilding.Position.x + 1,
selectedBuilding.Position.y,
selectedBuilding.Position.z);
}
public void MoveBuildingMinX()
{
selectedBuilding.Position = new Vector3(selectedBuilding.Position.x - 1,
selectedBuilding.Position.y,
selectedBuilding.Position.z);
}
public void DeleteSelectedBuilding()
{
if (selectedBuilding != null)
{
//delete gameObjects
GameObject.Destroy(selectedBuilding.GameObject);
//remove from list
myBuildings.Remove(selectedBuilding);
}
selectedBuilding = null;
sceneMode = SceneMode.cityMode;
}
public void AddFloorToSelectedBuilding(string prefabID)
{
if (selectedBuilding != null)
{
GameObject newGameObject = (GameObject)GameObject.Instantiate(buildingPrefabs[0]);
Building myBuilding = new Building();
myBuilding.Type = buildingTypes[0];//block
myBuilding.GameObject = newGameObject;
myBuilding.Position = selectedBuilding.Position + new Vector3(0, 3, 0) * selectedBuilding.NumFloors();
myBuilding.Rotation = selectedBuilding.Rotation; //this means no rotation
myBuilding.Scale = selectedBuilding.Scale; //scale is set to 1 on all ocasions
selectedBuilding.AddFloor(myBuilding);
}
}
}
↧