Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by PanDenat · Oct 27, 2015 at 09:32 AM · networkingunity 5.2

[UNet] How to initialize non-local player?

I'd like to initialize differently local and other clients' players. And apparently there is no easy way to do it.

For local player I just override OnStartLocalPlayer and everything is cool. But what about players from network? For example if I want a different instantiate animation for local players and network players? Where should I put "StartAwesomeNetworkBzzzztAnimation()"?

I cannot do it in OnStartClient because the isLocalPlayer flag is not set yet.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by thegreatzebadiah · Nov 16, 2015 at 01:49 AM

I think I more or less solved this by using the low level api to send a message to the server any time OnStartClient is called. The server listens for the message and sends a ClientRpc back that calls OnStartNonLocalPlayer:

In my Player script:

 public override void OnStartClient()
 {
   networkManager.client.Send(MsgType.RequestNonLocalPlayerInit, new NetIDMessage(netId));
 }

 [ClientRpc]
 public void RpcStartNonOwner() 
 {
   if (!isLocalPlayer)
   {
       OnStartNonOwner();
   }
 }

 public void OnStartNonOwner()
 {
   // Do the thing
 }

And then in my NetworkManager

 public override void OnMatchCreate(CreateMatchResponse matchResponse)
 {
   base.OnMatchCreate(matchResponse);
   if (matchResponse.success)
   {
     NetworkServer.RegisterHandler(MsgType.RequestNonLocalPlayerInit, OnRequestNonLocalPlayerInit);
   }
 }

 public void OnRequestNonLocalPlayerInit(NetworkMessage msg)
 {
   NetIDMessage idMsg = msg.ReadMessage<NetIDMessage>();
   GameObject player = ClientScene.FindLocalObject(idMsg.netId);
   player.GetComponent<PlayerNetworked>().RpcStartNonOwner();
 }

I think this may be a better solution than the one @seanr posted because it handles cases with more than 2 players. @seanr's solution won't work since ClientRpc's aren't buffered. When the first client connects to the server, the player spawns and the rpc is sent, but when a second client connects they will never receive the rpc to initialize the first non-local player since it was sent before they connected.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image PanDenat · Nov 16, 2015 at 09:40 AM 0
Share

That's nice solution and pretty straightforward. The main problem with it is that OnStartNonOwner is not guaranteed to run on the first frame Player is enabled (and problably usually doesn't). On laggy network (mobile for example) it can result in spawn animation playing long (even a second?) after new players shows up.

avatar image thegreatzebadiah PanDenat · Nov 16, 2015 at 10:10 AM 0
Share

If you're worried about the delay you could alternatively do something similar to what @seanr suggested, as long as you make sure to re-send the rpc every time a new client connects. That way the message gets sent out immediately after the client connects rather than waiting for the client to request it. Of course all the already connected clients will receive the rpc every time a new client connects but that's easy enough to check for and ignore. Unfortuntely I can't test it at the moment to make sure it actually works or I'd post it as another answer.

avatar image
1

Answer by seanr · Oct 28, 2015 at 03:32 PM

There is no built-in hook for that. The best solution is probable to invoke a ClientRpc after the player object is spawned, and run the instantiate animation in that handler - but NOT if isLocalPlayer is set.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image PanDenat · Oct 29, 2015 at 11:07 AM 0
Share

I was thinking about just waiting one frame after OnStartClient (with coroutine) and then checking isLocalPlayer. But it still looks like an ugly workaround.

avatar image seanr PanDenat · Oct 29, 2015 at 01:40 PM 0
Share

that would not be guaranteed to work - for ti$$anonymous$$g reasons.

avatar image PanDenat seanr · Oct 29, 2015 at 02:22 PM 0
Share

How so? As far as I know OnStartClient and OnStartLocalPlayer launches in the same frame one after another, so after one frame I'm sure that isLocalPlayer is set. Or is it possible that those methods do not run in the same frame?

Show more comments
avatar image thegreatzebadiah · Nov 16, 2015 at 12:52 AM 1
Share

Doesn't this not work since ClientRpc's aren't buffered? When the first client connects to the server, the player spawns and the rpc is sent, but then when a second client connects they will never receive the rpc to initialize the first non-local player.

avatar image
1

Answer by francesco_dente · Oct 29, 2015 at 04:44 PM

I solved the problem by initializing a generic network player inside of OnStartClient() and then overriding the local player settings inside of onStartLocalplayer(), but I think this is also not a great workaround.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
-1

Answer by BlackManta · Oct 14, 2017 at 08:42 PM

I think you can make the assumption OnStartLocalPlayer will happen fairly quickly after OnStartClient. If you do that you can use coroutines.

 private bool isAllSet = false
 
 public override void OnStartLocalPlayer()
 {
 //reset parameters for local player
 }
 public override void OnStartClient()
 {
 //Assume that this is going to be a remote machine
 //Set parameters for remote
 StartCoroutine(AllSetup());
 }
 
 private IEnumerator AllSetup()
 {
     //Need to wait to see if the local player function triggers
    yield return new WaitForSecodns(1); //or some other time.
    //Now determine if you are local player or not.
         if (!isLocalPlayer)
          {
             //Local Player Animation
          }
      else
      {
          //Remote Player Animation
        }
 }


Also I think you could use async if you are using C# 5. However, I would have to play around with that one for a bit.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by hexagonius · Jan 28, 2018 at 08:12 PM

These are my solutions:

  1. In case you just want a call to non local players without receiving info from the actual localplayer:

    void Start() { if (!isLocalPlayer) InitNonLocalPlayer(); }

    void InitNonLocalPlayer(){}

  2. In case you need information about the actual LocalPlayer on the nonLocalPlayers:

    void OnStartLocalPlayer() { CmdInfoToNonLocalPlayers(); }

    [Command] void CmdInfoToNonLocalPlayers() { RpcInfoToNonLocalPlayers() }

    [ClientRpc] void RpcInfoToNonLocalPlayers() { if (isLocalPlayer) return;

    // Do what you need to do on nonLocalPlayers with info }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

9 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Unet Client child object not rendering 0 Answers

UNet ClientRPC does not fire 2 Answers

UNET 5.2: How do you use NetworkServer.SpawnWithClientAuthority()? 1 Answer

SpawnWithClientAuthority Player object is not a Player 1 Answer

Unity networking tutorial? 6 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges