Projectile hit's target and gets destroyed, but sometimes doesn't do damage...

Hello, when I shoot my projectile on the host it always does damage, but sometimes on the client like 1 in 5 shots don’t do damage. Is this lag? Something wrong with networking physics? I know it’s nothing wrong with collision because my projectile gets destroyed when it hits something.

This is my health script.

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;

public class Health : NetworkBehaviour
{
    public Behaviour[] disableOnDie;
    public Renderer[] disableOnDieRen;
    public Behaviour[] disableLocal;

    public const int maxHealth = 100;

    [SyncVar(hook = "OnChangeHealth")]
    public int currentHealth = maxHealth;

    public RectTransform healthBar;

    void Start()
    {
        if(isLocalPlayer)
        {
            healthBar.gameObject.transform.parent.transform.parent.gameObject.SetActive(false);
        }
    }
    public override void OnStartClient()
    {
        OnChangeHealth(currentHealth);
    }
    public void TakeDamage(int amount,NetworkIdentity fromPlayer)
    {
        if (!isServer)
            return;

        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            currentHealth = maxHealth;
            RpcRespawnStart(fromPlayer);
            //RpcRespawn();
        }
    }

    void OnChangeHealth(int health)
    {
        healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
    }
    [ClientRpc]
    void RpcRespawnStart(NetworkIdentity fromPlayer)
    {
        foreach(Behaviour B in disableOnDie)
        {
            B.enabled = false;
        }
        foreach (Renderer R in disableOnDieRen)
        {
            R.enabled = false;
            GetComponent<PlayerShoot>().bowStringActual.GetComponentInChildren<Renderer>().enabled = false;
        }
        if (isLocalPlayer)
        {
            foreach (Behaviour LB in disableLocal)
            {
                LB.enabled = false;
            }
        }
        if (isLocalPlayer)
        {
            transform.FindChild("Main Camera").gameObject.SetActive(false);
            if (isClient)
            {
                ClientScene.FindLocalObject(fromPlayer.netId).gameObject.transform.FindChild("Spectator Camera").gameObject.SetActive(true);
            }
            if(isServer)
            {
                NetworkServer.FindLocalObject(fromPlayer.netId).gameObject.transform.FindChild("Spectator Camera").gameObject.SetActive(true);
            }
        }
        if (isServer)
        {
            StartCoroutine(RespawnDelay(fromPlayer));
        }
       
    }
    IEnumerator RespawnDelay(NetworkIdentity fromPlayer)
    {
        yield return new WaitForSeconds(5);

        RpcRespawn(fromPlayer);
    }
    [ClientRpc]
    void RpcRespawn(NetworkIdentity fromPlayer_)
    {
        foreach (Behaviour B in disableOnDie)
        {
            B.enabled = true;
        }
        foreach (Renderer R in disableOnDieRen)
        {
            GetComponent<PlayerShoot>().bowStringActual.GetComponentInChildren<Renderer>().enabled = true;
            R.enabled = true;
        }
        if (isLocalPlayer)
        {
            foreach (Behaviour LB in disableLocal)
            {
                LB.enabled = true;
            }
        }
        if (isLocalPlayer)
        {
            transform.FindChild("Main Camera").gameObject.SetActive(true);

            if (isClient)
            {
                ClientScene.FindLocalObject(fromPlayer_.netId).gameObject.transform.FindChild("Spectator Camera").gameObject.SetActive(false);
            }
            if (isServer)
            {
                NetworkServer.FindLocalObject(fromPlayer_.netId).gameObject.transform.FindChild("Spectator Camera").gameObject.SetActive(false);
            }
            transform.position = Vector3.zero;
        }
    }
}

This is my projectile script (On the projectile)

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Projectile : MonoBehaviour
{

    public NetworkIdentity fromPlayer;

    void OnCollisionEnter(Collision collision)
    {
        var hit = collision.gameObject;
        var health = hit.GetComponent<Health>();
        if (health != null)
        {
            health.TakeDamage(35,fromPlayer);

        }
        Destroy(gameObject);
    }
}

And this is my arrow script(also on the projectile)

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Arrow : NetworkBehaviour {

    [SyncVar(hook = "OnParentChange")]
    public Transform parent;
    public bool isRealArrow = false;
    Rigidbody rb;
    public float y;
    public float x;
    TrailRenderer t_Ren;

    void OnParentChange(Transform parent_)
    {
        parent = parent_;
        if (!isRealArrow)
        {
            transform.parent = parent_.GetComponent<PlayerShoot>().bowStringActual;
            transform.localEulerAngles = new Vector3(3.4254f, 89.8375f, -1.069127e-07F);
            transform.localPosition = new Vector3(2.670019f, -0.1708062f, 0.0190545f);
        }
        else
        {
            //Physics.IgnoreCollision(GetComponent<Collider>(), parent.GetComponent<Collider>(), true);
        }
    }
    void Awake()
    {
        if (isRealArrow)
        {
            t_Ren = GetComponentInChildren<TrailRenderer>();
            rb = GetComponent<Rigidbody>();
        }
    }
    void Start()
    {
     
        if(parent != null && transform.parent == null)
        {
            if (!isRealArrow)
            {
                transform.parent = parent.GetComponent<PlayerShoot>().bowStringActual;
                transform.localEulerAngles = new Vector3(3.4254f, 89.8375f, -1.069127e-07F);
                transform.localPosition = new Vector3(2.670019f, -0.1708062f, 0.0190545f);
            }
            else
            {
                //Physics.IgnoreCollision(GetComponent<Collider>(), parent.GetComponent<Collider>(), true);
                transform.position = parent.GetComponent<PlayerShoot>().bowString.transform.position;
                transform.rotation = parent.GetComponent<PlayerShoot>().bowString.transform.rotation;
                GetComponent<Projectile>().fromPlayer = parent.GetComponent<NetworkIdentity>();
                Invoke("ChangePOS", 0.02F);

            }
        }
    }

    void ChangePOS()
    {
        transform.parent = parent.transform.Find("Main Camera");
        transform.localPosition = new Vector3(0, 0, transform.localPosition.z);
        transform.localEulerAngles = Vector3.zero;
        transform.parent = null;

        rb.velocity = transform.TransformDirection(0, 0, 70);
        //t_Ren.enabled = true;
        t_Ren.Clear();
    }

}

I found that it was because the interpolate rotation was set too low, so even though it got destroyed on the client it hadn’t actually hit on the host, because the rotation of the camera(and in turn the bow) was lagging behind what it was on the client. I’ll see if I can fix it.

Hmmmm… How would I spawn a projectile at the firePOS, so that is exactly at the firePOS on the client who shot the projectile, becuase the firePOS on the server laggs behind a bit, making the projectile be a bit behind where I actually shot.

Finally got it fixed :slight_smile:

1 Like