Tasharen Entertainment Forum

Support => TNet 3 Support => Topic started by: Braveheart on April 28, 2013, 07:32:25 PM

Title: Setting up and spawning a player
Post by: Braveheart on April 28, 2013, 07:32:25 PM
All

I've set up a FPS controller as my player prefeb, I've added one of the following pieces of code to the scripts that are C# (I assume the Javascript scripts require something like the following also, but I can't figure out what that would be):

  1.         if(!TNManager.isThisMyObject) {
  2.                         enabled = false;       
  3.                 }

  1.         if(TNManager.isThisMyObject) {
  2.                         instance = this;       
  3.                 }

I've also set up an empty game object as my spawn point and attached to that a simple spawn script that calls:

  1. TNManager.Create(player, spawnpoint.position, spawnpoint.rotation);

To spawn players at the defined spawn point. (The player prefab has a TN Auto Sync attached to it. Where might I find information on using RFC instead like was mentioned in a TNet video?) However, there's two issues:

1. When more than one player is in the game, each player controls everyone else; and
2. When a player disconnects, their avatar remains in-game.

Could someone point me in the right direction here please?

Cheers
Title: Re: Setting up and spawning a player
Post by: Braveheart on April 29, 2013, 12:38:54 PM
Okay, so I've been trying to write my own character controllers because I can't figure this out.  It's driving me nuts.  What I'm now doing is this:

Spawn Player code which is attached to an empty game object spawn point:

  1. using UnityEngine;
  2. using System.Collections;
  3. using TNet;
  4.  
  5. public class SpawnPlayer : MonoBehaviour {
  6.        
  7.         public GameObject player;
  8.         public GameObject spawnPoint;
  9.        
  10.         TNObject tno;  
  11.  
  12.         void OnNetworkJoinChannel (bool success, string message) {
  13.                 if(success) {  
  14.                         TNManager.Create(player, spawnPoint.transform.position, spawnPoint.transform.rotation);        
  15.                 }
  16.                
  17.                 else {
  18.                         print ("Error on joining world: " + message);  
  19.                 }
  20.         }
  21.        
  22.         // Use this for initialization
  23.         void Start () {  
  24.                         //tno.Send(1, TNet.Target.AllSaved);   
  25.         }
  26.        
  27.         // Update is called once per frame
  28.         void Update () {
  29.        
  30.         }
  31.        
  32.  [RFC(1)]
  33.         void Spawn() {
  34.                 TNManager.Create(player, spawnPoint.transform.position, spawnPoint.transform.rotation);
  35.         }
  36. }

