0
votes

runtime Prefab with script runtime prefab with script

My problem is that my Prefab clone does not have a script component. The original prefab has a script component, therefore all the clones generated should have one or not?

Background: I created a shared augmented reality experience using the lobby network manager. The prefab is placed within 'Game Player Prefab' and generates per users within the server.

I'll explain and go in as much detail as I can before posting. Below is the script] attached to the prefab and the screenshot of where the prefab is implemented from Lobby Manager Inspector. For some reason stack won't allow me to include this part of the code, therefore it is included here: using System. Collections, System.Collections.Generic, UnityEngine, UnityEngine.Networking, UnityEngine.UI and public class player identity: NetworkBehaviour

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Collections.Generic;

public class PlayerIdentity : NetworkBehaviour, MonoBehaviour
{

    GameObject imageTracker_1, imageTracker_2, canvasUI;
    public GameObject[] user;
    public GameObject myTextObj, origin;
    public float distanceFromOrigin;
    int count = 0;
    //public Text myText;

    private void Awake()
    {
        transform.GetComponent<playerIdentity>().enabled = true;

        user[0] = GameObject.FindWithTag("Respawn");
        user[1] = GameObject.FindWithTag("Finish");

   
    }

    void Start()
    {
        if (!isLocalPlayer)
        {
            Destroy(this);
            return;
        }
        //code stop unity responding! 
        //while (count < user.Length)
        //{
        //    if (transform.name == "idle(Clone)")
        //    {
        //        transform.name = "player" + count;
        //        count++;
        //    }
        //}

        origin = GameObject.Find("PositionOrigin");
        //used for finding text, "GetComponent<Text>" needs to be attached or fails.
        // canvasUI = GameObject.Find("Canvas");
        // myText = canvasUI.GetComponentInChildren<Text>();
        //// myText.text = "Out of area";
        // myTextObj.SetActive(false);

the for loop makes the folder of the script a child of the user (marker components within the scene, used to spawn prefab on run-time).

        for (int i = 0; i < user.Length; i++) {
            transform.SetParent(user[i].transform, false); 
            if (user[i].GetComponentInChildren<playerIdentity>() == null){
                Debug.Log("no child");
            }
        }


        // we track the vuforia image within the scene and attach the avatar as a child                   
        //imageTracker_1 = GameObject.FindWithTag("Respawn");
        //GameObject imageTracker_2 = GameObject.FindWithTag("Finish");
        //transform.SetParent(imageTracker_1.transform, false);
        //transform.parent = imageTracker_1.transform;

    
        //imageTracker_2 = GameObject.Find("avatar_01");
        //GameObject.Find("Idle(Clone)").transform.parent = imageTracker_2.transform;
    }
}

the if statement was used because the gameObject was returning NUll but, I've referenced the gameObject but it fails on run-time. Therefore the if statement makes sure the components don't return Null.

private void Update()
{
    distanceFromOrigin = Vector3.Distance(origin.transform.position, transform.position);      

    //during start the gameObject will return NULL, this will make sure during every frame the gameObject does not equal null
    if ( origin || imageTracker_1 || myTextObj == null)
    {
        myTextObj = GameObject.Find("OutOfBound");
        origin = GameObject.Find("PositionOrigin");
        //imageTracker_1 = GameObject.FindWithTag("Player");
        //transform.SetParent(imageTracker_1.transform, false);
    }
}

}

this is the lobby manager script used to generate the prefab:

using UnityEngine, UnityEngine.UI, UnityEngine.SceneManagement, UnityEngine.Networking, UnityEngine.Networking.Types, UnityEngine.Networking.Match, System.Collections.

namespace Prototype.NetworkLobby

public class LobbyManager : NetworkLobbyManager 
{
    static short MsgKicked = MsgType.Highest + 1;

    static public LobbyManager s_Singleton;


    [Header("Unity UI Lobby")]
    [Tooltip("Time in second between all players ready & match start")]
    public float prematchCountdown = 5.0f;

    [Space]
    [Header("UI Reference")]
    public LobbyTopPanel topPanel;

    public RectTransform mainMenuPanel;
    public RectTransform lobbyPanel;

    public LobbyInfoPanel infoPanel;
    public LobbyCountdownPanel countdownPanel;
    public GameObject addPlayerButton;

    protected RectTransform currentPanel;

    public Button backButton;

    public Text statusInfo;
    public Text hostInfo;

    //Client numPlayers from NetworkManager is always 0, so we count (throught connect/destroy in LobbyPlayer) the number
    //of players, so that even client know how many player there is.
    [HideInInspector]
    public int _playerNumber = 0;

    //used to disconnect a client properly when exiting the matchmaker
    [HideInInspector]
    public bool _isMatchmaking = false;

    protected bool _disconnectServer = false;
    
    protected ulong _currentMatchID;

    protected LobbyHook _lobbyHooks;

    void Start()
    {
        s_Singleton = this;
        _lobbyHooks = GetComponent<Prototype.NetworkLobby.LobbyHook>();
        currentPanel = mainMenuPanel;

        backButton.gameObject.SetActive(false);
        GetComponent<Canvas>().enabled = true;

        DontDestroyOnLoad(gameObject);

        SetServerInfo("Offline", "None");
    }

