Hi,
I’m setting up a game using Netcode-for-GameObjects for the first time and I’m now running into an issue with throwing a grenade on the client-side.
Here is the code (I’ve included comments to explain how it works and where my issue arises)
// This is called by the animation event
public void LoadGrenade()
{
if (IsOwner)
{
LoadGrenadeServerRpc();
}
}
[ServerRpc(RequireOwnership = false)]
public void LoadGrenadeServerRpc()
{
LoadGrenadeClientRpc();
}
// I've set this up so the grenade is spawned and held locally while the player prepares to throw the Grenade
[ClientRpc]
public void LoadGrenadeClientRpc()
{
activeGrenade = Instantiate(currentGrenade, currentGrenadeTransform.position, currentGrenadeTransform.rotation);
// Transform follow is a basic script to align the transform to the hand without having to parent the Network Object
activeGrenade.GetComponent<transformFollow>().AcquireTarget(currentGrenadeTransform);
activeGrenade.GetComponent<transformFollow>().Follow();
activeGrenade.GetComponent<Rigidbody>().isKinematic = true;
activeGrenade.GetComponent<Rigidbody>().useGravity = false;
}
// This is called by another animation event where the grenade should leave the players hand
public void ThrowGrenade ()
{
if (IsOwner)
{
ThrowGrenadeServerRpc();
}
}
[ServerRpc(RequireOwnership = false)]
public void ThrowGrenadeServerRpc(ServerRpcParams serverRpcParams = default)
{
ulong senderID = serverRpcParams.Receive.SenderClientId;
activeGrenade.SpawnWithOwnership(senderID, true);
ThrowGrenadeClientRpc(senderID, activeGrenade.NetworkObjectId);
}
[ClientRpc]
public void ThrowGrenadeClientRpc(ulong sendingClientID, ulong ID)
{
// Removing the clients grenade
if (!IsServer)
{
Destroy(activeGrenade);
}
else
{
activeGrenade.GetComponent<transformFollow>().StopFollow();
}
// The client will use the grenade spawned by the host as the new prefab
if ( NetworkManager.Singleton.LocalClientId == sendingClientID)
{
activeGrenade = NetworkManager.SpawnManager.SpawnedObjects[ID];
StartCoroutine("ThrowGrenadeAction");
}
}
//This is where I'm running into issues. On the Host, the grenade is throwing with zero issues,
but, the client will throw and either have an ideal throw to where the character is facing or
it will go in an unintended direction from the hand. It appears to happen randomly.
public IEnumerator ThrowGrenadeAction ()
{
yield return new WaitForEndOfFrame();
activeGrenade.transform.position = currentGrenadeTransform.position;
activeGrenade.transform.rotation = currentGrenadeTransform.rotation;
Rigidbody rigidBody = activeGrenade.GetComponent<Rigidbody>();
rigidBody.useGravity = true;
rigidBody.isKinematic = false;
rigidBody.linearVelocity = new Vector3(0,0,0);
Vector3 forceToAdd = cam.transform.forward * grenadeForce + transform.up * grenadeUpForce;
rigidBody.AddForce(forceToAdd, ForceMode.Impulse);
if (grenadeSpin)
{
rigidBody.AddTorque(Vector3.up * grenadeSpinRPM);
}
activeGrenade.GetComponent<SmokeGrenade>().Thrown = true;
activeGrenade = null;
}
I’ve tried troubleshooting with various different ways and this is the latest where I’m still running into the same issue. There is a character controller as a potential collider but the grenade prefab has a layer that ignores the Players.
(Background information, the game only features 2 players in a 1v1 manner)