(I tried putting the TNManager.Create() into the Start() method but that makes each player control every character.) And my character controller script, which contains camera switching:

  1. using UnityEngine;
  2. using System.Collections;
  3. //using TNet;
  4.  
  5. public class FirstPersonController : TNBehaviour {
  6.        
  7.         private Camera fpsCamera;
  8.         private Camera thirdPersonCamera;
  9.        
  10.         private bool firstPerson;
  11.         public float movementSpeed = 3.0f;
  12.         CharacterController cc;
  13.        
  14.         // Use this for initialization
  15.         void Start () {
  16.                
  17.                 if(TNManager.isThisMyObject) {
  18.                        
  19.                         cc = GetComponent<CharacterController>();
  20.                        
  21.                         fpsCamera = GameObject.Find("firstPersonCam").camera;
  22.                         thirdPersonCamera = GameObject.Find("thirdPersonCam").camera;
  23.                        
  24.                         fpsCamera.enabled = true;
  25.                         thirdPersonCamera.enabled = false;
  26.                         firstPerson = true;
  27.                 }
  28.         }
  29.        
  30.         // Update is called once per frame
  31.         void Update () {
  32.        
  33.                                 if(TNManager.isThisMyObject) {
  34.                        
  35.                         if(Input.GetButtonDown("Change Camera")) {
  36.                
  37.                         if(firstPerson == true) {
  38.                                        
  39.                                  thirdPersonCamera.transform.position = Vector3.Lerp(thirdPersonCamera.transform.position, transform.FindChild("ThirdPersonPoint").position, 5.0f);
  40.                              thirdPersonCamera.transform.rotation = transform.FindChild("ThirdPersonPoint").rotation;
  41.                                
  42.                                 fpsCamera.enabled = false;
  43.                                 thirdPersonCamera.enabled = true;
  44.                                 firstPerson = false;
  45.                         }
  46.                
  47.                 else {
  48.                                  fpsCamera.transform.position = Vector3.Lerp(fpsCamera.transform.position, transform.FindChild("FirstPersonPoint").position, 5.0f);
  49.                              fpsCamera.transform.rotation = transform.FindChild("FirstPersonPoint").rotation;
  50.                                        
  51.  
  52.                                 fpsCamera.enabled = true;
  53.                                 thirdPersonCamera.enabled = false;
  54.                                 firstPerson = true;
  55.                         }
  56.                 }
  57.                        
  58.                 float forwardSpeed = Input.GetAxis("Vertical") * movementSpeed;
  59.                 float sideSpeed = Input.GetAxis("Horizontal") * movementSpeed;
  60.                 float jumpHeight = 2.0f;
  61.                        
  62.                 bool jump = Input.GetButtonDown("Jump");
  63.                        
  64.                         if(jump) {
  65.                                 cc.SimpleMove(new Vector3(0, jumpHeight, 0));
  66.                         }
  67.                                        
  68.                 Vector3 speed = new Vector3(sideSpeed, 0, forwardSpeed); // 1st: L/R, 2nd: Up/Dwn, 3rd: Fwd/Bk
  69.                
  70.  
  71.                
  72.                 cc.SimpleMove(speed);
  73.                        
  74.                 }
  75.         }
  76. }
  77.  

1. Should I include the two cameras as part of the player prefab, or just have them in the scene ready to be set to the correct player object? Or does it not matter?

2. When I start up the game everything works as expected when there's one player in the game, as soon as another player joins though the first player loses all control of their character and only player two can control their character. The same happens when a third player joins; only they can control their character. And so on and so forth... Oddly, when player three leaves player two re-gains control, but player one doesn't when player two leaves. All players are also re-spawned when a new player enters.  Why is this all happening?
 
2.1 How can I get this all fixed up to where each player properly controls themselves and only themselves? 
2.2 How can I get the player's character to be removed when they disconnect?

Can someone please offer me some assistance!? I would greatly appreciate it.  My apologies for the double post but I wanted to add further detail and get my post noticed :P!
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 29, 2013, 05:26:10 PM
Alright so starting from the top...

TNManager.isThisMyObject will only work correctly in Awake(). For any other place you need to check TNObject's isMine flag instead.

Do this and your original attempt should fall into place correctly.

For removal of player objects, you need to do it in OnNetworkPlayerLeft().
Title: Re: Setting up and spawning a player
Post by: Braveheart on April 29, 2013, 06:08:29 PM
Alright so starting from the top...

TNManager.isThisMyObject will only work correctly in Awake(). For any other place you need to check TNObject's isMine flag instead.

Do this and your original attempt should fall into place correctly.

For removal of player objects, you need to do it in OnNetworkPlayerLeft().

Thank you for the reply! I've tried adding that to my Awake function in the FPS controller script.  I still get the same effect as before, when player two joins both players re-spawn and player one loses control of their character... arg! What am I missing?

I have two scenes, one for MainMenu (handles connecting to the server etc) and the other for the World (the actual game word in which spawning, sync etc are handled).  Both of these have TNManagers in them, is this correct or should only one scene contain one?

Could you give me an example of using tno.isMine? I have the following in my fps controller:

TNObject tno;

So if I then do tno.isMine, is this checking if the attached game object is mine?
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 29, 2013, 06:14:03 PM
You can check tno.isMine anywhere you like. For example in the Update function just before you do actual FPS movement. Only proceed if tno.isMine.

