问题描述
我的工作和学习团结5,UNET和网络的一些基础知识。我做了一个简单的3D游戏,你去走一走,改变物体的颜色。但我想,以现在的多人,我有很多的麻烦找出如何通过网络发送的变化让所有玩家都可以看到一个玩家的颜色变化。
I'm working on and learning some basics of Unity 5, UNET, and networking. I made a simple 3D game where you go around and change the colors of objects. But I want to make it multiplayer now, and I am having lots of trouble figuring out how to send the changes over the network so all players can see a single player's color change.
部分的问题是,它已经很难寻找到较新的UNET网络引擎答案。有时候我会遇到一些为老办法的答案。
Part of the issue is that it has been difficult to find the answer using the newer UNET networking engine. And sometimes I come across answers that are for the older way.
所以,主要的问题是,如何连接非玩家游戏物体属性的变化?颜色,形状,大小等。
So the main question is, how do I network non-player GameObject property changes? Color, shape, size, etc..
下面是一些代码,我现在 - 和我有很多不同的版本,所以我将只发布当前的:
Here is some code I have now - and I've had many different versions so I'll just post the current one:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Player_Paint : NetworkBehaviour {
private int range = 200;
[SerializeField] private Transform camTransform;
private RaycastHit hit;
[SyncVar] private Color objectColor;
[SyncVar] private GameObject objIdentity;
void Update () {
CheckIfPainting();
}
void CheckIfPainting(){
if(Input.GetMouseButtonDown(0)) {
if (Physics.Raycast (camTransform.TransformPoint (0, 0, 0.5f), camTransform.forward, out hit, range)) {
string objName = hit.transform.name;
CmdPaint(objName);
}
}
}
[ClientRpc]
void RpcPaint(){
objIdentity.GetComponent<Renderer>().material.color = objectColor;
}
[Command]
void CmdPaint(string name) {
objIdentity = GameObject.Find (name); //tell us what was hit
objectColor = new Color(Random.value, Random.value, Random.value, Random.value);
RpcPaint ();
}
}
我已经尝试了一大堆更多的解决方案,其中包括写作在我想改变,包括[SyncVar]和钩子函数,其颜色的对象单独的脚本。我也试着在每一个我期待更新客户端上的对象以及它们与预期的数据执行功能的debug.log。
I've tried a bunch more solutions, including writing a separate script on the objects whose color I want to change and including [SyncVar] and hook functions. I've also tried Debug.Log on each of the functions I'm expecting to update the objects on the clients and they are executing with the expected data.
我真的不知道还能做什么。我觉得这是一个非常简单的事情,我想这样做,但我还没有碰到过同步非玩家游戏物体的任何问题,教程或其他资源。任何想法都将是有益的,谢谢。
I really don't know what else to do. I feel like it is a VERY simple thing I want to do, but I haven't come across syncing non-player GameObject's in any questions, tutorials, or other resources. Any ideas at all would be helpful, thank you.
推荐答案
我发现我的答案。 ,这是非常困难的,因为几乎每一个问题,张贴,例如,等...我能找到约为球员的对象,而不是非玩家的对象。
I found my answer. And it was very difficult, as almost every single question, post, example, etc... I could find was about player objects, and not non-player objects.
所以,我需要使用 AssignClientAuthority
功能。我试过几次,但没有正确地使用它。这里是工作的C#脚本应用到播放器:
So, I needed to use the AssignClientAuthority
function. Which I had tried a couple of times, but wasn't using it correctly. Here is the functioning C# script to apply to the player:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Player_Paint : NetworkBehaviour {
private int range = 200;
[SerializeField] private Transform camTransform;
private RaycastHit hit;
[SyncVar] private Color objectColor;
[SyncVar] private GameObject objectID;
private NetworkIdentity objNetId;
void Update () {
// only do something if it is the local player doing it
// so if player 1 does something, it will only be done on player 1's computer
// but the networking scripts will make sure everyone else sees it
if (isLocalPlayer) {
CheckIfPainting ();
}
}
void CheckIfPainting(){
// yes, isLocalPlayer is redundant here, because that is already checked before this function is called
// if it's the local player and their mouse is down, then they are "painting"
if(isLocalPlayer && Input.GetMouseButtonDown(0)) {
// here is the actual "painting" code
// "paint" if the Raycast hits something in it's range
if (Physics.Raycast (camTransform.TransformPoint (0, 0, 0.5f), camTransform.forward, out hit, range)) {
objectID = GameObject.Find (hit.transform.name); // this gets the object that is hit
objectColor = new Color(Random.value, Random.value, Random.value, Random.value); // I select the color here before doing anything else
CmdPaint(objectID, objectColor); // carry out the "painting" command
}
}
}
[ClientRpc]
void RpcPaint(GameObject obj, Color col){
obj.GetComponent<Renderer>().material.color = col; // this is the line that actually makes the change in color happen
}
[Command]
void CmdPaint(GameObject obj, Color col) {
objNetId = obj.GetComponent<NetworkIdentity> (); // get the object's network ID
objNetId.AssignClientAuthority (connectionToClient); // assign authority to the player who is changing the color
RpcPaint (obj, col); // usse a Client RPC function to "paint" the object on all clients
objNetId.RemoveClientAuthority (connectionToClient); // remove the authority from the player who changed the color
}
}
玩家 !重要!要影响必须具有NetworkIdentity组分
各自的对象,必须将其设定为LocalPlayerAuthority 强>
因此,这脚本仅仅是变化随机颜色,但你应该能够改变实际的东西,这适用于你想网络与非玩家目标的材料或其他任何改变。 应该是最佳的一句话 - 我还没有与任何其他的功能还没有试过
So this script is just to change a random color, but you should be able to change the actual stuff to apply this to any change in the materials or anything else you want to network with a non-player object. "Should" being the optimal word - I haven't tried with any other functionality yet.
编辑 - 学习之用增加更多评论
EDIT - added more comments for learning purposes.
这篇关于如何同步在UNET / Unity5非玩家游戏物体属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!