Improbable Icon

Cant get Reader/Writer Enabled

Hi,
I have problems trying to achieve server-authoritative movement. I made a player prefab, attached to PlayerInputSender class(intended to be handled by clientWorker) and PlayerMover class (handled by GameLogicWorker).
When I instantiate player (by EnableStandardGameObjectCreation) with ClientConnector, PlayerInputSender is enabled but PlayerMover isn’t.
When I instantiate player with GameLogicWorker, PlayerMover is enabled but PlayerInputSender isn’t.

PlayerInputSender class(intended to be handled by clientWorker)

   using BlankProject;

    using Improbable;

    using Improbable.Gdk.Core;

    using Improbable.Gdk.Subscriptions;

    using Improbable.Pickups;

    using UnityEngine;

    public class PlayerInputSender : MonoBehaviour {

        [Require] private PlayerInputWriter PlayerInputWriter1;

        [Require] private AcltestReader acl;

        [Require] private Improbable.PositionWriter PositionWriter1;

        void Update () {

            var xAxis1 = Input.GetAxis ("Horizontal");

            var yAxis1 = Input.GetAxis ("Vertical");

            var update = new PlayerInput.Update { X = xAxis1, Y = yAxis1 };

            PlayerInputWriter1.SendUpdate (update);

            var positionUpdate = new Position.Update {

                Coords = new Coordinates {

                X =  acl.Data.X, Y = acl.Data.Y, Z = acl.Data.Z

                }

            };

            PositionWriter1.SendUpdate (positionUpdate);

        }

    }

PlayerMover (for Gamelogicconnecter)

using System;

using System.Collections;

using System.Collections.Generic;

using BlankProject;

using Improbable;

using Improbable.Gdk.Core;

using Improbable.Gdk.Subscriptions;

using Improbable.Pickups;

using Unity.Entities;

using UnityEngine;

public class PlayerMover : MonoBehaviour {

    [Require] private AcltestWriter Acltestwr;

    [Require] private PlayerInputReader PlayerInputReader1;

    public const int PlayerAcceleration = 10;

    private Rigidbody rigidbody;

    void OnEnable () {

        rigidbody = GetComponent<Rigidbody> ();

 
    }

    void FixedUpdate () {

        var direction = new Vector3 (PlayerInputReader1.Data.X, 0, PlayerInputReader1.Data.Y);

        rigidbody.AddForce (direction * PlayerAcceleration);

        var pos = rigidbody.position;

        var positionUpdate = new Acltest.Update {

            X = pos.x, Y = pos.y, Z = pos.z

        };

        Acltestwr.SendUpdate (positionUpdate);

    }

}

EntityTemplate

public static EntityTemplate CreatePlayerEntityTemplate (EntityId entityId, string workerId, byte[] serializedArguments) {

            var clientAttribute = EntityTemplate.GetWorkerAccessAttribute (workerId);

            var serverAttribute = UnityGameLogicConnector.WorkerType;

            var template = new EntityTemplate ();

            template.AddComponent (new Position.Snapshot (), clientAttribute);

            template.AddComponent (new Metadata.Snapshot ("Player"), serverAttribute);

            template.AddComponent (new PlayerInput.Snapshot (x: 0, y: 0), clientAttribute);

            template.AddComponent (new Acltest.Snapshot (x:0,y:0,z:0), serverAttribute);

            PlayerLifecycleHelper.AddPlayerLifecycleComponents (template, workerId, serverAttribute);

            template.SetReadAccess (UnityClientConnector.WorkerType, MobileClientWorkerConnector.WorkerType, serverAttribute);

            template.SetComponentWriteAccess (EntityAcl.ComponentId, serverAttribute);

            return template;

        }

Please help me!
Similar : Transform Synchronization module and player input to move player

Hello @Henry-Lee

The components are disabled because you are trying to run classes that contain component writers on a worker that have no authority over said components

Talking specifically about the PlayerInputSender class. It contains a PlayerInputWriter. That means that when you instantiate this gameobject and this class is active, the worker where that GameObject is running will have write access to PlayerInput

As you mentioned, your clientWorker will be authoritative over your PlayerInput, so when you try to run this class in a worker that is not your clientWorker, SpatialOS will not inject it, to ensure that only the worker that is authoritative over this component effectively have write access over it.

So in your case you cannot have (as they exist today) the PlayerInputSender class running on your gameLogic worker, and you can’t have the PlayerMover class running on your client workers>

The GDK offers a tool callled “Requirable Inspector” that can show you exactly why your classes are failing to be injected - https://documentation.improbable.io/gdk-for-unity/docs/requirable-inspector