Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Camera in Client only world

Discussion in 'Entity Component System' started by SupinePandora43, Nov 22, 2020.

  1. SupinePandora43

    SupinePandora43

    Joined:
    May 13, 2019
    Posts:
    18
    It's pretty easy to do in regular ECS, without NetCode.
    But in NetCode, entity representing Player spawned from prefab, and ConvertToClientServerEntity for other gameobjects is deprecated.
    I don't have know how create Camera entity on Client, and attach it to Player entity.

    // It is possible without system creating it?
    // just placing camera object somewhere in scene/prefab?
     
  2. AdamBebko

    AdamBebko

    Joined:
    Apr 8, 2016
    Posts:
    158
    I asked a similar question earlier, no answers. It's currently not clear how to maintain different client and server worlds for standard gameobjects/monobehaviours.
     
  3. kanesteven

    kanesteven

    Joined:
    Aug 30, 2018
    Posts:
    34
    @SupinePandora43 @AdamBebko Write a system that lazily-instantiates one from the client only. Such a system is extremely useful for a wide range of client-only rendering. A system that looks like this might be as follows:


    Code (CSharp):
    1. [UpdateInGroup(typeof(ClientSimulationSystemGroup))]
    2. public class PlayerCameraSystem: ComponentSystem {
    3.   public class PlayerCameraInstance : ISystemStateComponent {
    4.     public Camera Instance;
    5.   }
    6.  
    7.   protected override void OnUpdate() {
    8.     // probably a static singleton in your project
    9.     Camera cameraPrefab = GetMyCameraPrefabSomehow();
    10.  
    11.     Entities
    12.     .WithName("Instantiate_Player_Camera")
    13.     .WithAll<Player>()
    14.     .WithNone<PlayerCameraInstance>()
    15.     .ForEach((Entity e) => {
    16.       EntityManager.AddComponentData(e, new PlayerCameraInstance {
    17.         Instance = Camera.Instantiate(cameraPrefab)
    18.       });
    19.     })
    20.     .WithoutBurst()
    21.     .Run();
    22.  
    23.     Entities
    24.     .WithName("Destroy_Player_Camera_Instance")
    25.     .WithAll<PlayerCameraInstance>()
    26.     .WithNone<Player>()
    27.     .ForEach((Entity e, PlayerCameraInstance instance) => {
    28.       GameObject.Destroy(instance.Instance);
    29.       EntityManager.RemoveComponent<PlayerCameraInstance>(e);
    30.     })
    31.     .WithoutBurst()
    32.     .Run();
    33.   }
    34. }
    If you don't want the camera actually attached to the player entity just create some other proxy entity called "PlayerCameraProxy" or something that you detect instead of the Player to instantiate this camera.

    Once you have the camera, access it and its associated Entity as you would any other normal Component. You will ONLY be able to access it from a job that runs .WithoutBurst().Run() though as managed objects ( the Camera ) can only be accessed from the main thread.
     
  4. AdamBebko

    AdamBebko

    Joined:
    Apr 8, 2016
    Posts:
    158
    Thanks for the ideas. Sounds promising. But I think one of the big barriers to this is the “Somehow” in how to get references to prefabs and the like. Do you know any easy ways to do that? How do you get static references to prefabs? I only know of serialized and public fields.

    One question: why do you query the entity by name? I’ve never seen that before.

    Also, I’ve never heard of ISystemStateComponent. Something to read up on I guess.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,449
    He's just naming the job for debugging purposes.
     
    AdamBebko likes this.
  6. kanesteven

    kanesteven

    Joined:
    Aug 30, 2018
    Posts:
    34
    Getting access to GameObjects inside Systems can be done about a bazillion ways. The dumbest and simplest way is probably this:


    Code (CSharp):
    1. public class MyPrefabs : MonoBehaviour {
    2.   public static MyPrefabs Instance;
    3.  
    4.   public GameObject MyOkPrefab;
    5.   public GameObject MyDecentPrefab;
    6.  
    7.   public void Awake() {
    8.     Instance = this;
    9.   }
    10. }
     
  7. AdamBebko

    AdamBebko

    Joined:
    Apr 8, 2016
    Posts:
    158
    Ahh yes. Thank you.