Search Unity

How to represent a player camera in hybrid ECS?

Discussion in 'Entity Component System' started by Cubic_Creo, May 4, 2018.

  1. Cubic_Creo

    Cubic_Creo

    Joined:
    Oct 13, 2014
    Posts:
    47
    This is probably an easy one for you guys! Let's say I have a player GameObject that I'm instantiating. It has a GameObjectEntity on it, and so I grab the entity and add a PlayerInput component. I have a PlayerInputSystem set up, no problem. But now let's say I have a camera GameObject as a child of that player GameObject. How would I represent/access that?

    When I instantiate the player, do I need to GetComponentInChildren<Camera>(), then grab the camera's entity and assign that to a player.camera entity? Or maybe I should have a "PlayerSetup" MonoBehaviour on the player GameObject that holds a reference to the child camera? Or am I completely missing something fundamental about hybrid ECS?
     
  2. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    Hi,

    there are many ways to do this...
    So I will show you how I handle my camera (3. person game)
    Code (CSharp):
    1.  
    2. public class ThirdPersonCamera : MonoBehaviour {
    3.     public Transform stayTransform;
    4.     public Transform crouchTransform;
    5.     [HideInInspector]
    6.     public float verticalAngle;
    7. }
    8.  
    9. public class ThirdPersonCameraSystem : ComponentSystem {
    10.     struct CameraData {
    11.         public int Length;
    12.         public ComponentArray<Transform> transforms;
    13.         public ComponentArray<ThirdPersonCamera> thirdPersonCam;
    14.         public ComponentArray<Cinemachine.CinemachineStateDrivenCamera> stateDrivenCamera;
    15.     }
    16.     struct PlayerData {
    17.         public int Length;
    18.         public ComponentArray<Transform> transforms;
    19.         public ComponentDataArray<PlayerInput> input;
    20.         public ComponentArray<Animator> animators;
    21.     }
    22.     [Inject] CameraData cameraData;
    23.     [Inject] PlayerData playerData;
    24.    
    25.     protected override void OnUpdate() {
    26.         if(playerData.Length == 0) {
    27.             return;
    28.         }
    29.  
    30.         float rotationSpeed = Bootstrap.GameSettings.HorizontalLookSpeed;
    31.  
    32.         PlayerInput input = playerData.input[0];
    33.         Transform playerTransform = playerData.transforms[0];
    34.         Animator animator = playerData.animators[0];
    35.         float dt = Time.deltaTime;
    36.         for (int i = 0; i < cameraData.Length; i++) {
    37.             cameraData.stateDrivenCamera[i].m_AnimatedTarget = animator;
    38.             cameraData.transforms[i].position = playerTransform.position;
    39.             cameraData.transforms[i].Rotate(new Vector3(0, input.look.x, 0) * rotationSpeed * dt);
    40.  
    41.             ThirdPersonCamera thirdPersonCam = cameraData.thirdPersonCam[i];
    42.  
    43.             thirdPersonCam.verticalAngle += input.look.y * rotationSpeed * dt;
    44.             thirdPersonCam.verticalAngle = Mathf.Clamp(thirdPersonCam.verticalAngle, -70, 70);
    45.  
    46.             Quaternion rotation = Quaternion.Euler(-thirdPersonCam.verticalAngle, 0, 0);
    47.             thirdPersonCam.stayTransform.localRotation = rotation;
    48.             thirdPersonCam.crouchTransform.localRotation = rotation;
    49.         }
    50.     }
    51. }
     
    RaL and vanxining like this.
  3. Cubic_Creo

    Cubic_Creo

    Joined:
    Oct 13, 2014
    Posts:
    47
    Thanks. That's very helpful.

    Looks like the solution above would work if you have a single player. But say I want to build a game with a bunch of players, some AI and some controlled by humans, and I want to move each character's head to indicate where they're looking. In that case it seems I would need to have some sort of relationship between each character and their head. Each character would know where it wants to look, and then each would tell its head where to point. Any thoughts on how that sort of relationship could be set up?

    It seems to work to have an Entity as a field in an IComponentData struct (ie it compiles). It seems like that might be a way to set up a relationship between character and head. But I haven't quite figured out yet where or how to assign a value to that entity field. My first instinct is to want to assign it when spawning a character, but I haven't found a way to to assign an Entity field in such a way that it persists.

    Maybe I'm missing something obvious. Maybe I'm overcomplicating things. Help? :)
     
  4. vanxining

    vanxining

    Joined:
    Mar 29, 2018
    Posts:
    20
    I'm a newbie, but the transform of each game object has a "forward" field which may meet your requirement.
     
  5. Cubic_Creo

    Cubic_Creo

    Joined:
    Oct 13, 2014
    Posts:
    47
    Thanks. What I'm really looking for is a way to set up relationships in ECS, or if not that, then another way of thinking about relationships in the context of ECS. Before I can do anything with the transform, I need to have access to the transform.
     
  6. mhernandez88

    mhernandez88

    Joined:
    Jul 20, 2016
    Posts:
    38
    In case you never figured it out or need a refresher, heres a video.