简体   繁体   English

Unity3D。 如何在多人射击游戏中正确处理弹丸?

[英]Unity3D. How to properly handle projectile in a multiplayer shooter?

So I tried adding physical projectiles/bullets with speed and gravity to a simple first person shooter instead of just Raycasting and and using a Command if the client hits something. 因此,我尝试将具有速度和重力的物理弹丸/子弹添加到一个简单的第一人称射击游戏中,而不是仅进行射线投射,如果客户碰到东西,则使用Command。 After a bit of trial and error I figured out that using a projectile with a collider isn't the best way of doing things as the physics aren't calculated fast enough for fast moving objects. 经过一番尝试和错误之后,我发现将弹丸与对撞机配合使用并不是最佳的处理方法,因为对于快速移动的物体,其物理计算速度不够快。 So I mad my own bullet physics as shown below. 所以我疯了自己的子弹物理学,如下所示。

 private float startingVelocity = 50f;
 private float gravity = 9.81f;

 private Vector3 forwardDirection;

 private Vector3 previousPosition;
 private Vector3 nextPosition;

 private Vector3 movementDirection;

 private Vector3 velocity;

 void Start ()
 {
   previousPosition = transform.position;
   forwardDirection = transform.forward.normalized;
   velocity = forwardDirection*startingVelocity;
 }
 void Update ()
 {
   previousPosition = transform.position;
   velocity += new Vector3(0f, -1f, 0f)*gravity*Time.deltaTime;

   nextPosition = previousPosition + velocity*Time.deltaTime;

   transform.position = nextPosition;

   Debug.DrawLine(previousPosition, nextPosition, Color.white, 10f);

   movementDirection = nextPosition - previousPosition;
   if (movementDirection!=Vector3.zero) 
   { 
     transform.rotation = Quaternion.LookRotation(movementDirection); 
   }

   CheckImpact(previousPosition, nextPosition);
 }

The CheckImpact function essentially just raycasts between the two positions to check if there is a wall or player in the way the projectile should hit. CheckImpact函数实际上只是在两个位置之间进行射线广播,以检查弹丸撞击的方式是否存在墙壁或玩家。 When hitting something, a Command is called and damage is done to the target by the server. 当击中某物时,将调用命令,服务器会对目标造成伤害。

The bullet itself is spawned like this: 子弹本身是这样生成的:

[Command]
void CmdShootProjectile(string projectilePath, Vector3 _position, Quaternion _rotation)
{
    GameObject projectile = Instantiate(Resources.Load<GameObject>(projectilePath), _position, _rotation);
    NetworkServer.Spawn(projectile);

The Client shoots, a Command spawns the bullet on the server and the bullet is then spawned for every client so it can be seen. 客户端射击,命令在服务器上生成项目符号,然后为每个客户端生成项目符号,以便可以看到它。 The problem I am having with this method is that the server calculates whether or not a bullet hits and this doesn't always line up with how it looks like for the player. 我在使用此方法时遇到的问题是,服务器会计算子弹是否被击中,而这并不总是与播放器的外观保持一致。

How could I efficiently and reliably handle my projectiles? 我如何有效,可靠地处理弹丸? Could I somehow make the client who is actually shooting do the calculating of the bullet and checking if it hits while other clients still being able to see the bullet? 我能以某种方式让实际射击的客户计算子弹并检查它是否命中,而其他客户仍然能够看到子弹吗?

Thanks in advance. 提前致谢。

Unfortunately, it's virtually impossible to have a 100% safe and reliable way of doing this. 不幸的是,几乎不可能有100%安全可靠的方法来做到这一点。 There is, however, quite a bit of research into this (by game companies such as Valve - for Counter Strike - and others). 但是,对此有相当多的研究(例如Valve公司(《反恐精英》)等游戏公司)。

The current consensus is to indeed have the calculations in the server-side, not on client-side. 当前的共识是确实在服务器端而不是在客户端进行计算。 There pros and cons. 有利弊。

Pros: 优点:

  • Safer against cheaters: if the client is making the decision "has my bullet hit", it's easy for an adulterated client (or similar) to fake a hit. 更安全地防止作弊:如果客户做出“受到我的子弹击中”的决定,则掺假的客户(或类似人)很容易伪造打击。
  • More fair when considering players with different latencies: if a player has high latency (50ms +), it can get quite easy to shoot at enemies and register hits. 在考虑具有不同延迟的玩家时更公平:如果玩家具有较高的延迟(50ms +),则可以很容易地向敌人射击并记录命中率。

Cons: 缺点:

  • Sometimes, the hits don't match up. 有时,点击次数不匹配。 This has been a topic if debate for years in eSports, specially for Counter Strike, where players complain that their hits didn't "hit". 如果在电子竞技领域辩论多年,尤其是在《反恐精英》中,玩家会抱怨他们的歌曲没有被“点击”,这就是一个话题。 Such is life. 这就是生活。
  • Depending on logic, it can get pretty heavy for the server, which can get expensive. 根据逻辑的不同,服务器可能会变得很沉重,这可能会变得昂贵。

Personally, I like your approach, and it should be fine for now. 就个人而言,我喜欢您的方法,现在应该还可以。 As your game progresses, and the need comes for a better system, then you can change it. 随着游戏的进展,以及对更好的系统的需求,您可以对其进行更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM