我尝试制作一个简单的多人游戏示例。如果我在 2d 或 3d 中尝试它并不重要,结果是相同的。我将用 3D 来描述它,这是我至少尝试过的。我简单地将两个圆柱体添加到一个场景和一个球中。我为 Player Controller 设置了一个脚本,这样每个 Player 都可以控制自己的 Player。我添加了网络转换,网络 ID 将其设置为 Player 预制的本地播放权限,并完成了我红色的几个教程中描述的所有内容。
想法按预期工作。在主机上,我可以与 Ball 和其他 Player 发生碰撞,添加弹跳材料后,当我用力击中他时,球会从 Player 和其他 Player 身上弹开。(我在点火按钮上添加了一个提升)我没有对碰撞进行编程,我只是让物理引擎完成工作。问题出在客户端,那里的球表现出某种粘性。它不会反弹播放器,它会出现故障并且行为方式不正确。
我尝试了碰撞检测 Descrete - Continuous - Continuous Dynmics 的每一种组合,包括插值或不插值或外插。球员和球以及球员/球员之间的组合。
我还尝试了与网络设置的不同组合,但没有任何帮助。
我添加了一些屏幕截图,以便您更好地了解我尝试做的事情和我的设置。
问题是:pyhics 引擎与网络相结合是否能够做我想做的事,或者是更好的方法:对 pyhics 进行编程或将播放器从客户端放回服务器,让他从客户端远程控制. 我想从键盘捕获输入并将其发送到服务器并在那里进行移动并仅同步回图形。(我希望你明白我的意思)
玩家刚体
[编辑] 我在球和球员之间的每个组合中尝试了从 5 到 100 的捕捉阈值。刚体在球上看起来相同(质量除外)。球质量为 0,5。Player 是一个预制件,因此每个 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");
}
}
}
球生成器
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";
}
}
游戏物理