如何减少从客户端生成游戏对象时的延迟

问题描述 投票:0回答:1

我有这段代码,可以生成一个球并将其扔向玩家所看的方向,稍后我想制作一个从库存中扔出物品的系统,但我在多人游戏中遇到问题,因为游戏对象只能生成服务器所以我使用 RPC,但它在抛出对象之前会导致相当大的延迟(例如 0.5 秒)

有谁知道减少这种延迟的方法吗?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;

public class PlayerFunctions : NetworkBehaviour
{
    public GameObject itemPrefab;
    public float throwForce;

    public Transform cameraPos;

    public Transform itemSpawnPos;

    private KeyCode throwKey = KeyCode.Q;

    bool network = false;

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

        network = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(throwKey) && IsOwner)
        {
            ThrowServerRpc(itemSpawnPos.position, cameraPos.rotation);
        }
        else if(!network)
        {
            Throw();
        }
    }

    [ServerRpc]
    void ThrowServerRpc(Vector3 position, Quaternion rotation)
    {
        GameObject objectToThrow = Instantiate(itemPrefab, position, rotation);
        var objectToThrowNetworkObject = objectToThrow.GetComponent<NetworkObject>();
        objectToThrowNetworkObject.Spawn();

        ThrowClientRpc(objectToThrowNetworkObject.NetworkObjectId);
    }

    [ClientRpc]
    void ThrowClientRpc(ulong networkObjectId)
    {
        NetworkObject networkObject = NetworkManager.Singleton.SpawnManager.SpawnedObjects[networkObjectId];

        if(networkObject != null)
        {
            Rigidbody itemRb = networkObject.GetComponent<Rigidbody>();


            itemRb.AddForce(cameraPos.forward * throwForce, ForceMode.Force);
            itemRb.AddForce(transform.up * 100, ForceMode.Force);
        }
    }

    void Throw()
    {

         GameObject objectToThrow = Instantiate(itemPrefab, itemSpawnPos.position, cameraPos.rotation);


        Rigidbody itemRb = objectToThrow.GetComponent<Rigidbody>();

        
        itemRb.AddForce(cameraPos.forward * throwForce, ForceMode.Force);
        itemRb.AddForce(transform.up * 100, ForceMode.Force);
    }
}

unity-game-engine delay rpc multiplayer unity-networking
1个回答
0
投票

如果您还没有解决这个问题,我看到您的代码中使用了实例化。那是一条缓慢的路。你想要的是对象池。

基本上,您预先实例化给定预制件的实例池,并且您有一个“可用”和“已用”列表,因此当您需要一个实例时,您可以通过“保留”它来获取对已实例化对象的引用,然后修改它来设置它供您使用,它会从“可用”列表转到“已用”列表。当您不再需要它时,您可以清除任何修改(或者更好地说,将实例重置为其默认值)并“释放”它,而不是销毁它,然后它会移回空闲列表。这显然意味着您需要为预实例化的实例数量找到一个好的配置,因为您基本上需要预先支付实例化的成本。这也意味着最坏的情况,即您希望在单个帧中“保留”多少个该对象的实例,以避免在您不想产生成本时实例化更多实例。此外,您不想过度使用它并使其成为开销,因此这是一个找到最佳点数的迭代过程。

您可以轻松地自行开发,但 Unity 现在有自己的 API,ObjectPool,其中 T 是您想要池化的类型。

还有这里有关处理池的 Netcode 内容的文档。

© www.soinside.com 2019 - 2024. All rights reserved.