cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot join an Oculus session: "Cannot map local player to unique net ID"

m_milazzo
Protege
I'm trying to create and join an Oculus session. I already succeeded in creating a session by using the Null and the Steam subsystems, but the Oculus' one seems to be more complex.

Rather than using the Unreal's CreateSession and FindSessions blueprint functions I used the Oculus' CreateSession and FindMatchmakingSessions. These one are my Blueprint blocks for creating and searching/joining sessions.
vmact1248j3h.jpg
ir12bk846ske.jpg
The session is created and found correctly (the Oculus matchmaking pool named "ciao" is the one configured on my Oculus dashboard). My problem is the JoinSession function, which actually is the one provided by Unreal, because the Oculus sdk does not provide an equivalent method, so when I call it I receive a warning message "Cannot map local player to unique net ID".

How can I join a session by using blueprints? I'm also trying to create a Blueprint function library and writing the JoinSession with C++, but I don't know how to call the OnlineInterface::JoinSession method correctly. Does someone has an example of code on how to join an Oculus session?
21 REPLIES 21

JPonczek
Honored Guest
I'm having the same exact problem. Please help!

Anonymous
Not applicable
I'd also love to know, as will be tackling multiplayer with blueprints soon! ...

m_milazzo
Protege
I was able to join the matchmaking session by assigning the oculus id as UniqueNetId to the PlayerController (the title's warning message has disappeared when calling the Unreal's JoinSession function).

Unlike what happens with the Null and the Steam subsystems, however, the voice is not replicated from side to side, so the abstraction still has something not working properly (the DefaultEngine.ini is configured like described here, and it actually works with the other aforementioned subsystems)...

brian_jew
Expert Protege


I was able to join the matchmaking session by assigning the oculus id as UniqueNetId to the PlayerController (the title's warning message has disappeared when calling the Unreal's JoinSession function).

That sounds like the PlayerController doesn't automatically get the oculus UniqueNetId when it first initializes and instead is using the local player.


Unlike what happens with the Null and the Steam subsystems, however, the voice is not replicated from side to side, so the abstraction still has something not working properly (the DefaultEngine.ini is configured like described here, and it actually works with the other aforementioned subsystems)...

That's correct.  Right now unlike the other subsystems, Oculus' Voice Interface isn't hooked into the Session subsystem automatically yet (or in other words, joining a session doesn't automatically connect the voices to the other players).  It was kept that way for now to keep it simple, though I can see how this makes it more difficult to rely on blueprints to set this up.

xN31
Protege
@brian_jew : Is Oculus voice chat meant to use the UE4 default Opus codec or a specific one? I thought Oculus voice chat was based on the codec used in Facebook's voice calls, but using the command "online test voice" I see the initialisation of the Opus codec. Is this correct?

m_milazzo
Protege

brian_jew said:

That's correct.  Right now unlike the other subsystems, Oculus' Voice Interface isn't hooked into the Session subsystem automatically yet (or in other words, joining a session doesn't automatically connect the voices to the other players).  It was kept that way for now to keep it simple, though I can see how this makes it more difficult to rely on blueprints to set this up.


Ok, so let's try to start a voice session "manually".
On this page I read to call 
Online::GetVoiceInterface()->RegisterRemoteTalker
to connect to someone else, by passing a FUniqueNetIdOculus object. FUniqueNetIdOculus is declared inside OnlineSubsystemOculusTypes.h, which is private, so I cannot include it. How can I instantiate it?

I tried to call RegisterRemoteTalker with a 
FUniqueNetIdString (which also extends FUniqueNetId) but the id it takes to register the remote talker is not the Oculus' one (with which the FUniqueNetIdString is created).

Thanks for your clarification.

m_milazzo
Protege
Finally we got the voice working. Below is described what we tried to do, we think also this feature has the same problem related to the Oculus player id.

First of all we tried to call RegisterRemoteTalker with the following code, by passing the oculus net id:
bool UMyClass::RegisterRemoteTalker(FString PlayerId) {
FUniqueNetIdString* uniqueNetId = new FUniqueNetIdString(PlayerId);
return Online::GetVoiceInterface()->RegisterRemoteTalker(*uniqueNetId);
}
It returned true (success), but after some seconds it printed this warning log:
LogVoice:Warning: RANDOM_NUMBER timed out
where RANDOM_NUMBER is a number unrelated to the player id (I suspect it was the FUniqueNetIdString object address, it was different also whether the PlayerId was the same).

