was really hoping someone can be good enough to look over my code, I've been trying to fix it for several days. I followed the Unity tutorial which is fairly basic but the bit that confuses me (and potentially where the problem lies) is the:
if (!server){return;}
part at the top of my TakeDamage() function.
The problem im seeing is that once I get to that part of the tutorial, the bullet fired by the Host is registered against the other player and I can see his health has gone down (great so far!) , but when I load the instance in the editor (i did running another standalone on my laptop and connect to internet matchmaking but the same thing occurs) his bullets are not registered (even though my debug log tells me the Ray did hit the player.
The tutorial tells me to make it return if not server, it then uses [SyncVar] and a hook that is supposed to call the method "OnChangeHealth" whenever currentHealth is changed. This DOES NOT appear to be happening, and the TakeDamage code is only happening on the Server-Client-Host instance.
I was trying to adapt the tutorial to my own game, so there are some slight differences in the function and class names, but to me it looks to be exactly the same functionality-wise. I will have to just post my full code here as I don't know which part is causing the issue:
(MANY THANKS FOR READING AND/OR HELPING):
the Player class:
public class Player : NetworkBehaviour {
private GameObject startScreen;
public const int maxHealth = 100;
[SyncVar(hook = "OnChangeHealth")]
public int currentHealth = maxHealth;
private float playerHeight;
private AudioSource audioSource;
public AudioClip painBodySound;
public AudioClip painHeadSound;
public AudioClip painHeadSound2;
public RectTransform healthBar;
void Start () {
startScreen = GameObject.FindGameObjectWithTag("StartScreen");
if (startScreen != null)
{
startScreen.SetActive(false);
}
playerHeight = GetComponent<Collider>().bounds.size.y;
currentHealth = maxHealth;
audioSource = GetComponent<AudioSource>();
}
void Update () {
if (!isLocalPlayer)
{
return;
}
if (Input.GetKey(KeyCode.LeftControl))
{
transform.localScale = new Vector3(1, 0.5f, 1);
}
else
{
transform.localScale = new Vector3(1, 1f, 1);
}
}
public void TakeDamage(Vector3 hitPoint, int bulletDamage)
{
// check that its Server so that damage only gets applied on the server
if (!isServer)
{
return;
}
currentHealth -= bulletDamage;
audioSource.PlayOneShot(painBodySound);
if (currentHealth <= 0)
{
currentHealth = 0;
Debug.Log("Dead!");
}
}
private void OnChangeHealth(int health)
{
healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
}
}
Inside the bullet class is this function:
private void CastBulletRay()
{
ray = new Ray(bulletSpawnPos, bulletSpawnDirection);
if (Physics.Raycast(ray, out hit, bulletRayDistance))
{
if (hit.collider.tag == "Baddie")
{
Debug.Log("ray has hit a baddie");
Destroy(gameObject);
}
if (hit.collider.tag == "Player")
{
Debug.Log("ray has hit a player");
hit.collider.gameObject.GetComponent<Player>().TakeDamage(hit.point, bulletDamage);
Destroy(gameObject);
}
}
}
and inside The Unity RigidBodyController class I'm using, I added:
[Command]
void CmdFireBullets()
{
muzzleFlashObject.SetActive(true);
audioSource.PlayOneShot(gunFireSound, 0.2f);
//Create a new bullet
GameObject newBullet = Instantiate(bulletPrefab, bulletSpawnPoint.transform.position, bulletSpawnPoint.transform.rotation) as GameObject;
//Spawn the bullet on the clients:
NetworkServer.Spawn(newBullet);
}
}