unity3d - 在 Unity 中使用 Unet 更改 GameObjects 上的材质
问题描述
当我在任何客户端中单击它时,我想在所有客户端上更改游戏对象的材质。我是 UNET 的新手,我认为我有一个概念缺陷。所以基本上我想做的是:
- 在 NetworkPlayer 上向场景中的对象发射光线
[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 游戏的好教程,请告诉我。
解决方案
您的问题是您curColOfThisObject
在客户端计算值,但同时使用[SyncVar]
它。
来自[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);
}
}
}
请注意,您可能会击中孩子或父母,而不是您想要击中的实际对象.. 所以 evtl。您必须使用or查找RPC_ColorChange
子级或父级中的组件。GetComponentInChildren
GetComponentInParent
推荐阅读
- bash - 在执行期间使用 bash 将进程的输出重定向到自身作为输入
- opengl - 在 OpenGL 的片段着色器中使用 mtl 信息进行纹理映射
- c# - 在 C# 中使用 linq 更改 xml 值
- php - WP_Query 按 menu_order 而非标题排序
- javascript - Flask-SocketIO 未收到消息
- arrays - 红宝石中的对称数组
- global - is valid = false and and error = .... 一个局部变量或全局变量
- java - NullPointerException - 启动方法 javafx 中的 label.settext
- html - 自动重新定位溢出内容的 CSS 列
- python - 正则表达式查找所有字符串和介于两者之间的任何字符的链接