Unity 5 Многопользовательские глюки столкновений
Я пытаюсь сделать простой мультиплеерный пример. Неважно, если я попробую это в 2d или в 3d, результат будет одинаковым. Я опишу это в 3D, это то, что я пробовал меньше всего. Я просто добавляю два цилиндра к сцене и шар. Я установил скрипт для контроллера игрока, чтобы каждый игрок мог управлять своим собственным игроком. Я добавил преобразование "Сеть", идентификатор сети установил для него локальные права воспроизведения для префаба "Плеер" и сделал все, что описано в нескольких уроках, которые я выделил.
Думает, работает как положено. На хозяине я могу столкнуться с мячом и другим игроком, после добавления подпрыгивающего материала мяч отскакивает от игрока, а также другой игрок, когда я достаточно сильно ударил его. (Я добавил буст на кнопку огня) Я не программировал столкновения, я просто позволил физическому движку сделать работу. Проблема на стороне клиента, там мяч ведёт себя как-то липко. Он не отскакивает от игрока, он глючит и ведет себя просто не правильно.
Я пробовал каждую комбинацию с детектированием столкновений - непрерывный - непрерывный, с интерполяцией или без или с экстраполяцией. Комбинация между игроком и мячом и игроком / игроком.
Я также пробовал разные комбинации с настройками сети, но ничего не помогает.
Я добавляю несколько скриншотов, чтобы вы лучше поняли, что я пытаюсь сделать, и мои настройки.
Вопросы следующие: способен ли механизм pyhics в сочетании с поддержкой сети делать то, что я хочу, или это лучший способ: запрограммировать pyhics ИЛИ перевести проигрыватель с клиента обратно на сервер и позволить ему просто удаленное управление с клиента, Я думаю о том, чтобы поймать ввод с клавиатуры и отправить его на сервер, выполнить движение и синхронизировать только графику. (Я надеюсь, что вы понимаете, о чем я)
Игрок
[РЕДАКТИРОВАТЬ] Я пробовал порог привязки от 5 до 100 в каждой комбинации между мячом и игроком. Твердое тело выглядит одинаково (кроме массы) на шаре. Масса шаров 0,5. Player - это сборный дом, поэтому каждый игрок имеет одинаковую физику. Я также играл с физикой игры, особенно с порогом отскока, но это не помогло.
Сценарий игрока:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class PlayerController : NetworkBehaviour
{
public float movmentForce = 75;
public float accelerationOnFire;
public GameObject ball;
public float fireRate = 0.5F;
private float nextFire = 0.0F;
private Rigidbody rbPlayer;
// Use this for initialization
void Start()
{
Vector3 pos;
Quaternion q;
pos.x = 0;
pos.y = 1;
pos.z = 10;
transform.position = pos;
rbPlayer = GetComponent<Rigidbody>();
ball = GameObject.FindGameObjectWithTag("Ball");
}
// Update is called once per frame
void Update()
{
if (!isLocalPlayer)
return;
float inputHorizontal = CrossPlatformInputManager.GetAxis("Horizontal");
float inputVertical = CrossPlatformInputManager.GetAxis("Vertical");
// float inputHorizontal = Input.GetAxis("Horizontal");
// float inputVertical = Input.GetAxis("Vertical");
if (inputHorizontal != 0)
{
rbPlayer.AddForce(Vector3.right * movmentForce * inputHorizontal, ForceMode.Force);
}
if (inputVertical != 0)
{
rbPlayer.AddForce(Vector3.forward * movmentForce * inputVertical, ForceMode.Force);
}
if (CrossPlatformInputManager.GetButton("Fire1") && Time.time > nextFire)
// if (Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
rbPlayer.AddForce(transform.forward * -accelerationOnFire, ForceMode.Force);
}
Vector3 pos = transform.position;
pos.y += 10;
Camera.main.transform.position = pos;
}
void FixedUpdate()
{
if (!isLocalPlayer)
return;
if (ball)
{
Vector3 dir = ball.transform.position - rbPlayer.transform.position;
float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
rbPlayer.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
rbPlayer.transform.Rotate(0, 180, 0);
}
else
{
ball = GameObject.FindGameObjectWithTag("Ball");
}
}
}
Ball Spawner
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class BallSpawn : NetworkBehaviour
{
public GameObject ballPrefab;
// Use this for initialization
public override void OnStartServer()
{
SpawnBall();
}
void SpawnBall()
{
GameObject myBall = Instantiate<GameObject>(ballPrefab);//, Vector2.zero, Quaternion.identity);
NetworkServer.Spawn(myBall);
myBall.tag = "Ball";
}
}
Физика игры
1 ответ
Насколько я понимаю, движения либо воспроизводятся только локально (когда нет активного компонента NetworkTransform), либо они синхронизируются с сервером, а затем с другими клиентами. Таким образом, физический движок не имеет прямого взаимодействия с сетевой системой, он только изменяет преобразованное / жесткое тело, которое затем синхронизируется с помощью NetworkTransform. Таким образом, то, что вы пытаетесь сделать, должно работать.
Чтобы ответить на ваш вопрос, я бы попробовал поиграться с настройками в NetworkTransform шара. У меня недавно была похожая проблема, и я решил ее с помощью следующих настроек:
Network Send Rate: 9
Transfrom Send Mode: Sync Rigidbody 3D
Movement Threshold: 0.001
Snap Threshold: 100
Interpolate Movement Factor: 1
Rotation Axis: XYZ (full 3D)
Interpolate Rotation Factor: 8
Compress Rotation: None
Sync Angular Velocity: No
Я предполагаю, что установка Snap Threshold
чтобы что-то выше, например, 100, должно решить вашу проблему.
Из документов:
Если обновление движения помещает объект дальше от его текущей позиции, чем это значение, он будет привязываться к позиции, а не двигаться плавно.