Since we was unable to use the class FUniqueNetIdOculus class, we copied it from OnlineSubsystemOculusTypes.h to one of our files (it is a simple class).
class FUniqueNetIdOculus : public FUniqueNetId {
private:
ovrID ID;

protected:
virtual bool Compare(const FUniqueNetId& Other) const
{
if (Other.GetSize() != sizeof(ovrID))
{
return false;
}

return ID == static_cast<const FUniqueNetIdOculus&>(Other).ID;
}

public:
/** Default constructor */
FUniqueNetIdOculus()
{
ID = 0;
}

FUniqueNetIdOculus(const ovrID& id)
{
ID = id;
}

FUniqueNetIdOculus(const FString& id)
{
ovrID_FromString(&ID, TCHAR_TO_ANSI(*id));
}

/**
* Copy Constructor
*
* @param Src the id to copy
*/
explicit FUniqueNetIdOculus(const FUniqueNetId& Src)
{
if (Src.GetSize() == sizeof(ovrID))
{
ID = static_cast<const FUniqueNetIdOculus&>(Src).ID;
}
}

// IOnlinePlatformData

virtual const uint8* GetBytes() const override
{
uint8* byteArray = static_cast<uint8*>(malloc(sizeof(uint8) * 4));
check(byteArray);

// convert from an unsigned long int to a 4-byte array
byteArray[0] = static_cast<uint8>((ID >> 24) & 0xFF);
byteArray[1] = static_cast<uint8>((ID >> 16) & 0xFF);
byteArray[2] = static_cast<uint8>((ID >> 😎 & 0XFF);
byteArray[3] = static_cast<uint8>((ID & 0XFF));

return byteArray;
}

virtual int32 GetSize() const override
{
return sizeof(ID);
}

virtual bool IsValid() const override
{
return ID != 0;
}

ovrID GetID() const
{
return ID;
}

virtual FString ToString() const override
{
return FString::Printf(TEXT("%llu"), ID);
}

virtual FString ToDebugString() const override
{
return FString::Printf(TEXT("ovrID: %llu"), ID);
}

/** Needed for TMap::GetTypeHash() */
friend uint32 GetTypeHash(const FUniqueNetIdOculus& A)
{
return GetTypeHash((uint64)A.ID);
}
};
This class uses the function 
ovrID_FromString, which is defined in OVR_Types.h and implemented in LibOVRPlatform64_1.lib. So we included the OVR_* header files in our project and added the file LibOVRPlatform64_1.lib to our Binaries.

Then we modified the function RegisterRemoteTalker thus:
bool UMyClass::RegisterRemoteTalker(FString PlayerId) {
FUniqueNetIdOculus* uniqueNetId = new FUniqueNetIdOculus(PlayerId);
return Online::GetVoiceInterface()->RegisterRemoteTalker(*uniqueNetId);
}
we call it the same way from Blueprint, by passing the same Oculus remote net id and now it is taking the right net id.

Finally we are able to send and receive voice from side to side, but I imagine this isn't how the whole thing should work. May you investigate on it or suggest us how to do the same in a cleaner way?

Anonymous
Not applicable


I was able to join the matchmaking session by assigning the oculus id as UniqueNetId to the PlayerController (the title's warning message has disappeared when calling the Unreal's JoinSession function).


How was this done exactly? Would love to see your blueprint for that 🙂

Would be a great help if blueprints also supported voice out of the box! hint for @brian_jew for a commonly required feature 😉

brian_jew
Expert Protege
Hey ginopeloso,

That's a creative solution, but you are correct there is an easier and cleaner way through UE4.  FUniqueNetIdOculus isn't expose (by UE4 design.  FUniqueNetId class are suppose to be opaque), but if you do have the Oculus Id in a FString you can instea do this:

bool UMyClass::RegisterRemoteTalker(FString PlayerId) {
auto uniqueNetId = Online::GetIdentityInterface()->CreateUniquePlayerId(PlayerId);
return Online::GetVoiceInterface()->RegisterRemoteTalker(*uniqueNetId);
}
That would create the FUniqueNetIdOculus but return it as a FUniqueNetId then plug that into the VoiceInterface.

@aussieburgerVR, I hear you.  We're looking more into blueprints as we realize that there's plenty of great devs like yourself who are using it in there game.