I use an entity as a Bridge that gives some information to Camera and Spawner gameobjects. To add the Camera as a follower of this Bridge entity, I use this pattern:
Camera has a monobehavior with a public Entity field;
the Bridge entity is a converting gameobject that adds itself to the above Entity field during conversion:
public class FollowGameObject : MonoBehaviour, IConvertGameObjectToEntity
{
public GameObject Follower;
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
FollowEntity followEntity = Follower.GetComponent<FollowEntity>();
followEntity.EntityToFollow = entity;
}
}
This entity Bridge tells me when to load a new scene, to do some level design. For example, when I reach a certain task in scene A, in one of my systems I set a flag in the Bridge. Then, the follower gameobject should notice this in LateUpdate() and try to load a new scene say B:
public class FollowEntity : MonoBehaviour
{
public Entity EntityToFollow;
public float3 offset;
private EntityManager _entityManager;
void Start()
{
_entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
}
void LateUpdate()
if (EntityToFollow == null)
return;
Translation entityPosition = _entityManager.GetComponentData<Translation>(EntityToFollow);
transform.position = entityPosition.Value + offset;
if(_entityManager.GetComponentData<ChangeScene>(EntityToFollow).Value)
{
_entityManager.DestroyEntity(_entityManager.UniversalQuery);
SceneManager.LoadScene("Level2Development");
}
}
}
Iām testing this just reloading an identical scene. The main problem is that when the new scene is loaded, the Camera gameobject canāt find the Bridge in its EntityToFollow field and I get āThe entity does not existā error⦠My guess is that the conversion happens too late, so the above code in the Convert function, in which the entity adds itself to GameObject, happens after the GameObject throws an error because because its field is null.
Any workaround to this? I hope my architecture is not too bad⦠but any architectural suggestion would be appreciated. also I prefer to stay with legacy Unity scene loading/unloading from monobehaviors because, yā knowā¦
Thank you in advance
I think you might be missing the IDeclareReferencedPrefabs on your conversion.
public GameObject Follower;
public void DeclareReferencedPrefabs(List<GameObject> referencedPrefabs)
{
referencedPrefabs.Add(Follower);
}
And maybe
followerEntity = conversionSystem.GetPrimaryEntity(Follower);
Other scene data transfer methods I use (because it works not because I would recommend them):
To move data between scenes I use a normal game object singleton with some static fields and a ādonāt destroy on loadā. This object is in every scene and when it is loaded the singleton is replaced with the new object and the data of the old object is copied to the new object. This allows to get correct game object references from normal objects in the scene (like the camera).
Thank you for your response! What Iām missing reading your solution is that I need a follower GameObject that never converts to entity. My Camera never converts, still needs to reference for an entity to follow its translation. So, nothing wrong with my above workflow for the first scene, but when I destroy all entities and reload the scene, Camera loses its reference for just one frame, throws an error, then gets the reference right (because conversion happened) and starts to follow the entity. But I wished to know how to avoid this first frame error and get the reference immediately (maybe with GetPrimaryEntity, but idk where to put it in the Camera Monobehavior since it canāt implement IConvertGameObjectToEntity).
Oke, what I do for this (if i understand your issue correctly) is have a ādonāt destroy on loadā Singleton āGameManagerā within every scene that holds the references all mono objects of the scene like the camera.
public class GameManager : MonoBehaviour
{
public static GameManager main;
public GameObject VrPlayer;
public bool pauseToggelReleased = true;
private void Awake()
{
var old = main;
main = this;
DontDestroyOnLoad(gameObject);
if (old != null)
{
// if you want to keep data from the previous instance
pauseToggelReleased = old.pauseToggelReleased;
Destroy(old.gameObject);
}
}
}
VRplayer will now always reference the GameObject you have in the loaded scene. (you could add a isNewGamemanagerLoaded bool that you set to false before loading and to true in the awake() function. So you will have something to check before trying to get the data, should the old GameManager still be the one in the singleton)
In the OnUpdate() of a system, in the non-burst main thread part, you can now access the data and put it in a variable which you can use in bursted/scheduled code.