• Unity3D - Discussion
    5,004 replies, posted
The prototype is going to be scrapped anyways if we nail the interview part but I'll play around with it to see if I can add something great.
Anybody have any experience with unity networking and can help me out with this? I am just trying to get player name tags to be over other players. Here is my OnGUI code on the players PlayerNetworkController: [CODE] void OnGUI(){ if(!networkView.isMine){ Vector3 labelPos = thisCamera.WorldToViewportPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name"); } } [/CODE] [IMG]http://i.imgur.com/47sEF3Z.png[/IMG] It should be above the player. Instead, it's on the top left of the screen.
My hunch is that it's returning normalized values. Try multiplying x by the width of the screen?
[QUOTE=garry;40493144]My hunch is that it's returning normalized values. Try multiplying x by the width of the screen?[/QUOTE] Yeah, WorldToViewportPoint returns normalized values. Sadly, multiplying the values by the screen width and height didn't seem to do anything. Using WorldToScreenPoint has the same effect. I thought the coordinates had to be normalized, but now that I think about it that would be pretty weird considering it takes non normalized points in the rect.
[url]http://docs.unity3d.com/Documentation/ScriptReference/Camera.WorldToViewportPoint.html[/url] Yeah it definitely gives out normalized screen values. Maybe try printing them to the console to see what it's giving you?
[QUOTE=garry;40493523][url]http://docs.unity3d.com/Documentation/ScriptReference/Camera.WorldToViewportPoint.html[/url] Yeah it definitely gives out normalized screen values. Maybe try printing them to the console to see what it's giving you?[/QUOTE] Alright, I set the player to be at 0,0,0 and the label should be at 0, 1, 0 then. [CODE] if(!networkView.isMine){ Vector3 labelPos = thisCamera.WorldToViewportPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name"); } [/CODE] printing the labelPos is giving strange results like this: (0.6, 3141130.0, 0.0) but mostly it just prints 0, 0, 0. using thisCamera.WorldToScreenPoint does exactly the same thing. Here is the entire script, maybe it's something else in here that is messing up the label position. [CODE] public class PlayerNetworkController : MonoBehaviour { private string playerName; private Transform worldMesh; private Transform viewMesh; private MouseLook thisMouseLook; private Camera thisCamera; // State synchronization private Vector3 newPos; private Quaternion newRot; // Use this for initialization void Start () { worldMesh = transform.FindChild("playerMesh_w"); //viewMesh = transform.FindChild("playerMesh_v"); thisMouseLook = GetComponent<MouseLook>(); thisCamera = transform.FindChild("playerCamera").camera; if(!networkView.isMine){ thisMouseLook.enabled = false; thisCamera.gameObject.SetActive(false); }else{ worldMesh.gameObject.SetActive(false); // Get the player name from PlayerPrefs playerName = PlayerPrefs.GetString("username"); // Grab the GameManager and tell it to change your name GameObject gameManager = GameObject.Find("GameManager"); gameManager.networkView.RPC("Server_RequestNameChange", RPCMode.Server, Network.player, playerName); } } // Update is called once per frame void Update () { // Lerp the bastard if(!networkView.isMine){ transform.position = Vector3.Lerp(transform.position, newPos, Time.deltaTime * 10); transform.rotation = Quaternion.Lerp(transform.rotation, newRot, Time.deltaTime * 10); } } void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info){ if(stream.isWriting){ Vector3 oldPos = transform.position; Quaternion oldRot = transform.rotation; stream.Serialize(ref oldPos); stream.Serialize(ref oldRot); }else{ newPos = Vector3.zero; newRot = Quaternion.identity; stream.Serialize(ref newPos); stream.Serialize(ref newRot); } } void OnGUI(){ if(!networkView.isMine){ //Vector3 relativePosition = thisCamera.transform.InverseTransformPoint(transform.position); //relativePosition = new Vector3(relativePosition.x, relativePosition.y, Mathf.Max(relativePosition.z, 1.0f)); //Vector3 labelPos = thisCamera.WorldToScreenPoint(thisCamera.transform.TransformPoint(relativePosition + new Vector3(0, 1, 0))); Vector3 labelPos = thisCamera.WorldToScreenPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name"); print(labelPos); } } [/CODE]
You need to change [code]GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name");[/code] to [code]GUI.Label(new Rect(labelPos.x * Screenwidth, labelPos.y * Screenheight, 200, 200), "Name");[/code] (I don't know the proper way to get the screen width/height)
[QUOTE=garry;40494912]You need to change [code]GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name");[/code] to [code]GUI.Label(new Rect(labelPos.x * Screenwidth, labelPos.y * Screenheight, 200, 200), "Name");[/code] (I don't know the proper way to get the screen width/height)[/QUOTE] I shouldn't have to multiply by the screen width and height, WorldToScreenPoint does not return normalized coordinatess, but WorldToViewportPoint does. I am beginning to think it's a problem with the camera that is causing this mess up... What would you do to display a GUI.Label over the other players when you have this data accessible: other layers network id other players name I have no idea.
I tried doing something similar on the last page with my orbit icons. I have an icon displayed according to a world point. Here's my script: [CODE]using UnityEngine; using System.Collections; public class OrbitIcon : MonoBehaviour { public Texture2D iconImage; bool isInLineOfSight; Vector2 screenPos; void Update() { if ( Physics.Linecast(transform.position, Camera.main.transform.position) == false ) isInLineOfSight = true; else isInLineOfSight = false; } void OnGUI() { if ( isInLineOfSight == true ) DisplayIcon(); } void DisplayIcon() { screenPos = Camera.main.WorldToScreenPoint(transform.position); float guiPosX = screenPos.x - ( iconImage.width / 2 ); float guiPosY = ( Screen.height - screenPos.y ) - ( iconImage.height / 2 ); Rect guiRect = new Rect(guiPosX, guiPosY, 22, 22); if ( GUI.Button(new Rect(guiPosX, guiPosY, 16, 16), iconImage, "") ) { Debug.Log("Icon Clicked"); } } } [/CODE] [editline]edit[/editline] wait, this seems to be just what you're doing. I'm not sure then
Oh yea, I'm so happy right now. [thumb]http://i.imgur.com/MvbTSAL.jpg[/thumb]
How does the networking work in Unity? Is there any prediction etc?
Unity networking itself is pretty easy. You hardly have to worry about it. It's standard peer-to-peer, with a option to create small dedicated server. I decided to roll my own solution, because I need a large centralized server, instead of rooms, and I can't afford the middleware. [editline]2nd May 2013[/editline] I believe there isn't any built-in prediction.
There's no built in prediction. The built in networking is pretty sufficient for most multiplayer games, you have access to RPC calls and unity has some built in functionality to sync objects positions and rotations over the network.
Have you fixed your label? It seems like your labelPos.y is incorrect. This part: [code] void OnGUI(){ if(!networkView.isMine){ // omitted Vector3 labelPos = thisCamera.WorldToScreenPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name"); print(labelPos); } }[/code] should be: [code] void OnGUI(){ if(!networkView.isMine){ // omitted Vector3 labelPos = thisCamera.WorldToScreenPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; // 100 is taken from Rect's width and height (in this case, 200) and divided by 2 GUI.Label(new Rect(labelPos.x - 100, Screen.height - (labelPos.y -100), 200, 200), "Name"); print(labelPos); } }[/code]
[QUOTE=secundus;40500130]Have you fixed your label? It seems like your labelPos.y is incorrect. This part: [code] void OnGUI(){ if(!networkView.isMine){ // omitted Vector3 labelPos = thisCamera.WorldToScreenPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; GUI.Label(new Rect(labelPos.x, labelPos.y, 200, 200), "Name"); print(labelPos); } }[/code] should be: [code] void OnGUI(){ if(!networkView.isMine){ // omitted Vector3 labelPos = thisCamera.WorldToScreenPoint(transform.position + new Vector3(0, 1, 0)); GUI.color = Color.black; // 100 is taken from Rect's width and height (in this case, 200) and divided by 2 GUI.Label(new Rect(labelPos.x - 100, Screen.height - (labelPos.y -100), 200, 200), "Name"); print(labelPos); } }[/code][/QUOTE] I actually found out after posting on the unity forums that it is a problem with the camera that I am using for the WorldToScreenPoint function causing the problem. I am right now exploring other ways to display name tags, as using this method won't work with my current network setup. EDIT: So networking is completely confusing me now. I can't even figure out how to do something as simple as making a damn player nametag. I tried to show the nametag when you look at another player using raycast, but I can't do that because clients can't get the owner NetworkPlayer from other objects, only the server can. I am beginning to think my entire server architecture is messed up and I am just really overwhelmed.
[QUOTE=garry;40499458]How does the networking work in Unity? Is there any prediction etc?[/QUOTE] I've been working a lot with networking lately and I had to deal with client side prediction. The major issue is that in order to have a perfect synchronization with the server you need a deterministic physics engine, and it simply doesn't exists yet. I've looked at how Valve solved the issue and it seems like they used multiple network optimization techniques that can be relatively easy to implement. Now if I recall correctly Unity uses Bullet so what you'll have to do first is to implement a proper entity interpolation system. I already got that working by setting up a state history class and performing lerp for the entity position/scaling and slerp for rotation. Now to fix the latency delay on the client-side I started working on a new approach... The main idea is to separate the rigid body simulation and the player collision by using a custom kinematic character controller. When the player presses a key, the character controller simulate the client-side movement using only the static body and then send the input to the server. The server will then perform the same character simulation but with both static and dynamic body and send the result back to the client. The last step is simply to adjust the client (possibly over time) by interpolating both the client and the server states.
Unity uses PhysX [url=http://unity3d.com/unity/quality/physics]according to this page[/url].
[QUOTE=secundus;40506434]Unity uses PhysX [url=http://unity3d.com/unity/quality/physics]according to this page[/url].[/QUOTE] Ah never mind then, they seem to have the "Kinematic Rigidbodies" just for that :v:
So I've got it pretty much figured out, what a pain in the ass. Anyway, having some trouble with changing the alpha of the nametag based on the distance. Currently, it works very well, but the effect is opposite ( closer is less alpha, further is more ). simply putting a - in front of the distance does not work for obvious reasons because the value has to be between 0 and 1. [CODE] Vector3 labelPos = Camera.main.WorldToScreenPoint(rayHit.collider.transform.position + new Vector3(0, .6f, 0)); float distance = Vector3.Distance(transform.position, rayHit.collider.transform.position); distance *= .2f; if(distance > 1.0f){ distance = 1.0f; } GUI.color = new Color(0, 0, 0, distance); GUI.Label(new Rect(labelPos.x - 50, Screen.height - labelPos.y, 100, 100), "Name"); [/CODE]
[QUOTE=Duskling;40507932]So I've got it pretty much figured out, what a pain in the ass. Anyway, having some trouble with changing the alpha of the nametag based on the distance. Currently, it works very well, but the effect is opposite ( closer is less alpha, further is more ). simply putting a - in front of the distance does not work for obvious reasons because the value has to be between 0 and 1. [CODE] Vector3 labelPos = Camera.main.WorldToScreenPoint(rayHit.collider.transform.position + new Vector3(0, .6f, 0)); float distance = Vector3.Distance(transform.position, rayHit.collider.transform.position); distance *= .2f; if(distance > 1.0f){ distance = 1.0f; } GUI.color = new Color(0, 0, 0, distance); GUI.Label(new Rect(labelPos.x - 50, Screen.height - labelPos.y, 100, 100), "Name"); [/CODE][/QUOTE] Try this: [code] GUI.color = new Color(0, 0, 0, 1 - distance); [/code]
Sick. I've still own 'Unity 3.x with the addon of iOS 3.x' thanks to Garry's tweet sometime last year. Where's a good place to start? Any recommended tutorials etc?
[url=http://forum.unity3d.com/threads/26785-Unity-Jump-Start-Video-Tutorials]This tutorial[/url] teaches you the basics of Unity from project creation. In the end you get yourself a simple space invader.
I hate making skyboxes so I made something similar to the one [url=http://garry.tv/2012/10/03/sky-shader/]garry made[/url] for gmod. [t]http://puu.sh/2M3Fo.png[/t] [t]http://puu.sh/2M3HZ.png[/t] It can also update the colours at runtime so I can use it for day-night cycles too, although at the moment though its just a simple gradient from one colour to another. I might add proper horizons and a proper sun to it later on, but this is good enough for me for now.
Getting my game pad to work was frustrating so I created a new project to mess with input, came up with [URL="https://dl.dropboxusercontent.com/u/41313766/Public.html"]this.[/URL] Turned out it was just an issue with the button naming on one of my inputs which kind of makes this a waste of time but hey, I hadn't done any first person stuff until now.
I tried making a GUI texture but it's not showing up right. How can I fix it? The texture (normally 16x16 but I made it bigger so you can see it): [IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/OptionsBox.png[/IMG] What it looks like ingame (zoomed in on the corners): [IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/2013-05-08_16-40-10.png[/IMG][IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/2013-05-08_16-41-29.png[/IMG] [editline]edit[/editline] Planetary gravity for a lunar lander game for school: [t]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/Unity Orbits.png[/t] [sp]It was actually really easy. Made it in about 10 minutes[/sp]
Switch the texture type on that particular texture?
Switch the rendering mode to nearest neighbor. I think.
[QUOTE=Pelf;40574117]I tried making a GUI texture but it's not showing up right. How can I fix it? The texture (normally 16x16 but I made it bigger so you can see it): [IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/OptionsBox.png[/IMG] What it looks like ingame (zoomed in on the corners): [IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/2013-05-08_16-40-10.png[/IMG][IMG]https://dl.dropboxusercontent.com/u/13781308/ShareX/2013-05/2013-05-08_16-41-29.png[/IMG][/QUOTE] You need to change the texture compression to TrueColor.
[QUOTE=Eric95;40581653]You need to change the texture compression to TrueColor.[/QUOTE] That worked. Thanks. Also, does anyone ever find the need to invert the mouse's X axis? I started implementing an options menu but I don't know if I should include an option to invert the mouse X axis. [editline]edit[/editline] Should I ask that in WAYWO instead? Or somewhere in H&S?
[QUOTE=Pelf;40586732]That worked. Thanks. Also, does anyone ever find the need to invert the mouse's X axis? I started implementing an options menu but I don't know if I should include an option to invert the mouse X axis. [editline]edit[/editline] Should I ask that in WAYWO instead? Or somewhere in H&S?[/QUOTE] I think it's usually only the mouse Y. I've played alot of games and I have never seen an option to invert the X.
Sorry, you need to Log In to post a reply to this thread.