- Home /
Multiplayer Inventory System with RPCs
I have a script for my game called Inventory.cs
On start it uses an a RPC to get its inventory info from the server. The player's inventory is saved server-side.
This works, but getting the Current Weapon that is equipped doesn't...
In the scene there is a GameObject called ServerManager which has a the Inventory script it is destroyed if the Instance becomes a client.
If it is a server it doesn't do the start function which would get the Inventory and Current Weapon.
Instead if it is a server it just sits there waiting to receive RPCs from players to load there Inventory and Current Weapon info and send it back to the player.
This all works (Current Weapon included) if one player is connected. However if a second player connects then for some reasons when the other players spawns in (when their player model is instantiated) it re-instantiates the current weapon...
EXAMPLE:
Player #1 connects and spawns and gets his current weapon which is = "Iron Hatchet" (Only one Iron Hatchet instantiated)
Player #2 connects and when he spawns he gets his current weapon but its instantiated twice and then Player #1's weapon is also instantiated twice. So both clients have two current weapons.
NOTE only one of the weapons is following the Weapons Slot (Only one each appears to be held by the player, the other is floating independently)
Code for Inventory.cs:
/// <summary>
/// Inventory.cs
/// 4/25/14
/// Matthew Nevers
///
/// This script handles using inventory. Sends RPCs to load and save inventory per server.
/// </summary>
using UnityEngine;
using System.Collections;
public class Inventory : MonoBehaviour {
public bool isServer;
private const int AMOUNT_OF_ITEMS = 40;
public string[] items;
private string playerName;
public GUISkin mySkin;
public GameObject currentWeapon;
public string currentWeaponName;
public Transform weaponSlot;
public Transform offHandSlot;
public Transform headSlot;
private bool _displayInventoryWindow = false;
private const int INVENTORY_WINDOW_ID = 10;
private Rect _inventoryWindowRect = new Rect(10,15,185,290); //change based on button size etc (15,15,250,400)
private int _inventoryRows = 8;
private int _inventoryCols = 5;
private string _selectedItem;
private int buttonWidth = 32;
private int buttonHeight = 32;
private bool curWeaponLoaded = false;
private float _doubleClickTimer = 0;
private const float DOUBLE_CLICK_TIMER_THRESHOLD = .5f;
// Use this for initialization
void Start () {
if(networkView.isMine == false && isServer == false)
enabled = false;
if (isServer == false) {
items = new string[AMOUNT_OF_ITEMS];
playerName = PlayerPrefs.GetString ("PlayerName", "Player");
//currentWeapon = //Use RPC// GameObject.Find(PlayerPrefs.GetString("CurrentWeapon"));
networkView.RPC ("LoadInventory", RPCMode.Server, playerName);
networkView.RPC("LoadCurrentWeapon", RPCMode.Server, playerName);
}
}
void Update(){
if(Input.GetButtonDown ("ToggleInventory"))
_displayInventoryWindow = !_displayInventoryWindow;
}
[RPC]
void GetInventory(string name, int index, string itemNameTemp){
if(name == playerName && isServer == false) {
items [index] = itemNameTemp;
Debug.Log("Got item: " + items[index] + " in Slot Number: " + index);
}
}
void OnGUI(){
GUI.skin = mySkin;
if(isServer == true)
return;
//</INVENTORY>
if(_displayInventoryWindow && isServer == false){
_inventoryWindowRect = GUI.Window(INVENTORY_WINDOW_ID, _inventoryWindowRect, InventoryWindow, "Inventory");
}
}
void InventoryWindow(int windowID){
int cnt = 0;
for(int y = 0; y < _inventoryRows; y++){
for(int x = 0; x < _inventoryCols; x++){
if(cnt < items.Length && items[cnt] != null && items[cnt] != "Empty"){ //might be error at Empty
if(GUI.Button(new Rect(12 + (x * buttonWidth), 20 + (y * buttonHeight), buttonWidth, buttonHeight), "", items[cnt])){
Debug.Log(items[cnt] + " Selected");
networkView.RPC ( "UseItem", RPCMode.AllBuffered, items[cnt], playerName, cnt);
}
cnt++;
}else{
if(GUI.Button(new Rect(12 + (x * buttonWidth), 20 + (y * buttonHeight), buttonWidth, buttonHeight), "", "Empty")){
Debug.Log(items[cnt] + " Selected (Empty)");
//Do Nothing
}
cnt++;
}
}
}
GUI.DragWindow();
}
[RPC]
void UseItem(string itemNameTemp, string name, int index){
if (networkView.isMine && isServer == false) {
items[index] = null;
if (itemNameTemp == "Iron Hatchet" && playerName == name) {
if(currentWeaponName != null){
ReAddItem(currentWeaponName);
Network.Destroy(currentWeapon);
}
GameObject mesh = Network.Instantiate (Resources.Load ("Weapons/Melee/_Prefabs/Iron Hatchet"), weaponSlot.transform.position, weaponSlot.transform.rotation, 90)as GameObject;
currentWeapon = mesh;
currentWeaponName = "Iron Hatchet";
networkView.RPC("SaveCurrentWeapon", RPCMode.Server, name, currentWeaponName);
}else if (itemNameTemp == "Iron Short Sword" && playerName == name) {
if(currentWeaponName != null){
ReAddItem(currentWeaponName);
Network.Destroy(currentWeapon);
}
GameObject mesh = Network.Instantiate (Resources.Load ("Weapons/Melee/_Prefabs/Iron Short Sword"), weaponSlot.transform.position, weaponSlot.transform.rotation, 90)as GameObject;
currentWeapon = mesh;
currentWeaponName = "Iron Short Sword";
networkView.RPC("SaveCurrentWeapon", RPCMode.Server, name, currentWeaponName);
}
}
}
void ReAddItem(string tempItem){
Debug.Log(tempItem);
if(tempItem == null || tempItem == "" || tempItem == "Empty")
return;
for(int cnt = 0; cnt <= AMOUNT_OF_ITEMS; cnt++){
if(items[cnt] == "Empty" || items[cnt] == "" || items[cnt] == null){
items[cnt] = tempItem;
Debug.Log(items[cnt] + " ReAdded to slot: " + cnt.ToString());
return;
}
}
}
[RPC]
void LoadInventory(string nameTemp){
if (Network.peerType == NetworkPeerType.Server) {
Debug.Log ("Recieved RPC from: " + playerName);
string[] temp;
temp = new string[AMOUNT_OF_ITEMS];
for(int cnt = 0; cnt <= AMOUNT_OF_ITEMS; cnt++){
temp[cnt] = PlayerPrefs.GetString(nameTemp + " Inventory" + cnt.ToString(), "Empty");
if(temp[cnt] != "Empty")
networkView.RPC("GetInventory", RPCMode.Server, nameTemp, cnt, temp[cnt]);
}
}
}
[RPC]
void SaveCurrentWeapon(string nameTemp, string weapon){
if (Network.peerType == NetworkPeerType.Server) {
Debug.Log ("Recieved RPC from: " + nameTemp + " To Save Current Weapon");
PlayerPrefs.SetString(nameTemp + " Current Weapon", weapon);
}
}
[RPC]
void LoadCurrentWeapon(string nameTemp){
if (Network.peerType == NetworkPeerType.Server) {
Debug.Log ("Recieved RPC from: " + nameTemp + "To Load Current Weapon");
string tempWep = PlayerPrefs.GetString(nameTemp + " Current Weapon", null);
networkView.RPC("GetCurrentWeapon", RPCMode.Others, nameTemp, tempWep);
}
}
[RPC]
void GetCurrentWeapon(string nameTemp, string weaponTemp){
if(Network.peerType != NetworkPeerType.Server && playerName == nameTemp && isServer == false && curWeaponLoaded == false){
curWeaponLoaded = true;
string temp;
temp = weaponTemp;
if(currentWeaponName != null){
ReAddItem(currentWeaponName);
Network.Destroy(currentWeapon);
}else{
currentWeaponName = temp;
}
if (temp == "Iron Hatchet") {
GameObject mesh = Network.Instantiate (Resources.Load ("Weapons/Melee/_Prefabs/Iron Hatchet"), weaponSlot.transform.position, weaponSlot.transform.rotation, 90)as GameObject;
currentWeapon = mesh;
}else if (temp == "Iron Short Sword") {
GameObject mesh = Network.Instantiate (Resources.Load ("Weapons/Melee/_Prefabs/Iron Short Sword"), weaponSlot.transform.position, weaponSlot.transform.rotation, 90)as GameObject;
currentWeapon = mesh;
}
}
}
}
Please Look it over and help me. I am new to using RPCs and networking so please correct any mistakes.
SIDE NOTES: The Weapon is updated with RPCs to be at the players hand (But the duplicates don't)
Players are renamed in scene to their name.
IF YOU NEED MORE INFO PLEASE ASK ME. I'll HELP YOU HELP ME.