In the example script you posted you are using TNObject.isThisMyObject in Update() -- which will not work as I explained. You need to replace all instances of that with tno.isMine instead.
Title: Re: Setting up and spawning a player
Post by: Braveheart on April 29, 2013, 06:58:30 PM
Ok - I've changed to tno.isMine.  I'm still getting the same effect as before though, when player two joins player one loses control of their character.  And I can't get the player object to delete properly upon a player leaving/closing the game, meaning when I re-join I'm getting only partial control of the camera which is completely odd (up down control).  Below is my FPS controller attached to each player:

  1. using UnityEngine;
  2. using System.Collections;
  3. using TNet;
  4.  
  5. public class FirstPersonController : TNBehaviour {
  6.        
  7.         private Camera fpsCamera;
  8.         private Camera thirdPersonCamera;
  9.        
  10.         private bool firstPerson = true;
  11.         public float movementSpeed = 3.0f;
  12.        
  13.         public float mouseSensitivity = 6.0f;
  14.         float verticalRot = 0;
  15.         private float UpDownRange = 60.0f;
  16.        
  17.         CharacterController cc;
  18.        
  19.         TNObject tno;
  20.  
  21.        
  22.         void Awake() {
  23.                         if(TNManager.isThisMyObject) {
  24.                                 tno = this.GetComponent<TNObject>();
  25.                 }
  26.                
  27.                 else this.enabled = false;     
  28.         }
  29.         // Use this for initialization
  30.         void Start () {
  31.                                 if(tno.isMine) {
  32.                 Screen.lockCursor = true;
  33.                
  34.                 cc = GetComponent<CharacterController>();
  35.                        
  36.                 fpsCamera = GameObject.Find("firstPersonCam").camera;
  37.                 thirdPersonCamera = GameObject.Find("thirdPersonCam").camera;
  38.                        
  39.                         fpsCamera.enabled = true;
  40.                         thirdPersonCamera.enabled = false;
  41.                         firstPerson = true;
  42.                        
  43.                 }
  44.         }
  45.        
  46.        
  47.         void OnNetworkPlayerLeft(Player p) {
  48.                 TNManager.Destroy(gameObject);         
  49.         }
  50.        
  51. void OnNetworkDisconnect() {
  52.         if(tno.isMine) {
  53.                 TNManager.Destroy(gameObject); 
  54.                 TNManager.Destroy(tno);
  55.         }
  56.         }
  57.        
  58.        
  59.         void Update () {
  60.        
  61.                 if(!tno.isMine) {
  62.                         this.enabled = false;
  63.                 }
  64.                
  65.                 if(tno.isMine) {
  66.                                                        
  67.                         // CHANGE CAMERA PERSPECTIVE
  68.                        
  69.                         if(Input.GetButtonDown("Change Camera")) {
  70.                
  71.                         if(firstPerson == true) {
  72.                                        
  73.                                  thirdPersonCamera.transform.position = Vector3.Lerp(thirdPersonCamera.transform.position, transform.FindChild("ThirdPersonPoint").position, 5.0f);
  74.                              thirdPersonCamera.transform.rotation = transform.FindChild("ThirdPersonPoint").rotation;
  75.                                
  76.                                 fpsCamera.enabled = false;
  77.                                 thirdPersonCamera.enabled = true;
  78.                                 firstPerson = false;
  79.                         }
  80.                
  81.                 else {
  82.                                  fpsCamera.transform.position = Vector3.Lerp(fpsCamera.transform.position, transform.FindChild("FirstPersonPoint").position, 5.0f);
  83.                              fpsCamera.transform.rotation = transform.FindChild("FirstPersonPoint").rotation;
  84.                                        
  85.  
  86.                                 fpsCamera.enabled = true;
  87.                                 thirdPersonCamera.enabled = false;
  88.                                 firstPerson = true;
  89.                         }
  90.                 }
  91.                        
  92.                
  93.             // ROTATION
  94.                        
  95.                         float rotUpDown = Input.GetAxis("Mouse Y") * mouseSensitivity;
  96.                         float rotLeftRight = Input.GetAxis("Mouse X") * mouseSensitivity;
  97.                        
  98.                         transform.Rotate(0, rotLeftRight, 0);
  99.                        
  100.                         verticalRot -= Input.GetAxis("Mouse Y") * mouseSensitivity;
  101.                        
  102.                         if(firstPerson == true) {              
  103.                                         UpDownRange = 60.0f;
  104.                         }
  105.                         else {
  106.                                    UpDownRange = 30.0f;
  107.                         }
  108.                        
  109.                                                
  110.                         verticalRot = Mathf.Clamp(verticalRot, -UpDownRange, UpDownRange);
  111.                                
  112.  
  113.                                 if(firstPerson == true) {
  114.                                 fpsCamera.transform.localRotation = Quaternion.Euler(verticalRot, 0, 0);                               
  115.                         }
  116.                        
  117.                         else {
  118.                                 thirdPersonCamera.transform.localRotation = Quaternion.Euler(verticalRot, 0, 0);       
  119.                         }
  120.  
  121.                 // MOVEMENT
  122.                        
  123.                 float forwardSpeed = Input.GetAxis("Vertical") * movementSpeed;
  124.                 float sideSpeed = Input.GetAxis("Horizontal") * movementSpeed;
  125.                 float jumpHeight = 2.0f;
  126.                        
  127.                 bool jump = Input.GetButtonDown("Jump");
  128.                        
  129.                         if(jump) {
  130.                                 cc.Move(new Vector3(0, jumpHeight, 0));
  131.                         }
  132.                                        
  133.                 Vector3 speed = new Vector3(sideSpeed, 0, forwardSpeed); // 1st: L/R, 2nd: Up/Dwn, 3rd: Fwd/Bk
  134.                                
  135.                 speed = transform.rotation * speed;    
  136.        
  137.                        
  138.                 if(Input.GetMouseButton(1)) {           // MOUSE BUTTON 2              
  139.                 }  
  140.                                
  141.                 cc.SimpleMove(speed);
  142.                        
  143.                 }
  144.                
  145.                 else this.enabled = false;
  146.         }
  147. }
  148.  

