【发布时间】:2017-11-30 15:55:46
【问题描述】:
好吧,这让我很沮丧,因为我以前从未做过这种事情,我需要一个解决方案。
所以我的游戏是 2D 的,需要你与其他玩家对抗,以便在时间限制内尽可能多地收集地图中的资源。世界是通过在地图中的每个图块上用一个随机块实例化一个精灵来生成的,玩家通过挖掘他们的方式并根据他们挖掘的资源获得积分。这些块也被保存到一个公共的二维数组中。
我有一个名为 LevelGenerator 的脚本,它在玩家开始游戏时运行。在脚本中,块是随机选择的,然后通过实例化生成,然后由 NetworkServer.Spawn 生成。整个世代被称为[Command]
拥有关卡生成器脚本的游戏对象具有网络身份,既不是服务器,也不是本地玩家权限。
在播放器脚本中,我有一些代码可以将射线从播放器投射到鼠标位置,它工作正常,但是游戏对象的破坏被破坏了。当玩家按下鼠标左键并且光线投射击中一个块时,我销毁命中的对象,在块的二维数组中添加与块的点值相同数量的点,然后将该数组中的块设置为空。当主机破坏一个块时,客户端可以看到这种情况发生,但是当客户端破坏一个块时,客户端显然可以看到它正在破坏,但主机看不到来自该客户端的更改。这可能不相关,但是会抛出一个错误,说块数组为空,即使我是通过 findobjectoftype 直接找到 levelgenerator 的。然而,这不会发生在主机上。地图是相同的,所以 networkserver.spawn 正在工作,但我在同步块以及它们是否损坏时遇到问题。
这些块是预制的,并且都有一个未选中任何框的网络标识,以及一个网络发送速率为 0 的网络转换,因为它们在生成时没有移动。
所以是的,我想不通。任何帮助表示赞赏。谢谢。
关卡生成器:
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;
}
}
}
}
玩家:
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;
}
}
}
}
}
【问题讨论】:
-
您应该考虑在您的问题中添加代码。正如所写,这是模糊且难以消化的。
-
好的,我已经添加了代码,如果还有其他内容请告诉我