    public override void OnLobbyClientSceneChanged(NetworkConnection conn)
    {
        if (SceneManager.GetSceneAt(0).name == lobbyScene)
        {
            if (topPanel.isInGame)
            {
                ChangeTo(lobbyPanel);
                if (_isMatchmaking)
                {
                    if (conn.playerControllers[0].unetView.isServer)
                    {
                        backDelegate = StopHostClbk;
                    }
                    else
                    {
                        backDelegate = StopClientClbk;
                    }
                }
                else
                {
                    if (conn.playerControllers[0].unetView.isClient)
                    {
                        backDelegate = StopHostClbk;
                    }
                    else
                    {
                        backDelegate = StopClientClbk;
                    }
                }
            }
            else
            {
                ChangeTo(mainMenuPanel);
            }

            topPanel.ToggleVisibility(true);
            topPanel.isInGame = false;
        }
        else
        {
            ChangeTo(null);

            Destroy(GameObject.Find("MainMenuUI(Clone)"));

            //backDelegate = StopGameClbk;
            topPanel.isInGame = true;
            topPanel.ToggleVisibility(false);
        }
    }

    public void ChangeTo(RectTransform newPanel)
    {
        if (currentPanel != null)
        {
            currentPanel.gameObject.SetActive(false);
        }

        if (newPanel != null)
        {
            newPanel.gameObject.SetActive(true);
        }

        currentPanel = newPanel;

        if (currentPanel != mainMenuPanel)
        {
            backButton.gameObject.SetActive(true);
        }
        else
        {
            backButton.gameObject.SetActive(false);
            SetServerInfo("Offline", "None");
            _isMatchmaking = false;
        }
    }

    public void DisplayIsConnecting()
    {
        var _this = this;
        infoPanel.Display("Connecting...", "Cancel", () => { _this.backDelegate(); });
    }

    public void SetServerInfo(string status, string host)
    {
        statusInfo.text = status;
        hostInfo.text = host;
    }


    public delegate void BackButtonDelegate();
    public BackButtonDelegate backDelegate;
    public void GoBackButton()
    {
        backDelegate();
        topPanel.isInGame = false;
    }

    // ----------------- Server management

    public void AddLocalPlayer()
    {
        TryToAddPlayer();
    }

    public void RemovePlayer(LobbyPlayer player)
    {
        player.RemovePlayer();
    }

    public void SimpleBackClbk()
    {
        ChangeTo(mainMenuPanel);
    }
             
    public void StopHostClbk()
    {
        if (_isMatchmaking)
        {
            matchMaker.DestroyMatch((NetworkID)_currentMatchID, 0, OnDestroyMatch);
            _disconnectServer = true;
        }
        else
        {
            StopHost();
        }

        
        ChangeTo(mainMenuPanel);
    }

    public void StopClientClbk()
    {
        StopClient();

        if (_isMatchmaking)
        {
            StopMatchMaker();
        }

        ChangeTo(mainMenuPanel);
    }

    public void StopServerClbk()
    {
        StopServer();
        ChangeTo(mainMenuPanel);
    }

    class KickMsg : MessageBase { }
    public void KickPlayer(NetworkConnection conn)
    {
        conn.Send(MsgKicked, new KickMsg());
    }




    public void KickedMessageHandler(NetworkMessage netMsg)
    {
        infoPanel.Display("Kicked by Server", "Close", null);
        netMsg.conn.Disconnect();
    }

    //===================

    public override void OnStartHost()
    {
        base.OnStartHost();

        ChangeTo(lobbyPanel);
        backDelegate = StopHostClbk;
        SetServerInfo("Hosting", networkAddress);
    }

    public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
    {
        base.OnMatchCreate(success, extendedInfo, matchInfo);
        _currentMatchID = (System.UInt64)matchInfo.networkId;
    }

    public override void OnDestroyMatch(bool success, string extendedInfo)
    {
        base.OnDestroyMatch(success, extendedInfo);
        if (_disconnectServer)
        {
            StopMatchMaker();
            StopHost();
        }
    }


    //allow to handle the (+) button to add/remove player
    public void OnPlayersNumberModified(int count)
    {
        _playerNumber += count;

        int localPlayerCount = 0;
        foreach (PlayerController p in ClientScene.localPlayers)
            localPlayerCount += (p == null || p.playerControllerId == -1) ? 0 : 1;

        addPlayerButton.SetActive(localPlayerCount < maxPlayersPerConnection && _playerNumber < maxPlayers);
    }

    // ----------------- Server callbacks ------------------