And the spawn script:

  1. using UnityEngine;
  2. using System.Collections;
  3. using TNet;
  4.  
  5. public class SpawnPlayer : MonoBehaviour {
  6.        
  7.         public GameObject player;
  8.         public GameObject spawnPoint;
  9.        
  10.         FirstPersonController fp;
  11.        
  12.         TNObject tno;
  13.        
  14.         void Awake() {
  15.                 if(TNManager.isThisMyObject) {
  16.                                
  17.         }      
  18.         }
  19.        
  20.         void OnNetworkJoinChannel (bool success, string message) {
  21.                 if(success) {          
  22.                         TNManager.Create(player, spawnPoint.transform.position, spawnPoint.transform.rotation);        
  23.                 }
  24.                
  25.                 else {
  26.                         print ("Error on joining world: " + message);  
  27.                 }
  28.         }
  29.                
  30.         // Update is called once per frame
  31.         void Update () {
  32.  
  33.         }
  34.        
  35.  [RFC(1)]
  36.         void Spawn() {
  37.                 TNManager.Create(player, spawnPoint.transform.position, spawnPoint.transform.rotation);
  38.         }
  39. }
  40.  


What am I missing!?
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 29, 2013, 08:25:20 PM
Your Awake() function is not needed at all. "tno" is already set for you when you derive from TNBehaviour.

Prior to doing a destroy in OnNetworkPlayerLeft you need to check -- did this player own this script before? If so, destroy it, and only then. I recommend saving the "player owner" in Start(). You currently destroy every script when a single player leaves.

