I am making a simple memory game. I have already made the game work with smartfoxserver. But when I tried to build another machine and let them run simultaneously, one player would be log out when another log in. Could you guys help me with this one. Here is the code on the client. Also is once the game start is there any way for the two machine to connect to eachother. For example showing the score from Player1 to Player2. Thank you.
using Sfs2X;
using Sfs2X.Core;
using Sfs2X.Entities.Data;
using Sfs2X.Requests;
using Sfs2X.Util;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using Sfs2X.Requests.MMO;
public class GameController : MonoBehaviour
{
public string defaultHost = "127.0.0.1";
public int defaultTcpport = 8888;
public int defaultWsport = 8080;
public string Zonename = "BasicExamples";
public string Username = "guest";
public string Roomname = "The Lobby";
private SmartFox sfs;
void Awake()
{
SourceSprites = Resources.LoadAll<Sprite>("Sprite/GameImages");
}
void Start()
{
Login_Click();
TotalGuess = btnlist.Count / 2;
GetButton();
AddListener();
AddSprites();
shuffle(GameSprite);
}
public void Login_Click()
{
if (sfs == null || !sfs.IsConnected)
{
sfs = new SmartFox();
sfs.ThreadSafeMode = true;
sfs.AddEventListener(SFSEvent.CONNECTION, OnConnection);
sfs.AddEventListener(SFSEvent.CONNECTION_LOST, OnConnectionLost);
sfs.AddEventListener(SFSEvent.LOGIN, OnLogin);
sfs.AddEventListener(SFSEvent.LOGIN_ERROR, OnLoginError);
sfs.AddEventListener(SFSEvent.ROOM_JOIN, OnJoinRoom);
sfs.AddEventListener(SFSEvent.ROOM_JOIN_ERROR, OnJoinRoomError);
sfs.AddEventListener(SFSEvent.EXTENSION_RESPONSE, GetResult);
ConfigData cfg = new ConfigData();
cfg.Host = defaultHost;
cfg.Port = defaultTcpport;
cfg.Zone = "BasicExamples";
cfg.Debug = true;
Debug.LogError("defaultHost " + defaultHost);
Debug.LogError("defaultTcpport " + defaultTcpport);
sfs.Connect(cfg);
}
}
void OnLogin(BaseEvent evt)
{
Debug.Log("Login Success");
sfs.Send(new JoinRoomRequest("The Lobby"));
}
void OnJoinRoom(BaseEvent evt)
{
Debug.Log("Joined Room"+ evt.Params["room"]);
}
void OnJoinRoomError(BaseEvent evt)
{
Debug.Log("Join Room Error" + evt.Params["errorMessage"]);
}
void OnLoginError(BaseEvent evt)
{
Debug.Log("Login Error"+ evt.Params["errorMessage"]);
}
void OnConnection(BaseEvent evt)
{
if ((bool)evt.Params["success"])
{
Debug.Log("Connection Success");
sfs.Send(new LoginRequest(Username, "", Zonename));
}
else
{
Debug.Log("Connection Error");
}
}
void OnConnectionLost(BaseEvent evt)
{
}
Your problem is that all of your clients have the same username when you do LoginRequest.
SFS automatically disconnect other users with the same username.
You must create a unique username for all of your clients to they can connect together.
The simplest way to do this is to use the device id as a username.
sfs.Send(new LoginRequest(SystemInfo.deviceUniqueIdentifier, "", Zonename));
hope this helps.
Related
So i have followed the tutorial series from Dilmer Valecillos on how to use Netcode and got it working with friends and all! I wanted to add a simple Inputfield in the menu to type in your username, and then apply that to the username logic the video had. However, whenever i do this, the host sees everyone as there own username, and so do the clients.
PlayerHud.CS
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Netcode;
using UnityEngine;
public class PlayerHud : NetworkBehaviour
{
private NetworkVariable<NetworkString> playersName = new NetworkVariable<NetworkString>();
private TMP_InputField nameInput;
private NetworkManagerUI uimanager;
private bool overlaySet = false;
public override void OnNetworkSpawn()
{
if (IsServer)
{
uimanager = GameObject.FindObjectOfType<NetworkManagerUI>();
playersName.Value = uimanager.username.Value + $" ({OwnerClientId})";
}
}
public void SetOverlay()
{
var localPlayerOverlay = gameObject.GetComponentInChildren<TMP_Text>();
localPlayerOverlay.text = playersName.Value;
}
private void Update()
{
if (!overlaySet && !string.IsNullOrEmpty(playersName.Value))
{
SetOverlay();
overlaySet = true;
}
}
}
Any idea how to fix this?
Tried alot of PlayerPrefs, input etc but did not work
I am trying to create a Regular Expression system as part of my program. When I pass emailSub (which is a String version of an InputField for the user's email) into other functions within the program, the emailSub goes from the email address (e.g: emailaddress#emailprovider.com) to null (I know this because the output of a Debug.Log before being passed is the email address and Debug.Log-ing it after passing it comes back with " ". This means that when it reaches the length check (IsEmailValid) it is less than 6 characters so all email addresses are rejected as invalid.
How can I fix this problem?
Thanks.
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
emailSub = arg0;
Debug.Log(emailSub);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
Main(emailSub);
}
public static bool IsEmailValid(string emailSub)
{
if (emailSub.Length <= 6)
{
Debug.Log(emailSub + "1");
return false;
}
if (string.IsNullOrWhiteSpace(emailSub))
{
Debug.Log(emailSub + "2");
return false;
}
try
{
emailSub = Regex.Replace(emailSub, #"(#)(.+)$", DomainMapper, RegexOptions.None,
TimeSpan.FromMilliseconds(200));
string DomainMapper(Match match)
{
var idnConversion = new IdnMapping();
var processDomainName = idnConversion.GetAscii(match.Groups[2].Value);
Debug.Log(emailSub + "3");
return match.Groups[1].Value + processDomainName;
}
}
catch (RegexMatchTimeoutException e)
{
return false;
}
catch (ArgumentException e)
{
return false;
}
try
{
Debug.Log(emailSub + "4");
return Regex.IsMatch(emailSub, #"^(([0-9a-z]((\.(?!\.))(?<=[0-9a-z])#))" + #"(([0-9a-z][-0-
9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase,
TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void Main(string emailSub)
{
if (RegEx.IsEmailValid(emailSub))
{
Debug.Log($"Valid: {emailSub}");
Debug.Log(emailSub + "5");
}
else
{
Debug.Log($"Invalid: {emailSub}");
Debug.Log(emailSub + "6");
}
}
}
The answer below was written by the person who asked the original question, but they wrote it as a replacement of the question, not in answer.
I fixed the problem, the program takes the contents of a text field and decides whether the text is in a valid email format or not. The problem was that the functions were running before the SubmitName() had updated the contents of arg0. Here is the working code:
using System.Text.RegularExpressions;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System;
public class RegEx : MonoBehaviour
{
public InputField emailField;
public Button acceptSubmissionButton;
public string emailSub;
public void Start()
{
var input = gameObject.GetComponent<InputField>();
var se = new InputField.SubmitEvent();
se.AddListener(SubmitName);
input.onEndEdit = se;
}
private void SubmitName(string arg0)
{
Debug.Log(arg0);
IsEmailValid(arg0);
ValidCheck(arg0);
}
public void Sequencer(string emailSub)
{
Debug.Log(emailSub);
IsEmailValid(emailSub);
ValidCheck(emailSub);
}
public static bool IsEmailValid(string arg0)
{
if (arg0.Length <= 6)
{
return false;
}
try
{
return Regex.IsMatch(arg0, #"^(?("")("".+?(?<!\\)""#)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])#))" + #"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)); // The pattern is taken from an article written by Microsoft. https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
public static void ValidCheck(string arg0)
{
if (IsEmailValid(arg0))
{
Debug.Log($"Valid: {arg0}");
}
else
{
Debug.Log($"Invalid: {arg0}");
}
}
}
I checked many times and I can’t find where my mistake is, someone please help, I don’t understand what is happening
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LobbyManager : MonoBehaviourPunCallbacks
{
public Text LogText;
private void Start()
{
PhotonNetwork.NickName = "Player " + Random.Range(1000, 9999);
Log("Player's name is set to " + PhotonNetwork.NickName);
PhotonNetwork.AutomaticallySyncScene = true;
PhotonNetwork.GameVersion = "1";
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Log("Connected to Master");
}
public void CreateRoom()
{
PhotonNetwork.CreateRoom(null, new Photon.Realtime.RoomOptions { MaxPlayers = 2 });
}
public void JoinRoom()
{
PhotonNetwork.JoinRandomRoom();
}
public override void onJoinedRoom()
{
Log("Joined the room");
PhotonNetwork.LoadLevel("Game");
}
private void Log(string message)
{
Debug.Log(message);
LogText.text += "\n";
LogText.text += message;
}
}
Error: Assets\LobbyManager.cs(40,26): error CS0115: 'LobbyManager.onJoinedRoom()': no suitable method found to override
I just can't understand where my mistake or what?? Help plssss guys
they have changed this in new updates, even if this is an old question, I would like to add the answer I found, as I just came across this question now !
public class NetworkManager: MonoBehaviourPunCallbacks
{
// Start is called before the first frame update
void Start()
{
ConnectToServer();
}
This is the code "template" I used for adverts in my project. Although the adverts are working (A bit slow when testing). Unity gives me this: "ShowOptions.resultCallback' is obsolete: 'Implement IUnityAdsListener and call Advertisement.AddListener(). I tried to do adverts by using a listener, but it failed to work... Any suggestions?
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Advertisements;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class PlayerController : MonoBehaviour
{
string gameId;
bool testMode;
string placementId;
void Start()
{
gameId = "<my id here>";
testMode = false;
placementId = "<placement id here>";
Advertisement.Initialize(gameId, true);
}
void ShowAd()
{
if (Application.internetReachability == NetworkReachability.NotReachable)
{
//Give internet connectivity feedback here
}
else
{
ShowOptions options = new ShowOptions();
options.resultCallback = HandleShowResult;
Advertisement.Show(placementId, options);
}
}
void HandleShowResult(ShowResult result)
{
switch (result)
{
case ShowResult.Finished:
//Advert completed
break;
case ShowResult.Skipped:
//Advert skipped
break;
case ShowResult.Failed:
//Advert failed
break;
}
}
}
Image:The error I get when using the listener method
The error basically tells you exactly what to do:
ShowOptions.resultCallback' is obsolete: 'Implement IUnityAdsListener and call Advertisement.AddListener()'
In the API there is a complete example! Adopted to your code:
public class PlayerController : MonoBehaviour, IUnityAdsListener
{
private string gameId;
private bool testMode;
private string placementId;
private bool adsAreReady;
private void Start()
{
gameId = "<my id here>";
testMode = false;
placementId = "<placement id here>";
// WAIT FOR ADS
Advertisment.AddListener(this);
Advertisement.Initialize(gameId, true);
}
public void ShowAd()
{
if (Application.internetReachability == NetworkReachability.NotReachable)
{
//Give internet connectivity feedback here
return;
}
if(!adsAreReady)
{
// Give not ready yet feedback
return;
}
ShowOptions options = new ShowOptions();
Advertisement.Show(placementId, options);
}
// Implement IUnityAdsListener interface methods:
public void OnUnityAdsDidFinish (string placementId, ShowResult showResult)
{
// Define conditional logic for each ad completion status:
switch(showResult)
{
case ShowResult.Finished:
// Reward the user for watching the ad to completion.
break;
case ShowResult.Skipped:
// Do not reward the user for skipping the ad.
break;
case ShowResult.Failed:
Debug.LogWarning (“The ad did not finish due to an error.);
break;
}
}
public void OnUnityAdsReady (string placementId)
{
if (placementId != myPlacementId) return;
adsAreReady = true;
}
public void OnUnityAdsDidError (string message)
{
// Log the error.
}
public void OnUnityAdsDidStart (string placementId)
{
// Optional actions to take when the end-users triggers an ad.
}
}
NOTE that in your code you never call ShowAdd .. it should probably be public and called from somewhere else.
I'm studying for an exam and I came across a question I couldn't figure out. It asks to Create a TurnOnRadio method for the Radio class. This method should remove any TV subscribers to the remote control object. I thought I could do this with just = without the += or -=. When I go to do this is says This event " RemoteControl.channelChange " can only be on the left hand side of += or -= (except when used from within the type 'Remote Control') Any help on accomplishing this task would be appreciated. Code posted below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RemoteControlApp2
{
class RemoteControl
{
public delegate void ChannelChanged(object remote, RemoteEventsArgs re);
public event ChannelChanged channelChange;
private int currentChannel;
public void ChangeTheCrrentChannel(int newChannel)
{
RemoteEventsArgs newRe = new RemoteEventsArgs(newChannel);
if (channelChange!=null)
{
channelChange(this, newRe);
}
}
}
class RemoteEventsArgs : EventArgs
{
public int newChannel;
public RemoteEventsArgs(int nc)
{
this.newChannel = nc;
}
}
class Television
{
private int tvChannel;
//Your code here
public void TurnOnTV(RemoteControl Remote)
{
Remote.channelChange += new RemoteControl.ChannelChanged(TVChannelChanged);
Console.WriteLine(Remote.ToString() + " is detected");
}
public void TurnOffTV(RemoteControl Remote)
{
Remote.channelChange -= new RemoteControl.ChannelChanged(TVChannelChanged);
Console.WriteLine(Remote.ToString() + " is no longer detected");
}
public void TVChannelChanged(Object Remote, RemoteEventsArgs nc)
{
Console.WriteLine("The TV channel is changed. New channel is: {0}", nc.newChannel);
}
}
class Radio
{
private int radioChannel;
//Your code here
public void TurnOnRadio(RemoteControl Remote)
{
Remote.channelChange = new RemoteControl.ChannelChanged(TVChannelChanged);
Console.WriteLine(Remote.ToString() + " is deteceted")
}
//May need to write RadioChannelChanged method
}
class Program
{
static void Main(string[] args)
{
RemoteControl rc = new RemoteControl();
Television tv = new Television();
tv.TurnOnTV(rc);
rc.ChangeTheCrrentChannel(29);
rc.ChangeTheCrrentChannel(32);
tv.TurnOffTV(rc);
Console.ReadKey();
}
}
}
I took out event from public event ChannelChanged channelchange;
So now it is public ChannelChanged channelchange;
Next I finished the radio class and TurnOnRadio method and now that event has been removed I can use = to remove all other subscriptions and now subscribes whatever channel the remote is changed to in main. Radio class code posted below.
class Radio
{
private int radioChannel;
//Your code here
public void TurnOnRadio(RemoteControl Remote)
{
Remote.channelChange = new RemoteControl.ChannelChanged(RadioChannelChanged);
//Console.WriteLine(Remote.ToString() + " is deteceted");
}
public void RadioChannelChanged(object Remote,RemoteEventsArgs re)
{
radioChannel = re.newChannel;
Console.WriteLine("Radio channel is changed. New channel is :{0}", re.newChannel);
}
//May need to write RadioChannelChanged method
}