预制克隆没有附加脚本组件

时间:2018-10-04 08:41:45

标签: c# visual-studio unity3d networking augmented-reality

runtime Prefab with script runtime prefab with script

我的问题是我的Prefab克隆没有脚本组件。原始的预制件具有脚本组件,因此生成的所有克隆都应该有一个吗?

背景:我使用大厅网络管理器创建了共享的增强现实体验。预制件放置在“ Game Player预制件”中,并在服务器内按用户生成。

在发布之前,我会尽力解释和详细介绍。以下是附加在预制件上的脚本]和Lobby Manager Inspector中实现预制件位置的屏幕截图。由于某些原因,堆栈不允许我包含这部分代码,因此它包含在此处:使用系统。集合,System.Collections.Generic,UnityEngine,UnityEngine.Networking,UnityEngine.UI和公共类播放器身份:NetworkBehaviour

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);

for循环使脚本的文件夹成为用户的子文件夹(场景中的标记组件,用于在运行时生成预制件)。

    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;
}

使用if语句是因为gameObject返回NUll,但是我引用了gameObject但它在运行时失败。因此,if语句可确保组件不返回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);
    }
}

}

这是用于生成预制件的大厅管理器脚本:

使用UnityEngine,UnityEngine.UI,UnityEngine.SceneManagement,UnityEngine.Networking,UnityEngine.Networking.Types,UnityEngine.Networking.Match,System.Collections。

命名空间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);
    }
}

}

我将在统一范围内询问与增强现实相关的问题,并且非常高兴有一个网站或一些文档可供查看。目前使用Unity API以及我能找到的任何帮助我的东西。

谢谢!

1 个答案:

答案 0 :(得分:0)

问题已解决:如果预制件不是孩子,总而言之,脚本将不会出现。因此,对于预制件来说必须是个孩子。

现在问题出在大厅管理器上,因为它的团结和混乱可能会引起问题,但是,通过编辑内容并为玩家预制件添加控件可以解决此问题。

问题是LobbyManager会生成预制件的克隆,例如空闲变为空闲(克隆),但是使用此code覆盖系统。先使用计数来识别不同的参与者,然后再使用code 这个预制块。该代码遍历标记的所有成员和所有预制件,然后将预制件转换为标记的子代。