OnNetworkDisconnect() is not going to do anything in your case either. If you get disconnected, you should load a disconnect level (or the main menu), not destroy anything. When you're disconnected, destroying objects is pointless. It's not like you are going to sync this with other players. After all, you're disconnected by this point.

I strongly suggest you watch the "making a multiplayer game from scratch" training video for TNet. It covers most of what you are trying to do.

You can also grab the entire example project for it here: http://www.tasharen.com/tnet/TNetExample2.unitypackage
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 29, 2013, 08:55:08 PM
P.S. You know that one of the flags on the Create() function is "persistent", meaning the object will be automatically destroyed when the player leaves if this is set to 'false'?
Title: Re: Setting up and spawning a player
Post by: Braveheart on April 30, 2013, 02:48:14 AM
Yeah I figured NetworkDisconect wouldn't do anything, I was just trying all the methods to see if anything worked as expected.  How would I save the player owner in Start()? When a single player joins then leaves, networkPlayerLeave doesn't destroy anything.  When there's two players and any leave, it only destroys one player.

I didn't know of Persistent in Create()... that saves me a headache lol!  What I don't understand though is still when a second player joins player one is losing all control except for pitch control over a camera.  Should the spawn script be attached to the player object too?  I may have to try setting up a really basic spawn a simple cube that moves left and right and get everything working on that first.

I watched the video and I'm trying to piece together things on my end with the video and examples in mind, but it's proving difficult as they're two different games.

Sorry for all these questions, I'm just trying to wrap my head around how this all works so I can start building things properly.  It seems like it should be pretty straightforward yet there's a lot of unexpected and odd behaviour, I'm probably overlooking something really simple.
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 30, 2013, 07:30:04 AM
Each player joining should result in a new player instance, and it should only be managed by the player that created it. This is handled like that in the video tutorial (and the package I linked). It certainly does sound like you are overlooking something simple.
Title: Re: Setting up and spawning a player
Post by: Braveheart on April 30, 2013, 12:15:42 PM
Okay, I still can't figure this out.

I've had a run through the example project you posted above (the one from the tutorial video) and I've copy-pasted a lot of it into a test scene to try and get this working.  I have:

