Search Unity

SpawnWithClientAuthority claims my player object is not my player.

Discussion in 'Scripting' started by Avo, Aug 26, 2018.

  1. Avo

    Avo

    Joined:
    Dec 4, 2010
    Posts:
    237
    In my multiplayer game I have a UI controller on my player. This UI instantiates buttons with a button control script on them that contains an abstract scriptable object called ability used in defining how each individual ability works, one such ability is Construct.This works fine for the host but when a client joins and tries to use their UI it gives the error
    Construct must be instantiated using the ScriptableObject.CreateInstance method instead of new Construct.
    however I never create any scriptable objects with the new keyword, instead I pass all of my scriptable objects in by reference.

    I'm also running into a problem with allowing my scriptable object to call the player's ConstructionControl script. It's my understanding the button needs to be owned by the player in order to effect the player and call the ConstructionControl script, however I have to Spawn my UI on the network for everyone if I do this.


    UI controller

    Code (CSharp):
    1.  [System.Serializable]
    2. public class AbilityUIController : NetworkBehaviour
    3. {
    4.  
    5.  
    6.     [Tooltip("Our abillity button game object.")]
    7.     [SerializeField] private GameObject abillityButton;
    8.  
    9.     //This is temporary and will be replaced with abilities being fed in.
    10.     public List<Ability> testAbillities;
    11.  
    12.     [Tooltip("The Canvas we want to draw our buttons on.")]
    13.     [SerializeField] private  Canvas abillityCanvas;
    14.  
    15.     [Tooltip("The gap between our buttons.")]
    16.     [SerializeField] private float buttonGap = 1.0f;
    17.  
    18.     private Button[,] buttonArray = new Button[4,3];
    19.  
    20.     // Use this for initialization
    21.     void Start ()
    22.     {
    23.         //Only run this script if we own the game object.
    24.         if(!isLocalPlayer)
    25.         {
    26.             this.enabled = false;
    27.             return;
    28.         }
    29.  
    30.         //Get our canvas
    31.         GameObject UI = GameObject.FindGameObjectWithTag("UI");
    32.         abillityCanvas = UI.GetComponent<Canvas>();
    33.  
    34.         float buttonWidth = abillityButton.gameObject.GetComponent<RectTransform>().rect.width;
    35.         float buttonHeight = abillityButton.gameObject.GetComponent<RectTransform>().rect.height;  
    36.  
    37.         //Create our buttons
    38.         for(int x = 0; x < 4; x++)
    39.         {
    40.             for(int y = 0; y < 3; y++)
    41.             {
    42.                 //Create the new button
    43.                 buttonArray[x,y] = Object.Instantiate(abillityButton).GetComponent<Button>();
    44.  
    45.                 //Set it's parent so it will render.
    46.                 buttonArray[x,y].gameObject.transform.SetParent(abillityCanvas.gameObject.transform);
    47.  
    48.                 //Get then new buttosn position
    49.                 Vector2 buttonPosition = new Vector2(Screen.width - ((4.0f*(buttonWidth + buttonGap) + buttonWidth/2) - (x*(buttonWidth+buttonGap) + buttonWidth/2)),(y*(buttonHeight+buttonGap) + buttonHeight/2));
    50.              
    51.                 buttonArray[x,y].GetComponent<RectTransform>().position = buttonPosition;
    52.                 buttonArray[x,y].GetComponent<AbilityButton>().Initialize();
    53.  
    54.                 //CmdInstantiateButton(buttonArray[x,y].gameObject, this.gameObject);          
    55.             }
    56.         }
    57.  
    58.         SetAbilities(testAbillities);
    59.     }
    60.  
    61.  
    62.     /*[Command]
    63.     private void CmdInstantiateButton(GameObject button, GameObject player)
    64.     {
    65.         NetworkServer.SpawnWithClientAuthority(button, player);
    66.     }*/
    67.  
    68.     public void SetAbilities(List<Ability> newAbilities)
    69.     {
    70.         int count = 0;
    71.         foreach(Ability ability in newAbilities)
    72.         {
    73.             int x = count%4;
    74.             int y = (count - x)/4;
    75.  
    76.             buttonArray[x,y].GetComponent<AbilityButton>().Initialize(ability);
    77.  
    78.             //ScriptableObject.CreateInstance(typeof(Ability))
    79.             count++;
    80.         }
    81.     }
    82.  
    83. }
    84.  
    AbilityButton


    Code (CSharp):
    1. public class AbilityButton : NetworkBehaviour
    2. {
    3.     [Tooltip("A text object that counts the cooldown down.")]
    4.     public Text coolDownTextDisplay;
    5.  
    6.     private Ability ability;
    7.  
    8.     private Image myButtonImage;
    9.     private AudioSource abillitySource;
    10.     private float coolDownDuration;
    11.     private float nextReadyTime;
    12.     private float coolDownTimeLeft;
    13.  
    14.     private Button button;
    15.  
    16.  
    17.     public void Initialize(Ability selectedAbility = null)
    18.     {
    19.         //Turn the button off if it doesn't have an ability associated with it.
    20.         if(selectedAbility == null)
    21.         {
    22.             GetComponent<Image>().enabled = false;
    23.             GetComponent<Button>().enabled = false;
    24.  
    25.             //Dont execute the rest of the code
    26.             return;
    27.         }
    28.      
    29.         //We may have turned this button off in the past so we'll want to activate it now.
    30.         GetComponent<Image>().enabled = true;
    31.         GetComponent<Button>().enabled = true;
    32.  
    33.         button = this.GetComponent<Button>();
    34.         ability = selectedAbility;
    35.  
    36.         SpriteState spriteState = new SpriteState();
    37.  
    38.         //Change the buttons look to that of the ability.
    39.         button.image.sprite = ability.aSprite;
    40.         spriteState.pressedSprite = ability.aPressedSprite;
    41.         spriteState.highlightedSprite = ability.aHighlightedSprite;
    42.         spriteState.pressedSprite = ability.aPressedSprite;
    43.  
    44.  
    45.  
    46.      
    47.         myButtonImage = GetComponent<Image>();
    48.  
    49.         abillitySource = GetComponent<AudioSource>();
    50.         coolDownDuration = ability.aBaseCoolDown;
    51.         ability.Initialize();
    52.  
    53.         //TODO: We'll want to store the cooldown somewhere other than on the button.
    54.         AbillityReady();
    55.     }
    56.  
    57.     // Update is called once per frame
    58.     void Update ()
    59.     {
    60.         if(Time.time > nextReadyTime)
    61.         {
    62.             AbillityReady();
    63.         }
    64.         else
    65.         {
    66.             CoolDown();
    67.         }
    68.     }
    69.  
    70.  
    71.     private void AbillityReady()
    72.     {
    73.         coolDownTextDisplay.enabled = false;
    74.     }
    75.  
    76.     private void CoolDown()
    77.     {
    78.         coolDownTimeLeft -= Time.deltaTime;
    79.         float roundedCoolDown = Mathf.Round(coolDownTimeLeft);
    80.         coolDownTextDisplay.text = roundedCoolDown.ToString();
    81.     }
    82.  
    83.     //The Button has been clicked
    84.     public void ButtonTriggered()
    85.     {
    86.         if(Time.time > nextReadyTime)
    87.         {
    88.             nextReadyTime = coolDownDuration + Time.time;
    89.             coolDownTimeLeft = coolDownDuration;
    90.  
    91.             if(coolDownDuration != 0)
    92.             {
    93.                 coolDownTextDisplay.enabled = true;
    94.             }      
    95.  
    96.             if(ability.aSound != null)
    97.             {
    98.                 abillitySource.clip = ability.aSound;
    99.             }
    100.          
    101.             if(ability.aSound != null)
    102.             {
    103.                 abillitySource.Play();
    104.             }
    105.  
    106.             ability.TriggerAbility();
    107.         }
    108.     }
    Ability
    Code (CSharp):
    1. public abstract class Ability : ScriptableObject
    2. {
    3.      [Header("Text")]
    4.  
    5.      public string aHotkey = "";
    6.     public string aName = "NewAbility";
    7.     public string aTooltip = "Tooltip";
    8.     [Space(1)]
    9.  
    10.      [Header("Sprites")]
    11.     public Sprite aSprite;
    12.     public Sprite aHighlightedSprite;
    13.     public Sprite aPressedSprite;
    14.     public Sprite aDisabledSprite;
    15.     [Space(1)]
    16.  
    17.     public AudioClip aSound;
    18.  
    19.     public float aBaseCoolDown = 1f;
    20.  
    21.  
    22.     public abstract void Initialize();
    23.  
    24.     public abstract void TriggerAbility();
    25. }
    26.  

    Construct
    Code (CSharp):
    1. [CreateAssetMenu (menuName = "Abilities/Construct")]
    2. public class Construct : Ability
    3. {
    4.     [Space(1)]
    5.  
    6.     [Header("Buildings")]
    7.     [Tooltip("The building we want to build.")]
    8.     public GameObject building;
    9.     [Tooltip("A template we use for placing the building.")]
    10.     public GameObject buildingTemplate;
    11.  
    12.     private ConstructionControl constructionController;
    13.  
    14.     public override void Initialize()
    15.     {
    16.         GameObject[] playerObjects = GameObject.FindGameObjectsWithTag("Player");
    17.         foreach(GameObject playerObject in playerObjects)
    18.         {
    19.             //Our player object should be the only one with an active ConstructionControl script
    20.             if(playerObject.GetComponent<ConstructionControl>().isActiveAndEnabled == true)
    21.             {
    22.                 constructionController = playerObject.GetComponent<ConstructionControl>();
    23.             }
    24.         }
    25.     }
    26.  
    27.  
    28.     public override void TriggerAbility()
    29.     {
    30.         constructionController.CreateBuildingShadow(this);
    31.     }
    32. }
    Edit: I've expanded the scope of this post as I get a better grasp of my problem.
     
    Last edited: Aug 26, 2018
  2. Avo

    Avo

    Joined:
    Dec 4, 2010
    Posts:
    237
    I hate to bump my own thread but I'm still struggling with this. If I can elaborate on anything please let me know!