Home Game Development In Unity, how do I set fixed participant numbers such that each one community purchasers agree on them?

In Unity, how do I set fixed participant numbers such that each one community purchasers agree on them?

0
In Unity, how do I set fixed participant numbers such that each one community purchasers agree on them?

[ad_1]

We are presently writing an internet sport in Unity. The important thought is that it’s structured like a split-screen, sofa co-op sport, with the net being provided as an extension to permit a number of gamers (as much as 4) to play remotely or utilizing their very own screens. In a community sport, gamers can dedicate the display screen to their very own view, however can even see precisely what one another participant sees both utilizing display screen switching or break up display screen. As such, it will be important for every participant to synchronize their very own digital camera, and for every participant to have a continuing participant index quantity in order that different gamers can simply name up their digital camera (i.e. from a SyncList or related).

However, I can’t work out the right way to implement this. I’m making an attempt to make use of the UNet RPC interface to have the shopper name into the server, assign a participant quantity, then report that worth again to the shopper. However, not solely do RPCs not return values, in addition they seem to have a really restricted model that solely permits them to be referred to as on objects owned by a selected participant – ShopperRpc and GoalRpc can solely be referred to as by purchasers, and Command doesn’t give a dependable option to inform which shopper referred to as it. I did handle to get across the first downside with a library that lets async calls return values utilizing what are primarily JavaScript Promises, however when I attempt to make directed Rpc calls, the Unity runtime rejects the decision from the shopper.

Simply put, I desire a single shopper to ask the server a query, and get a response again from it. This looks as if a basic factor to have in a community structure, and is the premise of many RPC programs corresponding to HTTP REST calls. Is UNet merely not designed for this type of interplay in any respect?

My code is beneath – it is a NetworkBehaviour script hooked up to a root object that’s seen to all purchasers, however has no different duties. The design is that the shopper would name AssignPlayerNumber to get a Promise yielding their canonical participant index, and the server would preserve the precise checklist of participant numbers in order that numbers do not get blended up.

utilizing RSG;
utilizing System.Collections;
utilizing System.Collections.Generic;
utilizing UnityEngine;
utilizing UnityEngine.Networking;

public class PlayerNumberBroker : NetworkBehaviour {

    // NOTE: Right now, this makes use of the participant GameObjects because the common key,
    // which could not work if participant objects are despawned

    public struct PlayerUniversalKey
    {
        public bool current;
        public GameObject playerObject;
    }

    public class SyncListPlayers : SyncListStruct<PlayerUniversalKey>
    {

    }

    non-public SyncListPlayers gamers;

    non-public void Start()
    {
        gamers = new SyncListPlayers();
    }

    non-public int assignPlayerNumberRequestSequenceNum = 0;
    non-public Dictionary<int, IPendingPromise<int>> assignPlayerNumberRequests = new Dictionary<int, IPendingPromise<int>>();

    public IPromise<int> AssignPlayerNumber(GameObject participant)
    {
        if (isServer)
        {
            return Promise<int>.Resolved(AssignPlayerNumber_Inner(participant));
        }
        else if (isClient)
        {
            Promise<int> promise = new Promise<int>();
            int requestNum = assignPlayerNumberRequestSequenceNum++;
            assignPlayerNumberRequests.Add(requestNum, promise);
            GoalAssignPlayerNumberRequest(this.connectionToServer, participant, requestNum);
            return promise;
        }
        else
            throw new System.Exception("Caller to AssignPlayerNumber is neither shopper nor server");
    }

    non-public int AssignPlayerNumber_Inner(GameObject participant)
    {
        PlayerUniversalKey keyToUse = new PlayerUniversalKey()
        {
            current = true,
            playerObject = participant
        };
        int indexToUse;
        for (int i = 0; i < gamers.Count; i++)
        {
            if (!gamers[i].current)
            {
                indexToUse = i;
                goto indexFound;
            }
            else if (gamers[i].playerObject.Equals(participant))
            {
                // Simply return the already assigned participant quantity
                return i;
            }
        }
        indexToUse = gamers.Count;
        gamers.Add(keyToUse);

        indexFound:
        gamers[indexToUse] = keyToUse;
        gamers.Dirty(indexToUse);
        Debug.Log(participant.ToString() + ":" + indexToUse.ToString());

        return indexToUse;
    }

    [TargetRpc]
    non-public void GoalAssignPlayerNumberResponse(NetworkConnection goal, int playerNumber, int requestNumber)
    {
        IPendingPromise<int> promise = assignPlayerNumberRequests[requestNumber];
        assignPlayerNumberRequests.Remove(requestNumber);
        promise.Resolve(playerNumber);
    }

    // run on server solely
    // TODO: Apparently this STILL would not work, as a result of a GoalRpc can solely be referred to as by a server.
    // We must work out a option to go a message extra immediately (although, as may be seen right here,
    // we do not have to do a lot to make that occur).
    [TargetRpc]
    non-public void GoalAssignPlayerNumberRequest(NetworkConnection caller, GameObject participant, int requestNumber)
    {
        int indexToUse = AssignPlayerNumber_Inner(participant);

        GoalAssignPlayerNumberResponse(caller, indexToUse, requestNumber);
    }

    // run on server solely
    [TargetRpc]
    public void TargetFreeAssignmentRequest(NetworkConnection caller, GameObject participant)
    {
        for (int i = 0; i < gamers.Count; i++)
        {
            if (gamers[i].playerObject.Equals(participant))
            {
                gamers[i] = new PlayerUniversalKey()
                {
                    current = false,
                    playerObject = null
                };
            }
        }
    }

    public int GetPlayerNumber(GameObject participant)
    {
        for (int i = 0; i < gamers.Count; i++)
        {
            if (gamers[i].current && gamers[i].playerObject.Equals(participant))
            {
                return i;
            }
        }
        return -1;
    }
}

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here