我尝试制作一个简单的多人游戏示例。如果我在2d或3d中尝试它并不重要,结果是相同的。我将在3D中描述它,这是我尝试过的最少。我简单地将两个圆柱体添加到场景和球中。我为播放器控制器设置了一个脚本,这样每个播放器都可以控制自己的播放器。我添加了网络转换,网络ID将其设置为播放器预制件的本地播放权限,并在我的红色的几个教程中做了所有描述。
认为正在按预期工作。在主持人身上我可以与球和另一个球员发生碰撞,在添加了一个弹跳材料之后,球会从玩家身上弹回来,而另一个玩家也会这样做,当我足够打他的时候。 (我在fire按钮上添加了一个提升)我没有对碰撞进行编程,我只是让物理引擎完成工作。问题出现在客户端,Ball表现出某种粘性。它没有反弹播放器它是毛病,并且行为不正确。
我尝试了每种组合的碰撞检测离散 - 连续 - 连续动态,插值或无插补或外插。球员与球和球员/球员之间的结合。
我也尝试过与网络设置的不同组合,但没有任何帮助。
我添加了一些屏幕截图,因此您可以更好地理解我尝试做的事情以及我的设置。
问题是:pyhics引擎是否与网络能够结合,能够做我想要的,或者是更好的方法:编程pyhics或将Player从客户端放回服务器并让他只需远程控制来自客户。我想从键盘上捕获输入并将其发送到服务器并在那里进行移动并仅同步图形。 (我希望,你明白我的意思)
Player Rigidbody
[编辑] 我在球和球员之间的每个组合中尝试了5到100的快照阈值。 Rigidbody在球上看起来相同(质量除外)。球质量为0.5。播放器是预制件,因此每个播放器都具有相同的物理特性。 我也玩游戏物理特别是反弹阈值,但它没有帮助。
播放器脚本:
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";
}
}
游戏物理
答案 0 :(得分:0)
根据我的理解,移动要么只在本地播放(当没有活动的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,可以解决您的问题。
来自文档:
如果移动更新将对象从其当前位置进一步放置该值,则它将捕捉到该位置而不是平滑移动。