PlayerControl.cs (attached to the player prefab which is referenced in the TNManager in the MainMenu scene):

  1. using UnityEngine;
  2. using System.Collections;
  3. using TNet;
  4.  
  5. public class PlayerControl : TNBehaviour {
  6.  
  7.         static public PlayerControl instance;
  8.        
  9.         CharacterController cc;
  10.        
  11.         Vector3 mTarget = Vector3.zero;
  12.        
  13.          private Vector3 moveDirection = Vector3.zero;
  14.        
  15.                 public Vector3 target
  16.         {
  17.                 set
  18.                 {
  19.                         tno.Send(5, TNet.Target.AllSaved, value);
  20.                 }
  21.         }
  22.        
  23.        
  24.                 void Awake ()
  25.         {
  26.                 if (TNManager.isThisMyObject)
  27.                 {
  28.                         instance = this;               
  29.                         cc = GetComponent<CharacterController>();
  30.                 }
  31.         }
  32.        
  33.                 void Update ()
  34.         {
  35.                 if(tno.isMine) {       
  36.                         cc.SimpleMove(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")));
  37.                 }
  38.                
  39.                 else {
  40.                         transform.position = Vector3.MoveTowards(transform.position, mTarget, 3f * Time.deltaTime);    
  41.                 }
  42.         }
  43.        
  44.                 void OnNetworkPlayerJoin (Player p)
  45.         {
  46.                 tno.Send(6, p, transform.position);
  47.         }
  48.        
  49.         [RFC(5)]
  50.         void OnSetTarget (Vector3 pos)
  51.         {
  52.                 mTarget = pos;
  53.         }
  54.  
  55.         [RFC(6)]
  56.         void OnSetTargetImmediate (Vector3 pos)
  57.         {
  58.                 transform.position = pos;      
  59.         }
  60. }
  61.  

PlayerSpawn.cs (which is attached to an empty game object marking the spawn point in the World scene):

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class PlayerSpawn : MonoBehaviour {
  5.        
  6.         public GameObject player;
  7.         public GameObject spawnPoint;
  8.        
  9.         void Start() {         
  10.         }
  11.         void OnNetworkJoinChannel (bool success, string message) {
  12.                 if(success) {    
  13.                         TNManager.Create(player, spawnPoint.transform.position, spawnPoint.transform.rotation, false); 
  14.                 }
  15.                
  16.                 else {
  17.                         print ("Error on joining world: " + message);  
  18.                 }
  19.         }
  20. }
  21.  

This works for one player.  As soon as a second player joins both players begin controlling the same character and the new character flies off to Vector3.zero. Why is that? Getting closer...
Title: Re: Setting up and spawning a player
Post by: ArenMook on April 30, 2013, 10:31:12 PM
You check tno.isMine correctly in update, but you have an "else" fallback that happens on the non-owned objects that lerps the position to mTarget, which is never set anywhere. Instead you use cc.SimpleMove, and you never sync its position, or update mTarget.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 01, 2013, 06:08:59 AM
Finally, it works! Thanks.

Some other things, when another player spawns they start to move towards vector3.Zero but then immediately sync to the correct position. What would cause the delay? Also the movement sync lags every now and again, I'm guessing I'd solve this with local prediction (if player 1 was moving on positive X keep doing that until further update received)?

And how would I go about having new players request via an RFC to be spawned, have the host (acting like an authoritive server) do the TNManager.Create()? Because surely if I do just that the player object will belong to the host player, right? So how would I pass ownership of the player object back to the player who had requested the spawn?

Thanks!
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 02, 2013, 03:36:35 AM
Players should spawn themselves using TNManager.Create. Player should own their own avatar, not the host.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 02, 2013, 06:09:08 AM
Is it not possible then to have a client send an RFC requesting to move have the host do the moving via sending an RFC to everyone?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 02, 2013, 08:23:45 AM
Why would you want that? I mean yes, you can (Target.Host), but why? In games you generally want each player to always feel responsive, so if their own character "lags" because it has to wait on the host, it would be bad.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 02, 2013, 09:15:41 AM
I'd like the game to be authoritive so clients can't send bogus RFC's and teleport, spawn at different places etc.  My plan was to have the local client move themselves anyway and just lerp/move to (like everyone else sees them do) to the authorised position.  That would work, right?

Or is there a better way to prevent bogus position updates and other game events (like player 1 claiming they shot player 2)?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 03, 2013, 08:48:36 AM
It's better to have the host run verification logic instead. Let the client "teleport", but the host should keep an eye on the distance of movement in RFCs -- if it's too much, boot the player.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 03, 2013, 10:41:15 AM
So would that would be something along the lines of:

  1. if(TNManager.isHosting) {
  2.  if(currentPosition - newPosition > 100) {
  3.       Print("This player has teleported)";
  4.        etc...
  5.    }
  6. }
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 03, 2013, 11:18:38 AM
Yup.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 03, 2013, 11:25:10 AM
Excellent. Thanks for all your help so far, I really appreciate it! I'm finally beginning to understand how this works.

So now that I have everything set up and spawning, I need a little help with movement. This is the code I'm using to sync positions:

  1.                
  2.                 if(!tno.isMine) {                              
  3.                        
  4. transform.position = Vector3.Lerp(transform.position, mTarget, Time.deltaTime * sentSpeed);    
  5.                        
  6.                         if(transform.rotation != mTargetRot) {
  7.                                 transform.rotation = Quaternion.Slerp(transform.rotation, mTargetRot, sentSpeed * Time.deltaTime);
  8.                         }                      
  9.                 }

And the end of my movement code I call the following RFC to update the position over the network:

  1.         [RFC(5)]
  2.         void OnSetTarget (Vector3 pos, Quaternion rot, float speed)
  3.         {
  4.                 mTarget = pos;
  5.                 mTargetRot = rot;
  6.                 sentSpeed = speed;
  7.         }

I've tried using Vector3.MoveTowards() and Vector3.SmoothDamp() and in every case the movement is smooth but there's quite a bit of lag now and again, especially when jumping. What would you recommend for cutting down on this as much as possible?

Side question: can I not check tno.isMine in JavaScript scripts?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 03, 2013, 09:40:10 PM
You must place C# scripts into the Plugins folder if you want to use them with javascript. It's the same as NGUI.

I recommend separating physics from the renderer. Renderer can smoothly follow an immediately-updated physics object.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 03, 2013, 10:51:06 PM
You must place C# scripts into the Plugins folder if you want to use them with javascript. It's the same as NGUI.

I recommend separating physics from the renderer. Renderer can smoothly follow an immediately-updated physics object.

How would I separate physics from the renderer? I have a simple capsule with a character controller attached to it.  So do you mean I should have a separate object (empty GameObject?) which the position of is updated and have the capsule with the controller parented to it?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 04, 2013, 01:13:38 PM
Just look at what I did with the cubes from the 2nd example that comes with TNet and do the same thing. :)
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 04, 2013, 02:25:16 PM
Okay great, that seems to have fixed a lot of movement issues. EDIT: In fact I don't think it did, does that technique only work on rigid bodies? My player has a character controller attached to it.

If I want clients to send data to the server (e.g. username and password) and then have the server code communicate to an external mySQL database, can I do this with a custom packet? (Explained in your tutorial (I've yet to watch it) http://www.youtube.com/watch?v=cmc_oIWmroI.)

Which server files would I edit, or is this explained in the tutorial?

Thanks for all your help thus far ArenMook! I'm looking to make a fairly large and many player world, will TNet be able to handle a lot of simultaneous connections (500+?) and a lot of AI all validated and ran through the host?
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 06, 2013, 10:33:51 PM
Okay great, that seems to have fixed a lot of movement issues. EDIT: In fact I don't think it did, does that technique only work on rigid bodies? My player has a character controller attached to it.

If I want clients to send data to the server (e.g. username and password) and then have the server code communicate to an external mySQL database, can I do this with a custom packet? (Explained in your tutorial (I've yet to watch it) http://www.youtube.com/watch?v=cmc_oIWmroI.)

Which server files would I edit, or is this explained in the tutorial?

Thanks for all your help thus far ArenMook! I'm looking to make a fairly large and many player world, will TNet be able to handle a lot of simultaneous connections (500+?) and a lot of AI all validated and ran through the host?

Bump, Aren could you give me some input on communicating with mySQL via client sends request to server with information to query with mySQL? Custom packet? Can I code some mySQL connection and querying code straight into the Server.cs file(s)?

Also I'm TNManager.Creating a bullethole prefab with persistent marked true however they are not remaining in-game after all players exit, why would this be?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 06, 2013, 11:13:16 PM
Unless you create your channel with the persistent flag 'true', the channel will be closed when the last player leaves.

I can't help you much with SQL. That's outside the kit's functionality. Sending a custom packet is easy, but what happens after the server receives that packet is entirely up to you.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 06, 2013, 11:43:33 PM
Unless you create your channel with the persistent flag 'true', the channel will be closed when the last player leaves.

I can't help you much with SQL. That's outside the kit's functionality. Sending a custom packet is easy, but what happens after the server receives that packet is entirely up to you.

Where about do I set the channel to persistent if I'm using the standalone server?

What I'm asking though is, if I want to add in mySQL communication code, can I:

Send a custom packet with say username and password to the server; then
have inside the server code the mySQL communication code which after that executes sends a response back to the client?

Or would the mySQL code have to go outside of the server files?

Also is there an easy way to add a child object to an object that was created via TNManager.Create?
What about make another object the parent of the one you created?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 07, 2013, 12:32:45 AM
It's one of the parameters in JoinChannel function.

I recommend keeping as much in memory as you can. SQL calls are expensive and take a while to query. It would be a lot faster to keep all the usernames and associated encrypted passwords in memory, as a simple memory look up is going to be several orders of magnitude faster.

But yes, you can structure it so that your server can call SQL -- but again the SQL communication is up to you, and I can't be of much help with that.

I would not recommend parenting dynamically instantiated objects because when time comes to destroying one of them, things can get hairy.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 07, 2013, 12:55:29 AM
In memory as in, static variables? Wouldn't those be exposed to cheaters, though?

I wanted to ask about the host authorising stuff also, my game is intended to have quite a number of players and I have the host doing all rigidbody bullet movement and hit detection also they will validate damage of these bullets too.  I plan to have the host do quite a bit in terms of validation (all SQL calls would be routed through them, AI and such like).  Is this going to cause problems with a lot of players in the game?

Also, is there any way to quickly send an RFC to only players close by? Or would I have to look for players within X distance and loop through them individually sending them the RFC's?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 07, 2013, 05:06:34 AM
SQL would be on the server-side, so how would cheaters have access to that? You are mixing the terms "host" and "server" I think.

Server is a stand-alone application you connect to. It has no knowledge of Unity, or your game.

Host is just another player. Only one player per channel is designated a "host".
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 07, 2013, 05:34:58 AM
I know that. You advised I keep variables in memory do you mean for example a static variable? If storing stuff in memory as opposed to SQL and requesting it wouldn't a hacker be able to modify the static variables?

Yeah I know the difference. Seeing how the host is another player processing everything that is required to play, will having a lot of additional processes and validation (AI, shooting, SQL updates etc) affect the host player's performance?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 07, 2013, 04:08:16 PM
Any variable you have is stored in memory. It has nothing to do with being static. If you have a custom SQL manager, you can have it query the database in the beginning, getting all the entries back. Use these entries to create your own table in memory (just an array or dictionary of structs), and from that point onward consult this table rather than executing queries. This should only be done on the server -- which is inaccessible from hackers.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 08, 2013, 04:12:38 PM
Thanks Aren. Could you explain in a little more depth how I would use tno.isMine etc inside of a JavaScript script? I don't own NGUI so I don't know what you meant by place them into the Plugins folder.
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 08, 2013, 05:05:24 PM
http://www.tasharen.com/forum/index.php?topic=6.0 has a picture. With TNet the idea is the same. Everything except the Editor folder should be moved into the Plugins folder. This makes all C# classes accessible from JS.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 08, 2013, 07:16:42 PM
Thanks again, got it all working!

I'm still having issues with choppy movement and slight delays in RFCs (both send and sendQuickly) though, even playing locally movement is extremely choppy... any further assistance you can offer? Strangely, using Unity's own networking the same code has no choppy movement.
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 08, 2013, 07:53:24 PM
Depends on how you send your data. It's best to send sync updates infrequently, and to separate renderer from collider. Look at what I did with the second example -- boxes there have their renderer lag behind and smoothly follow the immediately updated collider.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 09, 2013, 07:11:10 PM
Does that technique only work for rigidbodies?

I'm getting an odd error - TNet is telling me it can't sent a function and asking if I may have missed an RFC. The thing is, the function it's talking about I removed from my code ages ago but it's still throwing the error and causing my movement script to stop working.  I've tried using an entirely different player prefab which never included the offending code and still I'm getting an error about it. Any ideas?
Title: Re: Setting up and spawning a player
Post by: ArenMook on May 09, 2013, 11:47:35 PM
Was it a persistent function, used in a persistent channel? Delete server.dat file.
Title: Re: Setting up and spawning a player
Post by: Braveheart on May 10, 2013, 05:56:02 AM
Of course! Yes it was, thanks Aren.