AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
PrefabSpawnManager.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using UnityEngine;
7 using HoloToolkit.Unity;
8 
9 namespace HoloToolkit.Sharing.Spawning
10 {
14  [Serializable]
15  public struct PrefabToDataModel
16  {
17  // TODO Should this be a Type? Or at least have a custom editor to have a dropdown list
18  public string DataModelClassName;
19  public GameObject Prefab;
20  }
21 
26  public class PrefabSpawnManager : SpawnManager<SyncSpawnedObject>
27  {
32  [SerializeField]
33  private List<PrefabToDataModel> spawnablePrefabs = null;
34 
35  private Dictionary<string, GameObject> typeToPrefab;
36 
41  private int objectCreationCounter;
42 
43  protected override void Start()
44  {
45  base.Start();
46 
47  InitializePrefabs();
48  }
49 
50  private void InitializePrefabs()
51  {
52  typeToPrefab = new Dictionary<string, GameObject>(spawnablePrefabs.Count);
53  for (int i = 0; i < spawnablePrefabs.Count; i++)
54  {
55  typeToPrefab.Add(spawnablePrefabs[i].DataModelClassName, spawnablePrefabs[i].Prefab);
56  }
57  }
58 
59  protected override void InstantiateFromNetwork(SyncSpawnedObject spawnedObject)
60  {
61  GameObject prefab = GetPrefab(spawnedObject, null);
62  if (!prefab)
63  {
64  return;
65  }
66 
67  // Find the parent object
68  GameObject parent = null;
69  if (!string.IsNullOrEmpty(spawnedObject.ParentPath.Value))
70  {
71  parent = GameObject.Find(spawnedObject.ParentPath.Value);
72  if (parent == null)
73  {
74  Debug.LogErrorFormat("Parent object '{0}' could not be found to instantiate object.", spawnedObject.ParentPath);
75  return;
76  }
77  }
78 
79  CreatePrefabInstance(spawnedObject, prefab, parent, spawnedObject.Name.Value);
80  }
81 
82  protected override void RemoveFromNetwork(SyncSpawnedObject removedObject)
83  {
84  if (removedObject.GameObject != null)
85  {
86  Destroy(removedObject.GameObject);
87  removedObject.GameObject = null;
88  }
89  }
90 
91  protected virtual string CreateInstanceName(string baseName)
92  {
93  string instanceName = string.Format("{0}{1}_{2}", baseName, objectCreationCounter.ToString(), NetworkManager.AppInstanceUniqueId);
94  objectCreationCounter++;
95  return instanceName;
96  }
97 
98  protected virtual string GetPrefabLookupKey(SyncSpawnedObject dataModel, string baseName)
99  {
100  return dataModel.GetType().Name;
101  }
102 
103  protected virtual GameObject GetPrefab(SyncSpawnedObject dataModel, string baseName)
104  {
105  GameObject prefabToSpawn;
106  string dataModelTypeName = GetPrefabLookupKey(dataModel, baseName);
107  if (dataModelTypeName == null || !typeToPrefab.TryGetValue(dataModelTypeName, out prefabToSpawn))
108  {
109  Debug.LogErrorFormat("Trying to instantiate an object from unregistered data model {0}.", dataModelTypeName);
110  return null;
111  }
112  return prefabToSpawn;
113  }
114 
129  public bool Spawn(SyncSpawnedObject dataModel, Vector3 localPosition, Quaternion localRotation, Vector3? localScale, GameObject parent, string baseName, bool isOwnedLocally)
130  {
131  if (SyncSource == null)
132  {
133  Debug.LogError("Can't spawn an object: PrefabSpawnManager is not initialized.");
134  return false;
135  }
136 
137  if (dataModel == null)
138  {
139  Debug.LogError("Can't spawn an object: dataModel argument is null.");
140  return false;
141  }
142 
143  if (parent == null)
144  {
145  parent = gameObject;
146  }
147 
148  // Validate that the prefab is valid
149  GameObject prefabToSpawn = GetPrefab(dataModel, baseName);
150  if (!prefabToSpawn)
151  {
152  return false;
153  }
154 
155  // Get a name for the object to create
156  string instanceName = CreateInstanceName(baseName);
157 
158  // Add the data model object to the networked array, for networking and history purposes
159  dataModel.Initialize(instanceName, parent.transform.GetFullPath("/"));
160  dataModel.Transform.Position.Value = localPosition;
161  dataModel.Transform.Rotation.Value = localRotation;
162  if (localScale.HasValue)
163  {
164  dataModel.Transform.Scale.Value = localScale.Value;
165  }
166  else
167  {
168  dataModel.Transform.Scale.Value = prefabToSpawn.transform.localScale;
169  }
170 
171  User owner = null;
172  if (isOwnedLocally)
173  {
174  owner = SharingStage.Instance.Manager.GetLocalUser();
175  }
176 
177  SyncSource.AddObject(dataModel, owner);
178  return true;
179  }
180 
194  public bool Spawn(SyncSpawnedObject dataModel, Vector3 localPosition, Quaternion localRotation, GameObject parent, string baseName, bool isOwnedLocally)
195  {
196  return Spawn(dataModel, localPosition, localRotation, null, parent, baseName, isOwnedLocally);
197  }
198 
199  protected override void SetDataModelSource()
200  {
201  SyncSource = NetworkManager.Root.InstantiatedPrefabs;
202  }
203 
204  public override void Delete(SyncSpawnedObject objectToDelete)
205  {
206  SyncSource.RemoveObject(objectToDelete);
207  }
208 
217  protected virtual GameObject CreatePrefabInstance(SyncSpawnedObject dataModel, GameObject prefabToInstantiate, GameObject parentObject, string objectName)
218  {
219  GameObject instance = Instantiate(prefabToInstantiate, dataModel.Transform.Position.Value, dataModel.Transform.Rotation.Value);
220  instance.transform.localScale = dataModel.Transform.Scale.Value;
221  instance.transform.SetParent(parentObject.transform, false);
222  instance.gameObject.name = objectName;
223 
224  dataModel.GameObject = instance;
225 
226  // Set the data model on the various ISyncModelAccessor components of the spawned GameObject
227  ISyncModelAccessor[] syncModelAccessors = instance.GetComponentsInChildren<ISyncModelAccessor>(true);
228  if (syncModelAccessors.Length <= 0)
229  {
230  // If no ISyncModelAccessor component exists, create a default one that gives access to the SyncObject instance
231  ISyncModelAccessor defaultAccessor = instance.EnsureComponent<DefaultSyncModelAccessor>();
232  defaultAccessor.SetSyncModel(dataModel);
233  }
234 
235  for (int i = 0; i < syncModelAccessors.Length; i++)
236  {
237  syncModelAccessors[i].SetSyncModel(dataModel);
238  }
239 
240  // Setup the transform synchronization
241  TransformSynchronizer transformSynchronizer = instance.EnsureComponent<TransformSynchronizer>();
242  transformSynchronizer.TransformDataModel = dataModel.Transform;
243 
244  return instance;
245  }
246  }
247 }
virtual GameObject GetPrefab(SyncSpawnedObject dataModel, string baseName)
bool Spawn(SyncSpawnedObject dataModel, Vector3 localPosition, Quaternion localRotation, Vector3? localScale, GameObject parent, string baseName, bool isOwnedLocally)
Spawns content with the given parent. If no parent is specified it will be parented to the spawn mana...
Synchronizer to update and broadcast a transform object through our data model.
void SetSyncModel(SyncObject syncObject)
Sets the synchronized data model to use for this object.
virtual void Initialize(string name, string parentPath)
SyncTransform Transform
Transform (position, rotation, and scale) for the object.
virtual GameObject CreatePrefabInstance(SyncSpawnedObject dataModel, GameObject prefabToInstantiate, GameObject parentObject, string objectName)
Create a prefab instance in the scene, in reaction to data being added to the data model...
Spawn manager that creates a GameObject based on a prefab when a new SyncSpawnedObject is created in ...
virtual string GetPrefabLookupKey(SyncSpawnedObject dataModel, string baseName)
A SpawnedObject contains all the information needed for another device to spawn an object in the same...
static T Instance
Returns the Singleton instance of the classes type. If no instance is found, then we search for an in...
Definition: Singleton.cs:26
Interface that allows a components of a game object access the shared data model set by a SpawnManage...
override void InstantiateFromNetwork(SyncSpawnedObject spawnedObject)
A SpawnManager is in charge of spawning the appropriate objects based on changes to an array of data ...
Definition: SpawnManager.cs:17
SyncString ParentPath
Path to the parent object in the game object.
virtual string CreateInstanceName(string baseName)
bool Spawn(SyncSpawnedObject dataModel, Vector3 localPosition, Quaternion localRotation, GameObject parent, string baseName, bool isOwnedLocally)
Instantiate data model on the network with the given parent. If no parent is specified it will be par...
Structure linking a prefab and a data model class.
The SharingStage is in charge of managing the core networking layer for the application.
Definition: SharingStage.cs:14
override void Delete(SyncSpawnedObject objectToDelete)
override void SetDataModelSource()
Sets the data model source for the spawn manager.
override void RemoveFromNetwork(SyncSpawnedObject removedObject)
SyncTransform TransformDataModel
Data model to which this transform synchronization is tied to.
Default implementation of a MonoBehaviour that allows other components of a game object access the sh...