これは以前私がこの種のことをやったことがないので、これは私にとってイライラしています。ユニティ - ネットワーキング。ホストはクライアントの変更を見ることができません
私のゲームは2Dであり、限られた時間内にできるだけ多くのリソースを地図上で収集することになります。世界は、ランダムブロックで地図のすべてのタイルにスプライトをインスタンス化することによって生成され、プレイヤーは自分の道を掘り起こし、彼らが採掘する資源に応じてポイントを取得します。ブロックは、パブリック2D配列にも保存されます。
私はLevelGeneratorというスクリプトがあります。このスクリプトは、プレイヤーがゲームを開始したときに実行されます。スクリプトでは、ブロックがランダムに選択され、次にインスタンス化され、NetworkServer.Spawnによって生成されます。世代全体が[コマンド]
と呼ばれます。levelgeneratorスクリプトを保持するgameオブジェクトには、サーバーのみまたはローカルプレーヤー権限のないネットワークIDがあります。
プレイヤースクリプト内に、プレイヤーからマウスの位置にレイキャストをキャストするコードがありますが、ゲームオブジェクトの破損が壊れています。プレーヤーが左マウスを押してレイキャストがブロックに当たったとき、ヒットしたオブジェクトを破棄し、ブロックの2D配列のブロックのポイント値と同じ量のポイントを追加してから、そのブロックをnullに設定します。ホストがブロックを切断すると、クライアントはそのことを知ることができますが、クライアントがブロックを切断すると、クライアントは明らかにブロックを破損しているように見えますが、ホストはそのクライアントからの変更を見ることができません。これは関連しないかもしれませんが、findobjectoftypeでレベル生成器を直接探していても、ブロックの配列がnullであるというエラーがスローされます。しかし、これはホスト上では起こりません。マップは同じですので、networkserver.spawnは機能していますが、ブロックの同期や壊れているかどうかに問題があります。
ブロックはプレファブであり、ボックスはチェックされておらず、送信されたときから移動していないため、ネットワークの送信レートが0のネットワーク変換もありません。
だから私はこれを理解できません。どんな助けもありがとうございます。ありがとう。
LevelGenerator:
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;
}
}
}
}
}
質問にコードを追加することを検討する必要があります。これはあいまいで消化困難です。 – Jerdak
私はコードが追加されている場合は、私に何か他のものがあることをお知らせしました –