C# 统一-网络。主机可以';看不到客户端的更改
好吧,这让我很沮丧,因为我以前从未做过这种事情,我需要一个解决方案 所以我的游戏是2D的,包括你和另一个玩家对抗,在时间限制内收集尽可能多的地图资源。世界是通过在地图上的每个瓷砖上用一个随机块实例化一个精灵而生成的,玩家通过挖掘获得点数,这取决于他们挖掘的资源。块也会保存到公共二维阵列中 我有一个名为LevelGenerator的脚本,它在玩家开始游戏时运行。在脚本中,随机选择块,然后通过实例化生成,然后通过NetworkServer.Spawn生成。整个生成过程称为[命令] 持有levelgenerator脚本的游戏对象具有网络标识,既不具有服务器权限,也不具有本地玩家权限 在玩家脚本中,我有一些代码,可以将光线投射从玩家投射到鼠标位置,效果很好,但是破坏游戏对象的过程被破坏了。当玩家按下鼠标左键,光线投射命中一个块时,我销毁命中对象,在块的2D数组中添加与块的points值相同数量的点,然后将数组中的块设置为null。当主机断开一个块时,客户端可以看到这种情况发生,但当客户端断开一个块时,客户端显然可以看到它断开,但主机看不到来自该客户端的更改。这可能不相关,但会抛出一个错误,指出块数组为null,即使我通过findobjectoftype直接查找levelgenerator。但是,这不会发生在主机上。映射是相同的,因此networkserver.spawn正在工作,但我在同步块以及它们是否损坏方面遇到了问题 这些块都是预制块,并且所有块都具有网络标识(未选中任何一个复选框),以及网络发送速率为0的网络转换,因为它们在生成时不会移动 所以是的,我想不出来。感谢您的帮助。谢谢 液位发生器:C# 统一-网络。主机可以';看不到客户端的更改,c#,unity3d,C#,Unity3d,好吧,这让我很沮丧,因为我以前从未做过这种事情,我需要一个解决方案 所以我的游戏是2D的,包括你和另一个玩家对抗,在时间限制内收集尽可能多的地图资源。世界是通过在地图上的每个瓷砖上用一个随机块实例化一个精灵而生成的,玩家通过挖掘获得点数,这取决于他们挖掘的资源。块也会保存到公共二维阵列中 我有一个名为LevelGenerator的脚本,它在玩家开始游戏时运行。在脚本中,随机选择块,然后通过实例化生成,然后通过NetworkServer.Spawn生成。整个生成过程称为[命令] 持有levelge
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Networking;
public class LevelGenerator : NetworkBehaviour
{
[SerializeField] private List<Block> blocks; // Blocks are pre-defined in the Unity Editor.
[SerializeField] private int mapWidth; // How wide the map is.
[SerializeField] private int mapHeight; // How deep the map is.
public const int blockSize = 1;
public Block[,] blockMatrix; // 2D array of all blocks.
private List<Block> resourceBlocks = new List<Block>();
private List<GameObject> blockObjects = new List<GameObject>();
void Start()
{
CmdSpawnMap();
}
[Command]
public void CmdSpawnMap()
{
blockMatrix = new Block[mapWidth, mapHeight];
resourceBlocks = blocks.Where(z => z.blockType == "Resource").ToList(); // List of all the blocks that are tagged as resources.
resourceBlocks = resourceBlocks.OrderBy(z => z.rarity).ToList();
for (int r = 0; r < resourceBlocks.Count; r++)
{
resourceBlocks[r].spawnPercentagesAtLevels = new float[mapHeight];
for (int s = 1; s < resourceBlocks[r].spawnPercentagesAtLevels.Length; s++)
{
resourceBlocks[r].spawnPercentagesAtLevels[s] = resourceBlocks[r].basePercentage * Mathf.Pow(resourceBlocks[r].percentageMultiplier, resourceBlocks[r].spawnPercentagesAtLevels.Length - s);
}
}
// For every block in the map.
System.Random random = new System.Random();
for (int y = 0; y < mapHeight; y++)
{
for (int x = 0; x < mapWidth; x++)
{
if (y == mapHeight - 1)
{
Block grass = blocks.Where(z => z.blockName == "Grass").FirstOrDefault();
blockMatrix[x, y] = grass;
GameObject blockInstance = Instantiate(grass.blockPrefabs[random.Next(0, grass.blockPrefabs.Count - 1)]);
blockInstance.transform.position = new Vector3(x * blockSize, y * blockSize, 0);
blockInstance.transform.SetParent(transform, false);
blockInstance.name = blockMatrix[x, y].blockName + " => " + x + ", " + y;
blockObjects.Add(blockInstance);
NetworkServer.Spawn(blockInstance);
continue;
}
bool resourceSpawned = false;
for (int i = resourceBlocks.Count - 1; i >= 0; i--)
{
float roll = Random.Range(0.0f, 100.0f);
if (roll <= resourceBlocks[i].spawnPercentagesAtLevels[y])
{
blockMatrix[x, y] = resourceBlocks[i];
GameObject blockInstance = Instantiate(resourceBlocks[i].blockPrefabs[random.Next(0, resourceBlocks[i].blockPrefabs.Count - 1)]);
blockInstance.transform.position = new Vector3(x * blockSize, y * blockSize, 0);
blockInstance.transform.SetParent(transform, false);
blockInstance.name = blockMatrix[x, y].blockName + " => " + x + ", " + y;
blockObjects.Add(blockInstance);
resourceSpawned = true;
NetworkServer.Spawn(blockInstance);
break;
}
}
if (!resourceSpawned)
{
Block ground = blocks.Where(z => z.blockName == "Ground").FirstOrDefault();
blockMatrix[x, y] = ground;
GameObject blockInstance = Instantiate(ground.blockPrefabs[random.Next(0, ground.blockPrefabs.Count - 1)]);
blockInstance.transform.position = new Vector3(x * blockSize, y * blockSize, 0);
blockInstance.transform.SetParent(transform, false);
blockInstance.name = blockMatrix[x, y].blockName + " => " + x + ", " + y;
blockObjects.Add(blockInstance);
NetworkServer.Spawn(blockInstance);
}
resourceSpawned = false;
}
}
}
}
使用UnityEngine;
使用System.Collections.Generic;
使用System.Linq;
使用UnityEngine。联网;
公共类级别生成器:网络行为
{
[SerializeField]私有列表块;//块是在Unity编辑器中预定义的。
[SerializeField]私有int mapWidth;//映射的宽度。
[SerializeField]私有int mapHeight;//映射的深度。
public const int blockSize=1;
公共块[,]块矩阵;//所有块的2D数组。
私有列表resourceBlocks=新列表();
私有列表blockObjects=新列表();
void Start()
{
CmdSpawnMap();
}
[命令]
public void cmdmap()
{
blockMatrix=新块[mapWidth,mapHeight];
resourceBlocks=块。其中(z=>z.blockType==“Resource”).ToList();//标记为资源的所有块的列表。
resourceBlocks=resourceBlocks.OrderBy(z=>z.rarity.ToList();
for(int r=0;rz.blockName==“grass”).FirstOrDefault();
块矩阵[x,y]=草;
GameObject blockInstance=实例化(grass.blockprefables[random.Next(0,grass.blockprefables.Count-1)];
blockInstance.transform.position=新矢量3(x*块大小,y*块大小,0);
blockInstance.transform.SetParent(transform,false);
blockInstance.name=blockMatrix[x,y]。blockName+“=>”+x+“,“+y;
添加(blockInstance);
NetworkServer.Spawn(blockInstance);
继续;
}
bool resourceprowned=false;
对于(int i=resourceBlocks.Count-1;i>=0;i--)
{
浮动辊=随机范围(0.0f,100.0f);
如果(滚动z.blockName==“地面”).FirstOrDefault();
块矩阵[x,y]=地;
GameObject blockInstance=实例化(ground.blockprefables[random.Next(0,ground.blockprefables.Count-1)];
blockInstance.transform.position=新矢量3(x*块大小,y*块大小,0);
blockInstance.transform.SetParent(transform,false);
blockInstance.name=blockMatrix[x,y]。blockName+“=>”+x+“,“+y;
添加(blockInstance);
NetworkServer.Spawn(blockInstance);
}
resourceprowned=false;
}
}
}
}
玩家:
using UnityEngine;
using UnityEngine.Networking;
[RequireComponent(typeof(Rigidbody2D))]
public class Player : NetworkBehaviour
{
private Rigidbody2D rb;
[Header("Player Movement Settings")]
[SerializeField] private float moveSpeed;
private bool facingRight;
[HideInInspector] public int points;
void Start()
{
rb = GetComponent<Rigidbody2D>();
facingRight = true; // Start facing right
}
void FixedUpdate()
{
float horizontalSpeed = Input.GetAxis("Horizontal") * moveSpeed;
float jumpSpeed = 0;
if (horizontalSpeed > 0 && !facingRight || horizontalSpeed < 0 && facingRight) // If you were moving left and now have a right velocity
{ // or were moving right and now have a left velocity,
facingRight = !facingRight; // change your direction
Vector3 s = transform.localScale;
transform.localScale = new Vector3(s.x * -1, s.y, s.z); // Flip the player when the direction has been switched
}
rb.velocity = new Vector2(horizontalSpeed, jumpSpeed);
}
void Update()
{
GameManager gm = FindObjectOfType<GameManager>();
LevelGenerator levelGen = FindObjectOfType<LevelGenerator>();
if (gm.playing)
{
Camera playerCam = GetComponentInChildren<Camera>();
Vector3 direction = playerCam.ScreenToWorldPoint(Input.mousePosition) - transform.position;
direction.z = 0;
RaycastHit2D hit = Physics2D.Raycast(transform.position, direction, 1);
Debug.DrawRay(transform.position, direction, Color.red);
if (hit)
{
if (Input.GetButtonDown("BreakBlock"))
{
Destroy(hit.transform.gameObject);
points += levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)].blockPointsValue;
levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)] = null;
}
}
}
}
}
使用UnityEngine;
使用UnityEngine。联网;
[RequiredComponent(typeof(Rigidbody2D))]
公共类玩家:网络行为
{
私有刚体2d rb;
[标题(“玩家移动设置”)]
[SerializeField]专用浮点移动速度;
私人楼宇朝向权;
[HideInInstitt]公共整数点;
void Start()
{
rb=GetComponent();
facingRight=true;//开始向右
}
void FixedUpdate()
{
float horizontalSpeed=Input.GetAxis(“Horizont
if (hit)
{
if (Input.GetButtonDown("BreakBlock"))
{
CmdBreakBlock(hit.transform.gameObject);
points += levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)].blockPointsValue;
levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)] = null;
}
}
[Command]
void CmdBreakBlock(GameObject block)
{
NetworkServer.Destroy(block);
}
if (Input.GetButtonDown("BreakBlock")) // Ran on client
{
CmdBreakBlock(hit.transform.gameObject);
hit.transform.gameObject.SetActive(false); // Mimic that it was destroyed on the client so they don't try to mine it again.
}
//...
[Command]
void CmdBreakBlock(GameObject hit) // Ran on server, arguments from client
{
NetworkServer.Destroy(hit);
RpcAddPoints(levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)].blockPointsValue);
levelGen.blockMatrix[Mathf.FloorToInt(hit.transform.position.x), Mathf.FloorToInt(hit.transform.position.y)] = null;
}
[ClientRpc]
void RpcAddPoints(int p) // Ran on client, arguments from server
{
points += p;
}