    //we want to disable the button JOIN if we don't have enough player
    //But OnLobbyClientConnect isn't called on hosting player. So we override the lobbyPlayer creation
    public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId)
    {
        
        GameObject obj = Instantiate(lobbyPlayerPrefab.gameObject) as GameObject;
       

        LobbyPlayer newPlayer = obj.GetComponent<LobbyPlayer>();
        newPlayer.ToggleJoinButton(numPlayers + 1 >= minPlayers);

        for (int i = 0; i < lobbySlots.Length; ++i)
        {
            LobbyPlayer p = lobbySlots[i] as LobbyPlayer;

           

            if (p != null)
            {
                p.RpcUpdateRemoveButton();
                p.ToggleJoinButton(numPlayers + 1 >= minPlayers);
            }
        }

        return obj;
    }

    public override void OnLobbyServerPlayerRemoved(NetworkConnection conn, short playerControllerId)
    {
        for (int i = 0; i < lobbySlots.Length; ++i)
       {
            LobbyPlayer p = lobbySlots[i] as LobbyPlayer;

            if (p != null)
            {
                p.RpcUpdateRemoveButton();
                p.ToggleJoinButton(numPlayers + 1 >= minPlayers);
            }
        }
    }

    public override void OnLobbyServerDisconnect(NetworkConnection conn)
    {
        for (int i = 0; i < lobbySlots.Length; ++i)
        {
            LobbyPlayer p = lobbySlots[i] as LobbyPlayer;

            if (p != null)
            {
                p.RpcUpdateRemoveButton();
                p.ToggleJoinButton(numPlayers >= minPlayers);
            }
        }

    }

    public override bool OnLobbyServerSceneLoadedForPlayer(GameObject lobbyPlayer, GameObject gamePlayer)
    {
        //This hook allows you to apply state data from the lobby-player to the game-player
        //just subclass "LobbyHook" and add it to the lobby object.

        if (_lobbyHooks)
            _lobbyHooks.OnLobbyServerSceneLoadedForPlayer(this, lobbyPlayer, gamePlayer);

        return true;
    }

    // --- Countdown management

    public override void OnLobbyServerPlayersReady()
    {
        bool allready = true;
        for(int i = 0; i < lobbySlots.Length; ++i)
        {
            if(lobbySlots[i] != null)
                allready &= lobbySlots[i].readyToBegin;
        }

        if(allready)
            StartCoroutine(ServerCountdownCoroutine());
    }

    public IEnumerator ServerCountdownCoroutine()
    {
        float remainingTime = prematchCountdown;
        int floorTime = Mathf.FloorToInt(remainingTime);

        while (remainingTime > 0)
        {
            yield return null;

            remainingTime -= Time.deltaTime;
            int newFloorTime = Mathf.FloorToInt(remainingTime);

            if (newFloorTime != floorTime)
            {//to avoid flooding the network of a message, we only send a notice to the client when the number of plain seconds changes.
                floorTime = newFloorTime;

                for (int i = 0; i < lobbySlots.Length; ++i)
                {
                    if (lobbySlots[i] != null)
                    {//there is maxPlayer slots, so some could be == null, need to test it before accessing!
                        (lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(floorTime);
                    }
                }
            }
        }

        for (int i = 0; i < lobbySlots.Length; ++i)
        {
            if (lobbySlots[i] != null)
            {
                (lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(0);
            }
        }

        ServerChangeScene(playScene);
    }

    // ----------------- Client callbacks ------------------

    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);

        infoPanel.gameObject.SetActive(false);

        conn.RegisterHandler(MsgKicked, KickedMessageHandler);

        if (!NetworkServer.active)
        {//only to do on pure client (not self hosting client)
            ChangeTo(lobbyPanel);
            backDelegate = StopClientClbk;
            SetServerInfo("Client", networkAddress);
        }
    }


    public override void OnClientDisconnect(NetworkConnection conn)
    {
        base.OnClientDisconnect(conn);
        ChangeTo(mainMenuPanel);
    }

    public override void OnClientError(NetworkConnection conn, int errorCode)
    {
        ChangeTo(mainMenuPanel);
        infoPanel.Display("Cient error : " + (errorCode == 6 ? "timeout" : errorCode.ToString()), "Close", null);
    }
}

}

I will be asking questions related to Augmented reality within unity and would be great to have a website or some documentation to look at. At the moment using the Unity API and whatever I can find to help me.

1
You need to post the script containing the code where you instantiate the prefabs. Otherwise it is hard to review your questionImmorality
I've added the lobby manager script which generates the prefab. Thanks for helping me! @ImmoralityAbdullah
Are you sure the script is attached to the prefab? What do you see when you select the prefab in your assets folder. The inspector to the right, does it display the script? If not, then you have unapplied changes to a prefab object in scene.Immorality
Try using option "Apply" in Inspector on GameObject in Scene.Morasiu
Morasiu there is no apply button on the prefab within the asset folder. I'm sure that method only applies to prefabs within the scene on the hierarchy. @Immorality yes it is attached to the prefab, I will try to upload an image showing the inspector for the prefab.Abdullah

1 Answers

0
votes

Issue solved: All in all if the prefab was not a child, the script will not appear. Therefore for the prefab has to be a child.

Now the issue was with the lobby Manager as its an asset from unity and messing around could cause issues, however, by editing the contents and adding control for game player prefab this issue was solved.

The issue was that the LobbyManager would spawn clones of the prefab e.g. Idle becomes Idle(Clone) but, using this code to override the system. Using a count to identify different players and then this code which is held by the prefab. The code runs through all members of the markers and all prefab member, then converting the prefabs into children of the markers.