Reputation: 13
I'm creating a simple 3D online shooter. I encountered a problem that when the host fires a bullet, the bullet flies correctly and is displayed. But if the client connects... When he shoots, he does not see the bullet. But the host can see from his screen how the bullet flies by. Also my bullet has collision. When you shoot at a player's object, it moves slightly to the side. So, when you shoot from the host, you can see why the other player moved. And when you shoot from the client and the bullet hits another player, he just moves jerkily.
I saw a lot of problems on the forums when the host (server) does not display a bullet. But when it’s the other way around, I haven’t found anything like this anywhere.
This is my code to manage weapon:
using UnityEngine;
using Mirror;
public class WeaponManager : NetworkBehaviour
{
private Transform weaponTransform;
private Vector3 weaponInitialPosition = new Vector3(0.45f, -0.397f, 0.036f);
private Vector3 weaponTargetPosition = new Vector3(0f, -0.39f, 0.036f);
private float moveSpeed = 10f;
public GameObject bulletPrefab;
public Transform bulletSpawnPoint;
private float bulletSpeed = 20f;
private Camera playerCamera;
private float shootCooldown = 2f;
private float lastShootTime;
void Start()
{
weaponTransform = transform.Find("Weapon");
if (weaponTransform != null)
weaponTransform.localPosition = weaponInitialPosition;
lastShootTime = -shootCooldown;
if (isLocalPlayer)
{
NetworkClient.Ready();
playerCamera = GetComponentInChildren<Camera>();
}
}
void Update()
{
if (!isLocalPlayer) return;
if (weaponTransform != null)
{
if (Input.GetMouseButton(1))
{
weaponTransform.localPosition = Vector3.Lerp(
weaponTransform.localPosition,
weaponTargetPosition,
Time.deltaTime * moveSpeed
);
}
else
{
weaponTransform.localPosition = Vector3.Lerp(
weaponTransform.localPosition,
weaponInitialPosition,
Time.deltaTime * moveSpeed
);
}
}
if (Input.GetMouseButtonDown(0) && Time.time >= lastShootTime + shootCooldown)
{
lastShootTime = Time.time;
Vector3 shootDirection = playerCamera.transform.forward;
CmdShoot(shootDirection);
}
}
[Command]
void CmdShoot(Vector3 direction)
{
GameObject bullet = Instantiate(bulletPrefab, bulletSpawnPoint.position, bulletSpawnPoint.rotation);
Bullet bulletScript = bullet.GetComponent<Bullet>();
bulletScript.Initialize(direction, bulletSpeed);
NetworkServer.Spawn(bullet);
}
}
And code for bullet:
using Mirror;
using UnityEngine;
public class Bullet : MonoBehaviour
{
private Vector3 direction;
private float speed;
private float lifetime = 5f;
[Server]
public void Initialize(Vector3 dir, float spd)
{
direction = dir;
speed = spd;
Destroy(gameObject, lifetime);
}
[ServerCallback]
void Update()
{
transform.position += direction * speed * Time.deltaTime;
}
// Метод для обработки столкновений
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
return;
Destroy(gameObject);
}
}
Upvotes: 0
Views: 36
Reputation: 610
Makes sense because Command is used to run something on the server.
I think the problem might be with CmdShoot
Also note that your Bullet is a MonoBehaviour
[Command]
void CmdShoot(Vector3 direction)
{
GameObject bullet = Instantiate(bulletPrefab, bulletSpawnPoint.position, bulletSpawnPoint.rotation);
Bullet bulletScript = bullet.GetComponent<Bullet>();
bulletScript.Initialize(direction, bulletSpeed);
NetworkServer.Spawn(bullet);
}
From docs:
[Command] Call this from a client to run this function on the server. Make sure to validate input etc. It's not possible to call this from a server. Use this as a wrapper around another function, if you want to call it from the server too. See also Remote Actions and Data Types.
[ClientRpc] The server uses a Remote Procedure Call (RPC) to run that function on clients. See also: Remote Actions.
Upvotes: 0