我想在所有客户端上单击GameObject时在所有客户端上更改其材质。我是UNET的新手,我认为我在概念上存在缺陷。所以基本上我想做的是:
[Command]
[Command]
中,调用对象上的[ClientRpc]
[ClientRpc]
中更改该对象的材料我的播放器:
using UnityEngine;
using UnityEngine.Networking;
// This script is on my Game Player Prefab
// (removed the cam movement part)
public class CamMovement : NetworkBehaviour
{
void Update()
{
if (!isLocalPlayer)
{
return;
}
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
CmdNextColor(hit.transform.gameObject);
}
}
[Command]
public void CmdNextColor(GameObject hitObject)
{
RPC_ColorChange colorChange = hitObject.GetComponent<RPC_ColorChange>();
if (colorChange != null)
{
colorChange.RpcNextColor();
}
}
}
我的对象
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class RPC_ColorChange : NetworkBehaviour {
public Material[] material;
[SyncVar]
int curColOfThisObject;
Text text;
private void Start()
{
text = GetComponentInChildren<Text>();
}
[ClientRpc]
public void RpcNextColor()
{
if (!isClient)
return;
if (material.Length > 0)
{
Material curMaterial = this.GetComponent<MeshRenderer>().material;
curColOfThisObject++;
if (curColOfThisObject >= material.Length)
curColOfThisObject = 0;
curMaterial = material[curColOfThisObject];
}
}
private void Update()
{
if (isClient)
{
text.text = "new color of this object: " + curColOfThisObject.ToString();
}
}
}
会发生什么: 对象上的文本将更改为适当的颜色,但是材质永远不会更改。如何更改材料?
奖金问题: 如果有人知道如何设计UNET游戏的好教程,请告诉我。
答案 0 :(得分:0)
您的问题是您在客户端计算了curColOfThisObject
的值,但同时使用了[SyncVar]
。
这些变量的值将从服务器同步到客户端
->不要在RpcNextColor
中更改在客户端上的值,而是已经在CmdNextColor
中更改在服务器上。否则curColOfThisObject
将立即被服务器上从未更改的默认值覆盖。我将把值作为[ClientRpc]
中的参数传递给客户端,因此从技术上讲,您甚至根本不需要[SyncVar]
。
在CamMovement
[Command]
public void CmdNextColor(GameObject hitObject)
{
RPC_ColorChange colorChange = hitObject.GetComponent<RPC_ColorChange>();
if (colorChange != null)
{
colorChange.NextColor();
// after calculating a new curColOfThisObject send it to clients (doesn't require [SyncVar] anymore)
colorChange.RpcNextColor(curColOfThisObject);
}
}
在RPC_ColorChange
// Make the calculation of the value on the server side
[Server]
private void NextColor()
{
if (material.Length > 0)
{
Material curMaterial = this.GetComponent<MeshRenderer>().material;
curColOfThisObject++;
if (curColOfThisObject >= material.Length)
curColOfThisObject = 0;
// set the material also on the server
curMaterial = material[curColOfThisObject];
}
}
[ClientRpc]
public void RpcNextColor(int newValue)
{
if (!isClient) return;
// easier to debug if you keep the curColOfThisObject variable
curColOfThisObject = newValue;
if(newValue=> material.Length)
{
Debug.LogError("index not found in material");
return;
}
// instead of curColOfThisObject you could also just use the newValue
// but this is easier to debug
curMaterial = material[curColOfThisObject];
}
如果您想坚持使用[SyncVar]
,也可以完全跳过ClientRpc
,而将hook
设为[SyncVar]
,
在CamMovement
[Command]
public void CmdNextColor(GameObject hitObject)
{
RPC_ColorChange colorChange = hitObject.GetComponent<RPC_ColorChange>();
if (colorChange != null)
{
colorChange.NextColor();
}
}
在RPC_ColorChange
[SyncVar(hook = "OnNextColor")]
private int curColOfThisObject;
// Make the calculation of the value on the server side
[Server]
private void NextColor()
{
if (material.Length > 0)
{
Material curMaterial = this.GetComponent<MeshRenderer>().material;
curColOfThisObject++;
if (curColOfThisObject >= material.Length)
curColOfThisObject = 0;
// set the material also on the server
curMaterial = material[curColOfThisObject];
}
}
// This method automatically gets called when the value of
// curColOfObject is changed to newValue on the server
private void OnNextColor(int newValue)
{
if (!isClient) return;
// easier to debug if you keep the curColOfThisObject variable
curColOfThisObject = newValue;
if(newValue=> material.Length)
{
Debug.LogError("index not found in material");
return;
}
// instead of curColOfThisObject you could also just use the newValue
// but this is easier to debug
curMaterial = material[curColOfThisObject];
}
一点点额外的东西:在通过网络发送内容之前,我会先检查RPC_ColorChange
组件的存在。
if (Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if(hit.GetComponent<RPC_ColorChange>()!=null)
{
CmdNextColor(hit.transform.gameObject);
}
}
}
请注意,您可能击中了孩子或父母,而不是您想击中的实际物体。您将必须使用RPC_ColorChange
或GetComponentInChildren
在子代或父代中寻找GetComponentInParent
组件。
答案 1 :(得分:0)
在处理Command函数之后调用RpcFunctions是有点反常理的:
在播放器预制板上:
[Command]
public void CmdNextColor(GameObject hitObject)
{
RPC_ColorChange colorChange = hitObject.GetComponent<RPC_ColorChange>();
if (colorChange != null)
{
int curColor = colorChange.GetCurColor();
// change color +1 on the clients
colorChange.RpcNextColor(curColor);
// assign a SyncVar with the current color
colorChange.SyncColorVar();
}
}
现在按以下顺序调用函数:
1)SyncColorVar()
2)RpcNextColor()